mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
[FIX] move all unported addons into __unported__ folder instead of adding _unported suffix
This commit is contained in:
committed by
Pedro M. Baeza
parent
42a4171121
commit
3e36773432
@@ -1,30 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import mail
|
||||
from . import run
|
||||
from . import line
|
||||
from . import account
|
||||
from . import partner
|
||||
from . import policy
|
||||
from . import company
|
||||
from . import wizard
|
||||
from . import report
|
||||
from . import invoice
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
|
||||
class AccountAccount(orm.Model):
|
||||
"""Add a link to a credit control policy on account.account"""
|
||||
|
||||
_inherit = "account.account"
|
||||
|
||||
_columns = {
|
||||
'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):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default['credit_control_line_ids'] = False
|
||||
return super(AccountAccount, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
@@ -1,33 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<act_window
|
||||
id="act_account_credit_relation_relation"
|
||||
name="Credit Lines"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_user"
|
||||
domain="[('account_id', '=', active_id)]"
|
||||
res_model="credit.control.line"
|
||||
src_model="account.account"/>
|
||||
|
||||
<record id="invoice_followup_form_view" model="ir.ui.view">
|
||||
<field name="name">invoice.followup.form.view</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form" />
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Credit Control"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_user,account_credit_control.group_account_credit_control_info">
|
||||
<label string="Force credit control policy:" />
|
||||
<field name="credit_policy_id" widget="selection"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_user,account_credit_control.group_account_credit_control_info"/>
|
||||
<newline/>
|
||||
<field name="credit_control_line_ids" colspan="4" nolabel="1"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_user,account_credit_control.group_account_credit_control_info"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,38 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
|
||||
class ResCompany(orm.Model):
|
||||
"""Add credit control parameters"""
|
||||
_inherit = 'res.company'
|
||||
|
||||
_columns = {'credit_control_tolerance': fields.float('Credit Control Tolerance'),
|
||||
# This is not a property on the partner because we cannot search
|
||||
# on fields.property (subclass fields.function).
|
||||
'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 overridden"
|
||||
" on partners or invoices.")),
|
||||
}
|
||||
|
||||
_defaults = {"credit_control_tolerance": 0.1}
|
||||
@@ -1,16 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="credit_control_company_form" model="ir.ui.view">
|
||||
<field name="name">credit.control.company.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="currency_id" position="after">
|
||||
<field name="credit_policy_id" widget="selection"/>
|
||||
<field name="credit_control_tolerance"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,33 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="a_recv_1" model="account.account">
|
||||
<field name="code">X11002-a</field>
|
||||
<field name="name">B2B Debtors - (test)</field>
|
||||
<field ref="account.cas" name="parent_id"/>
|
||||
<field name="type">receivable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="credit_policy_id" ref="credit_control_no_follow"/>
|
||||
<field name="user_type" ref="account.data_account_type_receivable"/>
|
||||
</record>
|
||||
|
||||
<record id="a_recv_2" model="account.account">
|
||||
<field name="code">X11002-b</field>
|
||||
<field name="name">B2C Debtors - (test)</field>
|
||||
<field ref="account.cas" name="parent_id"/>
|
||||
<field name="type">receivable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="credit_policy_id" ref="credit_control_2_time"/>
|
||||
<field name="user_type" ref="account.data_account_type_receivable"/>
|
||||
</record>
|
||||
|
||||
<record id="a_recv_3" model="account.account">
|
||||
<field name="code">X11002-c</field>
|
||||
<field name="name">New Debtors - (test)</field>
|
||||
<field ref="account.cas" name="parent_id"/>
|
||||
<field name="type">receivable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="credit_policy_id" ref="credit_control_3_time"/>
|
||||
<field name="user_type" ref="account.data_account_type_receivable"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,224 +0,0 @@
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!--Email template -->
|
||||
<record id="email_template_credit_control_base" model="email.template">
|
||||
<field name="name">Credit Control Email</field>
|
||||
<field name="email_from">noreply@localhost</field>
|
||||
<field name="subject">Credit Control: (${object.current_policy_level.name or 'n/a'})</field>
|
||||
<field name="email_to">${object.get_email() or ''}</field>
|
||||
<field name="model_id" ref="model_credit_control_communication"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
<field name="lang">${object.get_contact_address().lang or 'en_US'}</field>
|
||||
<field name="report_template" ref="report_webkit_html"/>
|
||||
<field name="body_html"><![CDATA[
|
||||
Dear ${object.get_contact_address().name or ''}
|
||||
<br/>
|
||||
<br/>
|
||||
${object.current_policy_level.custom_mail_text}
|
||||
]]></field>
|
||||
</record>
|
||||
|
||||
<!-- policy no follow -->
|
||||
<record model="credit.control.policy"
|
||||
id="credit_control_no_follow">
|
||||
<field name="name">No follow</field>
|
||||
<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">
|
||||
<field name="name">3 time policy</field>
|
||||
</record>
|
||||
|
||||
<record model="credit.control.policy.level"
|
||||
id="3_time_1">
|
||||
<field name="name">10 days net</field>
|
||||
<field name="level" eval="1"/>
|
||||
<field name="computation_mode">net_days</field>
|
||||
<field name="delay_days" eval="10"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_3_time"/>
|
||||
<field name="channel">email</field>
|
||||
<field name="custom_text">Our records indicate that we have not received the payment of the above mentioned invoice.
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 10 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
|
||||
<field name="custom_mail_text">Our records indicate that we have not received the payment of the above mentioned invoice (copy attached for your convenience).
|
||||
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 10 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="credit.control.policy.level"
|
||||
id="3_time_2">
|
||||
<field name="name">30 days end of month</field>
|
||||
<field name="level" eval="2"/>
|
||||
<field name="computation_mode">end_of_month</field>
|
||||
<field name="delay_days" eval="30"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_3_time"/>
|
||||
<field name="channel">email</field>
|
||||
<field name="custom_text">Our records indicate that we have not yet received the payment of the above mentioned invoice despite our first reminder.
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 5 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
<field name="custom_mail_text">Our records indicate that we have not yet received the payment of the above mentioned invoice (copy attached for your convenience) despite our first reminder.
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 5 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="credit.control.policy.level"
|
||||
id="3_time_3">
|
||||
<field name="name">10 days last reminder</field>
|
||||
<field name="level" eval="3"/>
|
||||
<field name="computation_mode">previous_date</field>
|
||||
<field name="delay_days" eval="10"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_3_time"/>
|
||||
<field name="channel">letter</field>
|
||||
<field name="custom_text">
|
||||
Our records indicate that we still have not received the payment of the above mentioned invoice despite our two reminders.
|
||||
If payment have already been sent, please disregard this notice. If not, please proceed with payment.
|
||||
If your payment has not been received in the next 5 days, your file will be transfered to our debt collection agency.
|
||||
|
||||
Should you need us to arrange a payment plan for you, please advise.
|
||||
A customer account statement is enclosed for you convenience.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
|
||||
<field name="custom_mail_text">Our records indicate that we still have not received the payment of the above mentioned invoice (copy attached) despite our two reminders.
|
||||
If payment have already been sent, please disregard this notice. If not, please proceed with payment.
|
||||
If your payment has not been received in the next 5 days, your file will be transfered to our debt collection agency.
|
||||
|
||||
Should you need us to arrange a payment plan for you, please advise.
|
||||
A customer account statement is enclosed for you convenience.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- policy 2 -->
|
||||
<record model="credit.control.policy"
|
||||
id="credit_control_2_time">
|
||||
<field name="name">2 time policy</field>
|
||||
</record>
|
||||
|
||||
<record model="credit.control.policy.level"
|
||||
id="2_time_1">
|
||||
<field name="name">30 days end of month</field>
|
||||
<field name="level" eval="1"/>
|
||||
<field name="computation_mode">end_of_month</field>
|
||||
<field name="delay_days" eval="30"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_2_time"/>
|
||||
<field name="channel">email</field>
|
||||
<field name="custom_text">Our records indicate that we have not received the payment of the above mentioned invoice.
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 10 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
<field name="custom_mail_text">Our records indicate that we have not received the payment of the above mentioned invoice (copy attached for your convenience).
|
||||
If it has already been sent, please disregard this notice. If not, please proceed with payment within 10 days.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="credit.control.policy.level"
|
||||
id="2_time_2">
|
||||
<field name="name">60 days last reminder</field>
|
||||
<field name="level" eval="2"/>
|
||||
<field name="computation_mode">previous_date</field>
|
||||
<field name="delay_days" eval="60"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_2_time"/>
|
||||
<field name="channel">letter</field>
|
||||
<field name="custom_text">Our records indicate that we still have not received the payment of the above mentioned invoice despite our reminder.
|
||||
|
||||
If payment have already been sent, please disregard this notice. If not, please proceed with payment.
|
||||
If your payment has not been received in the next 5 days, your file will be transfered to our debt
|
||||
collection agency.
|
||||
|
||||
Should you need us to arrange a payment plan for you, please advise.
|
||||
A customer account statement is enclosed for you convenience.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
<field name="custom_mail_text">Our records indicate that we still have not received the payment of the above mentioned invoice (copy attached) despite our reminder.
|
||||
|
||||
If payment have already been sent, please disregard this notice. If not, please proceed with payment.
|
||||
If your payment has not been received in the next 5 days, your file will be transfered to our debt
|
||||
collection agency.
|
||||
|
||||
Should you need us to arrange a payment plan for you, please advise.
|
||||
A customer account statement is enclosed for you convenience.
|
||||
|
||||
Thank you in advance for your anticipated cooperation in this matter.
|
||||
|
||||
Best regards
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="group_account_credit_control_manager" model="res.groups">
|
||||
<field name="name">Credit Control Manager</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
</record>
|
||||
|
||||
<record id="group_account_credit_control_user" model="res.groups" context="{'noadmin':True}">
|
||||
<field name="name">Credit Control User</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
</record>
|
||||
|
||||
<record id="group_account_credit_control_info" model="res.groups" context="{'noadmin':True}">
|
||||
<field name="name">Credit Control Info</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
</record>
|
||||
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="credit_policy_id" ref="credit_control_3_time"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,83 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Vincent Renaville
|
||||
# Copyright 2013 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
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:
|
||||
cc_nondraft_line_ids = cc_line_obj.search(
|
||||
cr, uid,
|
||||
[('invoice_id', '=', invoice_id),
|
||||
('state', '<>', 'draft')],
|
||||
context=context)
|
||||
if cc_nondraft_line_ids:
|
||||
raise orm.except_orm(_('Error!'),
|
||||
_('You cannot cancel this invoice.\n'
|
||||
'A payment reminder has already been '
|
||||
'sent to the customer.\n'
|
||||
'You must create a credit note and '
|
||||
'issue a new invoice.'))
|
||||
cc_draft_line_ids = cc_line_obj.search(
|
||||
cr, uid,
|
||||
[('invoice_id', '=', invoice_id),
|
||||
('state', '=', 'draft')],
|
||||
context=context)
|
||||
cc_line_obj.unlink(cr, uid,
|
||||
cc_draft_line_ids,
|
||||
context=context)
|
||||
return super(AccountInvoice, self).action_cancel(cr, uid, ids,
|
||||
context=context)
|
||||
@@ -1,225 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 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.osv import orm, fields
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
logger = logging.getLogger('credit.line.control')
|
||||
|
||||
|
||||
class CreditControlLine(orm.Model):
|
||||
"""A credit control line describes an amount due by a customer for a due date.
|
||||
|
||||
A line is created once the due date of the payment is exceeded.
|
||||
It is created in "draft" and some actions are available (send by email,
|
||||
print, ...)
|
||||
"""
|
||||
|
||||
_name = "credit.control.line"
|
||||
_description = "A credit control line"
|
||||
_rec_name = "id"
|
||||
_order = "date DESC"
|
||||
_columns = {
|
||||
'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',
|
||||
required=True,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'date_entry': fields.related('move_line_id', 'date', type='date',
|
||||
string='Entry date',
|
||||
store=True, readonly=True),
|
||||
|
||||
'date_sent': fields.date('Sent date',
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'state': fields.selection([('draft', 'Draft'),
|
||||
('ignored', 'Ignored'),
|
||||
('to_be_sent', 'Ready To Send'),
|
||||
('sent', 'Done'),
|
||||
('error', 'Error'),
|
||||
('email_error', 'Emailing Error')],
|
||||
'State', required=True, readonly=True,
|
||||
help=("Draft lines need to be triaged.\n"
|
||||
"Ignored lines are lines for which we do "
|
||||
"not want to send something.\n"
|
||||
"Draft and ignored lines will be "
|
||||
"generated again on the next run.")),
|
||||
|
||||
'channel': fields.selection([('letter', 'Letter'),
|
||||
('email', 'Email')],
|
||||
'Channel', required=True,
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', "Partner", required=True),
|
||||
'amount_due': fields.float('Due Amount Tax incl.', required=True, readonly=True),
|
||||
'balance_due': fields.float('Due balance', required=True, readonly=True),
|
||||
'mail_message_id': fields.many2one('mail.mail', 'Sent Email', readonly=True),
|
||||
|
||||
'move_line_id': fields.many2one('account.move.line', 'Move line',
|
||||
required=True, readonly=True),
|
||||
|
||||
'account_id': fields.related('move_line_id', 'account_id', type='many2one',
|
||||
relation='account.account', string='Account',
|
||||
store=True, readonly=True),
|
||||
|
||||
'currency_id': fields.related('move_line_id', 'currency_id', type='many2one',
|
||||
relation='res.currency', string='Currency',
|
||||
store=True, readonly=True),
|
||||
|
||||
'company_id': fields.related('move_line_id', 'company_id', type='many2one',
|
||||
relation='res.company', string='Company',
|
||||
store=True, readonly=True),
|
||||
|
||||
# we can allow a manual change of policy in draft state
|
||||
'policy_level_id':fields.many2one('credit.control.policy.level',
|
||||
'Overdue Level', required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'policy_id': fields.related('policy_level_id',
|
||||
'policy_id',
|
||||
type='many2one',
|
||||
relation='credit.control.policy',
|
||||
string='Policy',
|
||||
store=True,
|
||||
readonly=True),
|
||||
|
||||
'level': fields.related('policy_level_id',
|
||||
'level',
|
||||
type='integer',
|
||||
relation='credit.control.policy',
|
||||
string='Level',
|
||||
store=True,
|
||||
readonly=True),
|
||||
'manually_overridden': fields.boolean('Manually overridden')
|
||||
}
|
||||
|
||||
|
||||
_defaults = {'state': 'draft'}
|
||||
|
||||
def _prepare_from_move_line(self, cr, uid, move_line,
|
||||
level, controlling_date, open_amount,
|
||||
context=None):
|
||||
"""Create credit control line"""
|
||||
data = {}
|
||||
data['date'] = controlling_date
|
||||
data['date_due'] = move_line.date_maturity
|
||||
data['state'] = 'draft'
|
||||
data['channel'] = level.channel
|
||||
data['invoice_id'] = move_line.invoice.id if move_line.invoice else False
|
||||
data['partner_id'] = move_line.partner_id.id
|
||||
data['amount_due'] = (move_line.amount_currency or move_line.debit or
|
||||
move_line.credit)
|
||||
data['balance_due'] = open_amount
|
||||
data['policy_level_id'] = level.id
|
||||
data['company_id'] = move_line.company_id.id
|
||||
data['move_line_id'] = move_line.id
|
||||
return data
|
||||
|
||||
def create_or_update_from_mv_lines(self, cr, uid, ids, lines,
|
||||
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')
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid)
|
||||
currency_ids = currency_obj.search(cr, uid, [], context=context)
|
||||
|
||||
tolerance = {}
|
||||
tolerance_base = user.company_id.credit_control_tolerance
|
||||
for c_id in currency_ids:
|
||||
tolerance[c_id] = currency_obj.compute(
|
||||
cr, uid,
|
||||
c_id,
|
||||
user.company_id.currency_id.id,
|
||||
tolerance_base,
|
||||
context=context)
|
||||
|
||||
level = level_obj.browse(cr, uid, level_id, context)
|
||||
line_ids = []
|
||||
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)
|
||||
|
||||
# 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
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None, check=True):
|
||||
for line in self.browse(cr, uid, ids, context=context):
|
||||
if line.state != 'draft':
|
||||
raise orm.except_orm(
|
||||
_('Error !'),
|
||||
_('You are not allowed to delete a credit control line that '
|
||||
'is not in draft state.'))
|
||||
|
||||
return super(CreditControlLine, self).unlink(cr, uid, ids, context=context)
|
||||
@@ -1,155 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="credit_control_line_form" model="ir.ui.view">
|
||||
<field name="name">credit.control.line.form</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Control Credit Lines">
|
||||
<field name="date"/>
|
||||
<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"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="amount_due"/>
|
||||
<field name="balance_due"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="move_line_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="policy_level_id"/>
|
||||
<field name="policy_id"/>
|
||||
<field name="mail_message_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_line_search" model="ir.ui.view">
|
||||
<field name="name">Credit Control Lines</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Control Credit Lines">
|
||||
<group string="Filters">
|
||||
<filter name="filter_draft" icon="terp-mail-message-new"
|
||||
string="Draft" domain="[('state', '=', 'draft')]"
|
||||
help="Draft lines have to be triaged."/>
|
||||
<filter name="filter_to_be_sent" icon="terp-mail-forward"
|
||||
string="Ready To Send" domain="[('state', '=', 'to_be_sent')]"
|
||||
help="These lines are ready to send by email or by letter using the Actions."/>
|
||||
<filter name="filter_ignored" icon="terp-mail_delete"
|
||||
string="Ignored" domain="[('state', '=', 'ignored')]"
|
||||
help="Lines which have been ignored from previous runs."/>
|
||||
<filter name="filter_sent" icon="terp-mail-replied"
|
||||
string="Sent" domain="[('state', '=', 'sent')]"
|
||||
help="Lines already sent."/>
|
||||
<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"/>
|
||||
<field name="channel" />
|
||||
<field name="policy_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="More...">
|
||||
<field name="partner_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="invoice_id"/>
|
||||
<field name="level"/>
|
||||
<field name="policy_level_id"/>
|
||||
</group>
|
||||
|
||||
<newline/>
|
||||
<group expand="0" string="Group By...">
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'date'}"
|
||||
icon="terp-go-month" string="Run date"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'level'}"
|
||||
icon="terp-gtk-jump-to-rtl" string="Level"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'partner_id'}"
|
||||
icon="terp-partner" string="Partner"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'account_id'}"
|
||||
icon="terp-folder-green" string="Account"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'invoice_id'}"
|
||||
icon="terp-document-new" string="Invoice"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'policy_id'}"
|
||||
icon="terp-document-new" string="Credit policy"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'policy_level_id'}"
|
||||
icon="terp-document-new" string="Credit policy level"/>
|
||||
<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>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_line_tree" model="ir.ui.view">
|
||||
<field name="name">credit.control.line.tree</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Control Credit Lines" colors="green:state == 'sent';red:state in ('error', 'email_error');">
|
||||
<field name="date"/>
|
||||
<field name="date_due"/>
|
||||
<field name="level"/>
|
||||
<field name="manually_overridden"/>
|
||||
<field name="state"/>
|
||||
<field name="channel"/>
|
||||
<field name="invoice_id"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="amount_due"/>
|
||||
<field name="balance_due"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="move_line_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="policy_level_id"/>
|
||||
<field name="policy_id"/>
|
||||
<field name="mail_message_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Credit Control"
|
||||
parent="account.menu_finance_periodical_processing"
|
||||
id="base_credit_control_menu"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="credit_control_line_action">
|
||||
<field name="name">Credit Control Lines</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">credit.control.line</field>
|
||||
<field name="domain"></field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="credit_control_line_tree"/>
|
||||
<field name="context">{'search_default_filter_draft': 1, 'search_default_filter_to_be_sent': 1}</field>
|
||||
<field name="search_view_id" ref="credit_control_line_search"/>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem
|
||||
name="Credit Control Lines"
|
||||
parent="base_credit_control_menu"
|
||||
action="credit_control_line_action"
|
||||
id="credit_control_line_action_menu"/>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
class Mail(orm.Model):
|
||||
_inherit = 'mail.mail'
|
||||
|
||||
# use HTML fields instead of text
|
||||
_columns = {'body_html': fields.html('Rich-text Contents',
|
||||
help="Rich-text/HTML message"),}
|
||||
@@ -1,79 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class ResPartner(orm.Model):
|
||||
"""Add a settings on the credit control policy to use on the partners,
|
||||
and links to the credit control lines."""
|
||||
|
||||
_inherit = "res.partner"
|
||||
|
||||
_columns = {
|
||||
'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:
|
||||
default = default.copy()
|
||||
default['credit_control_line_ids'] = False
|
||||
return super(ResPartner, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
@@ -1,25 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="partner_followup_form_view" model="ir.ui.view">
|
||||
<field name="name">partner.credit_control.form.view</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form" />
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="credit_limit" position="after">
|
||||
<field name="credit_policy_id" widget="selection"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_use"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window
|
||||
id="act_partner_credit_relation_relation"
|
||||
name="Credit Lines"
|
||||
groups="account_credit_control.group_account_credit_control_manager,account_credit_control.group_account_credit_control_user"
|
||||
domain="[('partner_id', '=', active_id)]"
|
||||
res_model="credit.control.line"
|
||||
src_model="res.partner"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,416 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlPolicy(orm.Model):
|
||||
"""Define a policy of reminder"""
|
||||
|
||||
_name = "credit.control.policy"
|
||||
_description = """Define a reminder policy"""
|
||||
_columns = {'name': fields.char('Name', required=True, size=128),
|
||||
|
||||
'level_ids': fields.one2many('credit.control.policy.level',
|
||||
'policy_id',
|
||||
'Policy Levels'),
|
||||
|
||||
'do_nothing': fields.boolean('Do nothing',
|
||||
help='For policies which should not '
|
||||
'generate lines or are obsolete'),
|
||||
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
|
||||
'account_ids': fields.many2many('account.account',
|
||||
string='Accounts',
|
||||
required=True,
|
||||
domain="[('type', '=', 'receivable')]",
|
||||
help="This policy will be active only"
|
||||
" for the selected accounts"),
|
||||
'active': fields.boolean('Active'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
}
|
||||
|
||||
def _move_lines_domain(self, cr, uid, policy, controlling_date, context=None):
|
||||
"""Build the default domain for searching move lines"""
|
||||
account_ids = [a.id for a in policy.account_ids]
|
||||
return [('account_id', 'in', account_ids),
|
||||
('date_maturity', '<=', controlling_date),
|
||||
('reconcile_id', '=', False),
|
||||
('partner_id', '!=', False)]
|
||||
|
||||
def _due_move_lines(self, cr, uid, policy, controlling_date, context=None):
|
||||
""" Get the due move lines for the policy of the company.
|
||||
|
||||
The set of ids will be reduced and extended according to the specific policies
|
||||
defined on partners and invoices.
|
||||
|
||||
Do not use direct SQL in order to respect security rules.
|
||||
|
||||
Assume that only the receivable lines have a maturity date and that
|
||||
accounts used in the policy are reconcilable.
|
||||
"""
|
||||
move_l_obj = self.pool.get('account.move.line')
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if user.company_id.credit_policy_id.id != policy.id:
|
||||
return set()
|
||||
|
||||
domain_line = self._move_lines_domain(cr, uid, policy,
|
||||
controlling_date, context=context)
|
||||
return set(move_l_obj.search(cr, uid, domain_line, context=context))
|
||||
|
||||
def _move_lines_subset(self, cr, uid, policy, controlling_date,
|
||||
model, move_relation_field, context=None):
|
||||
""" Get the move lines related to one model for a policy.
|
||||
|
||||
Do not use direct SQL in order to respect security rules.
|
||||
|
||||
Assume that only the receivable lines have a maturity date and that
|
||||
accounts used in the policy are reconcilable.
|
||||
|
||||
The policy relation field must be named credit_policy_id.
|
||||
|
||||
:param browse_record policy: policy
|
||||
:param str controlling_date: date of credit control
|
||||
:param str model: name of the model where is defined a credit_policy_id
|
||||
:param str move_relation_field: name of the field in account.move.line
|
||||
which is a many2one to `model`
|
||||
:return: set of ids to add in the process, set of ids to remove from
|
||||
the process
|
||||
"""
|
||||
# MARK possible place for a good optimisation
|
||||
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)
|
||||
to_add_ids = set()
|
||||
to_remove_ids = set()
|
||||
|
||||
# The lines which are linked to this policy have to be included in the
|
||||
# run for this policy.
|
||||
# If another object override the credit_policy_id (ie. invoice after
|
||||
add_obj_ids = my_obj.search(
|
||||
cr, uid,
|
||||
[('credit_policy_id', '=', policy.id)],
|
||||
context=context)
|
||||
if add_obj_ids:
|
||||
domain = list(default_domain)
|
||||
domain.append((move_relation_field, 'in', add_obj_ids))
|
||||
to_add_ids = set(move_l_obj.search(cr, uid, domain, context=context))
|
||||
|
||||
# The lines which are linked to another policy do not have to be
|
||||
# included in the run for this policy.
|
||||
neg_obj_ids = my_obj.search(
|
||||
cr, uid,
|
||||
[('credit_policy_id', '!=', policy.id),
|
||||
('credit_policy_id', '!=', False)],
|
||||
context=context)
|
||||
if neg_obj_ids:
|
||||
domain = list(default_domain)
|
||||
domain.append((move_relation_field, 'in', neg_obj_ids))
|
||||
to_remove_ids = set(move_l_obj.search(cr, uid, domain, context=context))
|
||||
return to_add_ids, to_remove_ids
|
||||
|
||||
def _get_partner_related_lines(self, cr, uid, policy, controlling_date, context=None):
|
||||
""" Get the move lines for a policy related to a partner.
|
||||
|
||||
:param browse_record policy: policy
|
||||
:param str controlling_date: date of credit control
|
||||
:param str model: name of the model where is defined a credit_policy_id
|
||||
:param str move_relation_field: name of the field in account.move.line
|
||||
which is a many2one to `model`
|
||||
:return: set of ids to add in the process, set of ids to remove from
|
||||
the process
|
||||
"""
|
||||
return self._move_lines_subset(cr, uid, policy, controlling_date,
|
||||
'res.partner', 'partner_id', context=context)
|
||||
|
||||
def _get_invoice_related_lines(self, cr, uid, policy, controlling_date, context=None):
|
||||
""" Get the move lines for a policy related to an invoice.
|
||||
|
||||
:param browse_record policy: policy
|
||||
:param str controlling_date: date of credit control
|
||||
:param str model: name of the model where is defined a credit_policy_id
|
||||
:param str move_relation_field: name of the field in account.move.line
|
||||
which is a many2one to `model`
|
||||
:return: set of ids to add in the process, set of ids to remove from
|
||||
the process
|
||||
"""
|
||||
return self._move_lines_subset(cr, uid, policy, controlling_date,
|
||||
'account.invoice', 'invoice', context=context)
|
||||
|
||||
def _get_move_lines_to_process(self, cr, uid, policy_id, controlling_date, context=None):
|
||||
"""Build a list of move lines ids to include in a run for a policy at a given date.
|
||||
|
||||
:param int/long policy: id of the policy
|
||||
:param str controlling_date: date of credit control
|
||||
:return: set of ids to include in the run
|
||||
"""
|
||||
assert not (isinstance(policy_id, list) and len(policy_id) > 1), \
|
||||
"policy_id: only one id expected"
|
||||
if isinstance(policy_id, list):
|
||||
policy_id = policy_id[0]
|
||||
|
||||
policy = self.browse(cr, uid, policy_id, context=context)
|
||||
# there is a priority between the lines, depicted by the calls below
|
||||
# warning, side effect method called on lines
|
||||
lines = self._due_move_lines(cr, uid, policy, controlling_date, context=context)
|
||||
add_ids, remove_ids = self._get_partner_related_lines(cr, uid, policy,
|
||||
controlling_date,
|
||||
context=context)
|
||||
lines = lines.union(add_ids).difference(remove_ids)
|
||||
add_ids, remove_ids = self._get_invoice_related_lines(cr, uid, policy,
|
||||
controlling_date,
|
||||
context=context)
|
||||
lines = lines.union(add_ids).difference(remove_ids)
|
||||
return lines
|
||||
|
||||
def _lines_different_policy(self, cr, uid, policy_id, lines, context=None):
|
||||
""" Return a set of move lines ids for which there is an existing credit line
|
||||
but with a different policy.
|
||||
"""
|
||||
different_lines = set()
|
||||
if not lines:
|
||||
return different_lines
|
||||
assert not (isinstance(policy_id, list) and len(policy_id) > 1), \
|
||||
"policy_id: only one id expected"
|
||||
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"
|
||||
" 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(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"""
|
||||
|
||||
_name = "credit.control.policy.level"
|
||||
_order = 'level'
|
||||
_description = """A credit control policy level"""
|
||||
_columns = {
|
||||
'policy_id': fields.many2one('credit.control.policy',
|
||||
'Related Policy', required=True),
|
||||
'name': fields.char('Name', size=128, required=True,
|
||||
translate=True),
|
||||
'level': fields.integer('Level', required=True),
|
||||
|
||||
'computation_mode': fields.selection([('net_days', 'Due Date'),
|
||||
('end_of_month', 'Due Date, End Of Month'),
|
||||
('previous_date', 'Previous Reminder')],
|
||||
'Compute Mode',
|
||||
required=True),
|
||||
|
||||
'delay_days': fields.integer('Delay (in days)', required='True'),
|
||||
'email_template_id': fields.many2one('email.template', 'Email Template',
|
||||
required=True),
|
||||
'channel': fields.selection([('letter', 'Letter'),
|
||||
('email', 'Email')],
|
||||
'Channel', required=True),
|
||||
'custom_text': fields.text('Custom Message', required=True, translate=True),
|
||||
'custom_mail_text': fields.text('Custom Mail Message',
|
||||
required=True, translate=True),
|
||||
|
||||
}
|
||||
|
||||
def _check_level_mode(self, cr, uid, rids, context=None):
|
||||
""" The smallest level of a policy cannot be computed on the
|
||||
"previous_date". Return False if this happens. """
|
||||
if isinstance(rids, (int, long)):
|
||||
rids = [rids]
|
||||
for level in self.browse(cr, uid, rids, context):
|
||||
smallest_level_id = self.search(
|
||||
cr, uid,
|
||||
[('policy_id', '=', level.policy_id.id)],
|
||||
order='level asc', limit=1, context=context)
|
||||
smallest_level = self.browse(cr, uid, smallest_level_id[0], context)
|
||||
if smallest_level.computation_mode == 'previous_date':
|
||||
return False
|
||||
return True
|
||||
|
||||
_sql_constraint = [('unique level',
|
||||
'UNIQUE (policy_id, level)',
|
||||
'Level must be unique per policy')]
|
||||
|
||||
_constraints = [(_check_level_mode,
|
||||
'The smallest level can not be of type Previous Reminder',
|
||||
['level'])]
|
||||
|
||||
def _previous_level(self, cr, uid, policy_level, context=None):
|
||||
""" For one policy level, returns the id of the previous level
|
||||
|
||||
If there is no previous level, it returns None, it means that's the
|
||||
first policy level
|
||||
|
||||
:param browse_record policy_level: policy level
|
||||
:return: previous level id or None if there is no previous level
|
||||
"""
|
||||
previous_level_ids = self.search(
|
||||
cr,
|
||||
uid,
|
||||
[('policy_id', '=', policy_level.policy_id.id),
|
||||
('level', '<', policy_level.level)],
|
||||
order='level desc',
|
||||
limit=1,
|
||||
context=context)
|
||||
return previous_level_ids[0] if previous_level_ids else None
|
||||
|
||||
# ----- sql time related methods ---------
|
||||
|
||||
def _net_days_get_boundary(self):
|
||||
return " (mv_line.date_maturity + %(delay)s)::date <= date(%(controlling_date)s)"
|
||||
|
||||
def _end_of_month_get_boundary(self):
|
||||
return ("(date_trunc('MONTH', (mv_line.date_maturity + %(delay)s))+INTERVAL '1 MONTH - 1 day')::date"
|
||||
"<= date(%(controlling_date)s)")
|
||||
|
||||
def _previous_date_get_boundary(self):
|
||||
return "(cr_line.date + %(delay)s)::date <= date(%(controlling_date)s)"
|
||||
|
||||
def _get_sql_date_boundary_for_computation_mode(self, cr, uid, level, controlling_date, context=None):
|
||||
"""Return a where clauses statement for the given
|
||||
controlling date and computation mode of the level"""
|
||||
fname = "_%s_get_boundary" % (level.computation_mode,)
|
||||
if hasattr(self, fname):
|
||||
fnc = getattr(self, fname)
|
||||
return fnc()
|
||||
else:
|
||||
raise NotImplementedError(_('Can not get function for computation mode: '
|
||||
'%s is not implemented') % (fname,))
|
||||
|
||||
# -----------------------------------------
|
||||
|
||||
def _get_first_level_move_line_ids(self, cr, uid, level, controlling_date, lines, context=None):
|
||||
"""Retrieve all the move lines that are linked to a first level.
|
||||
We use Raw SQL for performance. Security rule where applied in
|
||||
policy object when the first set of lines were retrieved"""
|
||||
level_lines = set()
|
||||
if not lines:
|
||||
return level_lines
|
||||
sql = ("SELECT DISTINCT mv_line.id\n"
|
||||
" FROM account_move_line mv_line\n"
|
||||
" WHERE mv_line.id in %(line_ids)s\n"
|
||||
" AND NOT EXISTS (SELECT id\n"
|
||||
" 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 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:
|
||||
level_lines.update([x[0] for x in res])
|
||||
return level_lines
|
||||
|
||||
def _get_other_level_move_line_ids(self, cr, uid, level, controlling_date, lines, context=None):
|
||||
""" Retrieve the move lines for other levels than first level.
|
||||
"""
|
||||
level_lines = set()
|
||||
if not lines:
|
||||
return level_lines
|
||||
sql = ("SELECT mv_line.id\n"
|
||||
" FROM account_move_line mv_line\n"
|
||||
" JOIN credit_control_line cr_line\n"
|
||||
" 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 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,
|
||||
controlling_date, context)
|
||||
previous_level_id = self._previous_level(cr, uid, level, context=context)
|
||||
previous_level = self.browse(cr, uid, previous_level_id, context=context)
|
||||
data_dict = {'controlling_date': controlling_date,
|
||||
'line_ids': tuple(lines),
|
||||
'delay': level.delay_days,
|
||||
'previous_level': previous_level.level}
|
||||
|
||||
# print cr.mogrify(sql, data_dict)
|
||||
cr.execute(sql, data_dict)
|
||||
res = cr.fetchall()
|
||||
if res:
|
||||
level_lines.update([x[0] for x in res])
|
||||
return level_lines
|
||||
|
||||
def get_level_lines(self, cr, uid, level_id, controlling_date, lines, context=None):
|
||||
"""get all move lines in entry lines that match the current level"""
|
||||
assert not (isinstance(level_id, list) and len(level_id) > 1), \
|
||||
"level_id: only one id expected"
|
||||
if isinstance(level_id, list):
|
||||
level_id = level_id[0]
|
||||
matching_lines = set()
|
||||
level = self.browse(cr, uid, level_id, context=context)
|
||||
if self._previous_level(cr, uid, level, context=context) is None:
|
||||
method = self._get_first_level_move_line_ids
|
||||
else:
|
||||
method = self._get_other_level_move_line_ids
|
||||
matching_lines.update(method(cr, uid, level,
|
||||
controlling_date, lines,
|
||||
context=context))
|
||||
return matching_lines
|
||||
@@ -1,125 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="credit_control_policy_form" model="ir.ui.view">
|
||||
<field name="name">credit.control.policy.form</field>
|
||||
<field name="model">credit.control.policy</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Credit control policy">
|
||||
<field name="name"/>
|
||||
<field name="do_nothing"/>
|
||||
<field name="company_id"/>
|
||||
<field name="active"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Policy levels">
|
||||
<field name="level_ids" nolabel="1" colspan="4" >
|
||||
<tree string="Credit control policy Level">
|
||||
<field name="name"/>
|
||||
<field name="level"/>
|
||||
<field name="channel"/>
|
||||
<field name="delay_days"/>
|
||||
<field name="computation_mode"/>
|
||||
<field name="email_template_id"/>
|
||||
</tree>
|
||||
<form string="Policy level">
|
||||
<field name="name"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Delay Setting">
|
||||
<field name="level"/>
|
||||
<field name="channel"/>
|
||||
<field name="delay_days"/>
|
||||
<field name="computation_mode"/>
|
||||
</page>
|
||||
<page string="Mail and reporting">
|
||||
<field name="email_template_id"/>
|
||||
<newline/>
|
||||
<field name="custom_text" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="custom_mail_text" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Accounts">
|
||||
<field name="account_ids" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_policy_tree" model="ir.ui.view">
|
||||
<field name="name">credit.control.policy.tree</field>
|
||||
<field name="model">credit.control.policy</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Credit control policy">
|
||||
<field name="name"/>
|
||||
<field name="do_nothing"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Credit Control"
|
||||
parent="account.menu_finance_configuration"
|
||||
id="base_credit_control_configuration_menu"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="credit_policy_configuration_action">
|
||||
<field name="name">Credit Control Policies</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">credit.control.policy</field>
|
||||
<field name="domain"></field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="credit_control_policy_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Credit Control Policies"
|
||||
parent="base_credit_control_configuration_menu"
|
||||
action="credit_policy_configuration_action"
|
||||
id="credit_policy_configuration_action_menu"/>
|
||||
|
||||
<record id="credit_mangement_policy_level_form" model="ir.ui.view">
|
||||
<field name="name">credit.mangement.policy.level.form</field>
|
||||
<field name="model">credit.control.policy.level</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Policy level">
|
||||
<field name="name"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Delay Setting">
|
||||
<field name="level"/>
|
||||
<field name="channel"/>
|
||||
<field name="delay_days"/>
|
||||
<field name="computation_mode"/>
|
||||
</page>
|
||||
<page string="Mail and reporting">
|
||||
<field name="email_template_id"/>
|
||||
<field name="custom_text"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_policy_level_tree" model="ir.ui.view">
|
||||
<field name="name">credit.control.policy.level.tree</field>
|
||||
<field name="model">credit.control.policy.level</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Credit control policy level">
|
||||
<field name="name"/>
|
||||
<field name="level"/>
|
||||
<field name="channel"/>
|
||||
<field name="delay_days"/>
|
||||
<field name="computation_mode"/>
|
||||
<field name="email_template_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1 +0,0 @@
|
||||
from . import credit_control_summary
|
||||
@@ -1,244 +0,0 @@
|
||||
## -*- coding: utf-8 -*-
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
${css}
|
||||
body {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.custom_text {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-left: 0px;
|
||||
text-align: left;
|
||||
width: 300px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.basic_table{
|
||||
text-align: center;
|
||||
border: 1px solid lightGrey;
|
||||
border-collapse: collapse;
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.basic_table th {
|
||||
border: 1px solid lightGrey;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.basic_table td {
|
||||
border: 1px solid lightGrey;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.list_table {
|
||||
border-color: black;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.list_table td {
|
||||
border-color: gray;
|
||||
border-top: 1px solid gray;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
padding-top: 3px;
|
||||
padding-bottom:3px;
|
||||
}
|
||||
|
||||
.list_table th {
|
||||
border-bottom: 2px solid black;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
padding-right: 3px
|
||||
padding-left: 3px
|
||||
}
|
||||
|
||||
.list_table thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
.address table {
|
||||
font-size: 11px;
|
||||
border-collapse: collapse;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.address .shipping {
|
||||
|
||||
}
|
||||
|
||||
.address .invoice {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.address .recipient {
|
||||
font-size: 13px;
|
||||
margin-right: 120px;
|
||||
margin-left: 350px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
table .address_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.address td.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td.amount, th.amount {
|
||||
text-align: right;
|
||||
padding-right:2px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
tr.line .note {
|
||||
border-style: none;
|
||||
font-size: 9px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
tr.line {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
%for comm in objects :
|
||||
<% setLang(comm.get_contact_address().lang) %>
|
||||
<div class="address">
|
||||
<table class="recipient">
|
||||
<%
|
||||
add = comm.get_contact_address()
|
||||
%>
|
||||
%if comm.partner_id.id == add.id:
|
||||
<tr><td class="name">${comm.partner_id.title and comm.partner_id.title.name or ''} ${comm.partner_id.name }</td></tr>
|
||||
<% address_lines = comm.partner_id.contact_address.split("\n") %>
|
||||
|
||||
%else:
|
||||
<tr><td class="name">${comm.partner_id.name or ''}</td></tr>
|
||||
<tr><td>${add.title and add.title.name or ''} ${add.name}</td></tr>
|
||||
<% address_lines = add.contact_address.split("\n")[1:] %>
|
||||
%endif
|
||||
%for part in address_lines:
|
||||
%if part:
|
||||
<tr><td>${part}</td></tr>
|
||||
%endif
|
||||
%endfor
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
<h3 style="clear: both; padding-top: 20px;">
|
||||
${_('Reminder')}: ${comm.current_policy_level.name or '' }
|
||||
</h3>
|
||||
|
||||
<p>${_('Dear')},</p>
|
||||
<p class="custom_text" width="95%">${comm.current_policy_level.custom_text.replace('\n', '<br />')}</p>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<p><b>${_('Summary')}<br/></b></p>
|
||||
<table class="basic_table" style="width: 100%;">
|
||||
<tr>
|
||||
<th width="200">${_('Invoice number')}</th>
|
||||
<th>${_('Invoice date')}</th>
|
||||
<th>${_('Date due')}</th>
|
||||
<th>${_('Invoiced amount')}</th>
|
||||
<th>${_('Open amount')}</th>
|
||||
<th>${_('Currency')}</th>
|
||||
|
||||
</tr>
|
||||
%for line in comm.credit_control_line_ids:
|
||||
<tr>
|
||||
%if line.invoice_id:
|
||||
<td width="200">${line.invoice_id.number}
|
||||
%if line.invoice_id.name:
|
||||
<br/>
|
||||
${line.invoice_id.name}
|
||||
%endif
|
||||
</td>
|
||||
%else:
|
||||
<td width="200">${line.move_line_id.name}</td>
|
||||
%endif
|
||||
<td class="date">${line.date_entry}</td>
|
||||
<td class="date">${line.date_due}</td>
|
||||
<td class="amount">${line.amount_due}</td>
|
||||
<td class="amount">${line.balance_due}</td>
|
||||
<td class="amount">${line.currency_id.name or comm.company_id.currency_id.name}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
<%doc>
|
||||
<!-- uncomment to have info after summary -->
|
||||
<p>${_('If you have any question, do not hesitate to contact us.')}</p>
|
||||
|
||||
<p>${comm.user_id.name} ${comm.user_id.email and '<%s>'%(comm.user_id.email) or ''}<br/>
|
||||
${comm.company_id.name}<br/>
|
||||
% if comm.company_id.street:
|
||||
${comm.company_id.street or ''}<br/>
|
||||
|
||||
% endif
|
||||
|
||||
% if comm.company_id.street2:
|
||||
${comm.company_id.street2}<br/>
|
||||
% endif
|
||||
% if comm.company_id.city or comm.company_id.zip:
|
||||
${comm.company_id.zip or ''} ${comm.company_id.city or ''}<br/>
|
||||
% endif
|
||||
% if comm.company_id.country_id:
|
||||
${comm.company_id.state_id and ('%s, ' % comm.company_id.state_id.name) or ''} ${comm.company_id.country_id.name or ''}<br/>
|
||||
% endif
|
||||
% if comm.company_id.phone:
|
||||
Phone: ${comm.company_id.phone}<br/>
|
||||
% endif
|
||||
% if comm.company_id.website:
|
||||
${comm.company_id.website or ''}<br/>
|
||||
% endif
|
||||
</%doc>
|
||||
|
||||
<p style="page-break-after:always"></p>
|
||||
%endfor
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 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 time
|
||||
|
||||
from openerp.report import report_sxw
|
||||
|
||||
class CreditSummaryReport(report_sxw.rml_parse):
|
||||
def __init__(self, cr, uid, name, context):
|
||||
super(CreditSummaryReport, self).__init__(cr, uid, name, context=context)
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'cr':cr,
|
||||
'uid': uid,
|
||||
})
|
||||
|
||||
report_sxw.report_sxw('report.credit_control_summary',
|
||||
'credit.control.communication',
|
||||
'addons/account_credit_control/report/credit_control_summary.html.mako',
|
||||
parser=CreditSummaryReport)
|
||||
@@ -1,16 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<report auto="False"
|
||||
id="report_webkit_html"
|
||||
model="credit.control.communication"
|
||||
name="credit_control_summary"
|
||||
file="account_credit_control/report/credit_control_summary.html.mako"
|
||||
string="Credit Summary"
|
||||
report_type="webkit"
|
||||
webkit_header="report_webkit.ir_header_webkit_basesample0"/>
|
||||
|
||||
<record model="ir.actions.report.xml" id="report_webkit_html">
|
||||
<field name="precise_mode" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,169 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 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.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
logger = logging.getLogger('credit.control.run')
|
||||
|
||||
|
||||
class CreditControlRun(orm.Model):
|
||||
"""Credit Control run generate all credit control lines and reject"""
|
||||
|
||||
_name = "credit.control.run"
|
||||
_rec_name = 'date'
|
||||
_description = """Credit control line generator"""
|
||||
_columns = {
|
||||
'date': fields.date('Controlling Date', required=True),
|
||||
'policy_ids':
|
||||
fields.many2many('credit.control.policy',
|
||||
rel="credit_run_policy_rel",
|
||||
id1='run_id', id2='policy_id',
|
||||
string='Policies',
|
||||
readonly=True,
|
||||
states={'draft': [('readonly', False)]}),
|
||||
|
||||
'report': fields.text('Report', readonly=True),
|
||||
|
||||
'state': fields.selection([('draft', 'Draft'),
|
||||
('done', 'Done')],
|
||||
string='State',
|
||||
required=True,
|
||||
readonly=True),
|
||||
|
||||
'manual_ids':
|
||||
fields.many2many('account.move.line',
|
||||
rel="credit_runreject_rel",
|
||||
string='Lines to handle manually',
|
||||
help=('If a credit control line has been generated'
|
||||
'on a policy and the policy has been changed '
|
||||
'in the meantime, it has to be handled '
|
||||
'manually'),
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default.update({
|
||||
'report': False,
|
||||
'manual_ids': False,
|
||||
})
|
||||
return super(CreditControlRun, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
|
||||
def _get_policies(self, cr, uid, context=None):
|
||||
return self.pool['credit.control.policy'].search(cr, uid, [], context=context)
|
||||
|
||||
_defaults = {'state': 'draft',
|
||||
'policy_ids': _get_policies}
|
||||
|
||||
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"""
|
||||
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 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):
|
||||
""" Generate credit control lines. """
|
||||
cr_line_obj = self.pool.get('credit.control.line')
|
||||
assert not (isinstance(run_id, list) and len(run_id) > 1), \
|
||||
"run_id: only one id expected"
|
||||
if isinstance(run_id, list):
|
||||
run_id = run_id[0]
|
||||
|
||||
run = self.browse(cr, uid, run_id, context=context)
|
||||
manually_managed_lines = set() # line who changed policy
|
||||
credit_line_ids = [] # generated lines
|
||||
run._check_run_date(run.date, context=context)
|
||||
|
||||
policies = run.policy_ids
|
||||
if not policies:
|
||||
raise orm.except_orm(_('Error'),
|
||||
_('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)
|
||||
manually_managed_lines.update(manual_lines)
|
||||
policy_generated_ids = []
|
||||
if lines:
|
||||
# policy levels are sorted by level so iteration is in the correct order
|
||||
for level in reversed(policy.level_ids):
|
||||
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))
|
||||
credit_line_ids += policy_generated_ids
|
||||
else:
|
||||
report += _("Policy \"%s\" has not generated any Credit Control Lines.\n" %
|
||||
policy.name)
|
||||
|
||||
vals = {'state': 'done',
|
||||
'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
|
||||
|
||||
Lock the ``credit_control_run`` Postgres table to avoid concurrent
|
||||
calls of this method.
|
||||
"""
|
||||
try:
|
||||
cr.execute('SELECT id FROM credit_control_run'
|
||||
' 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'),
|
||||
_('A credit control run is already running'
|
||||
' in background, please try later.'))
|
||||
|
||||
self._generate_credit_lines(cr, uid, run_id, context)
|
||||
return True
|
||||
@@ -1,66 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="credit_control_run_tree" model="ir.ui.view">
|
||||
<field name="name">credit.control.run.tree</field>
|
||||
<field name="model">credit.control.run</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Credit control run"> <!-- editable="bottom" -->
|
||||
<field name="date"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="credit_control_run_form" model="ir.ui.view">
|
||||
<field name="name">credit.control.run.form</field>
|
||||
<field name="model">credit.control.run</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Credit control run">
|
||||
<field name="date"
|
||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
<newline/>
|
||||
<notebook colspan="4">
|
||||
<page string="Policies">
|
||||
<field name="policy_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Report and Errors">
|
||||
<field name="report" colspan="4" nolabel="1"/>
|
||||
<separator string="Move lines To be treated manually"/>
|
||||
<field name="manual_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<group col="3" colspan="4">
|
||||
<button name="generate_credit_lines"
|
||||
string="Compute Credit Control Lines"
|
||||
colspan="1"
|
||||
type="object" icon="gtk-execute"
|
||||
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
|
||||
</group>
|
||||
<field name="state"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.actions.act_window" id="credit_control_run">
|
||||
<field name="name">Credit Control Run</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">credit.control.run</field>
|
||||
<field name="domain"></field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="credit_control_run_tree"/>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem
|
||||
name="Credit Control Run"
|
||||
parent="base_credit_control_menu"
|
||||
action="credit_control_run"
|
||||
id="credit_control_run_menu"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,55 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# OERPScenario, OpenERP Functional Tests
|
||||
# Copyright 2009 Camptocamp SA
|
||||
#
|
||||
##############################################################################
|
||||
##############################################################################
|
||||
# Branch # Module # Processes # System
|
||||
@account_credit_control @account_credit_control_setup
|
||||
|
||||
Feature: General parameters in order to test the credit control module
|
||||
|
||||
|
||||
@account_credit_control_setup_install_modules
|
||||
Scenario: MODULES INSTALLATION
|
||||
|
||||
Given I do not want all demo data to be loaded on install
|
||||
Given I install the required modules with dependencies:
|
||||
| name |
|
||||
| account_credit_control |
|
||||
|
||||
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
|
||||
And having:
|
||||
| name | value |
|
||||
| smtp_host | mailtrap.railsware.com |
|
||||
| sequence | 1 |
|
||||
| smtp_port | 2525 |
|
||||
| smtp_user | camptocamp1 |
|
||||
| smtp_pass | 20468fa2f2879cb9 |
|
||||
|
||||
@account_credit_control_policy_2_times
|
||||
Scenario: Configure the credit control policy in 2 times
|
||||
Given I configure the following accounts on the credit control policy with oid: "account_credit_control.credit_control_2_time":
|
||||
| account code |
|
||||
| 4111 |
|
||||
| 4112 |
|
||||
|
||||
@account_credit_control_policy_3_times
|
||||
Scenario: Configure the credit control policy in 3 times
|
||||
Given I configure the following accounts on the credit control policy with oid: "account_credit_control.credit_control_3_time":
|
||||
| account code |
|
||||
| 4111 |
|
||||
| 4112 |
|
||||
@@ -1,105 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# OERPScenario, OpenERP Functional Tests
|
||||
# Copyright 2009 Camptocamp SA
|
||||
#
|
||||
##############################################################################
|
||||
##############################################################################
|
||||
# Branch # Module # Processes # System
|
||||
@account_credit_control @account_credit_control_add_policy @account_credit_control_setup
|
||||
|
||||
Feature: I add policy to partners already created
|
||||
@account_credit_control_partner_1
|
||||
Scenario: Partner_1
|
||||
Given I need a "res.partner" with oid: scen.partner_1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | partner_1 |
|
||||
| credit_policy_id | by name: No follow |
|
||||
|
||||
@account_credit_control_customer_1
|
||||
Scenario: Customer_1
|
||||
Given I need a "res.partner" with oid: scen.customer_1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_1 |
|
||||
| credit_policy_id | by name: 2 time policy |
|
||||
|
||||
@account_credit_control_customer_2
|
||||
Scenario: Customer_2
|
||||
Given I need a "res.partner" with oid: scen.customer_2
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_2 |
|
||||
| credit_policy_id | by name: 2 time policy |
|
||||
|
||||
@account_credit_control_customer_3
|
||||
Scenario: Customer_3
|
||||
Given I need a "res.partner" with oid: scen.customer_3
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_3 |
|
||||
| credit_policy_id | by name: 2 time policy |
|
||||
|
||||
@account_credit_control_customer_4
|
||||
Scenario: Customer_4
|
||||
Given I need a "res.partner" with oid: scen.customer_4
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_4 |
|
||||
# the credit policy must be 3 time policy (inherited from company)
|
||||
|
||||
@account_credit_control_customer_5
|
||||
Scenario: Customer_5
|
||||
Given I need a "res.partner" with oid: scen.customer_5
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_5_usd |
|
||||
| credit_policy_id | by name: 3 time policy |
|
||||
|
||||
@account_credit_control_customer_6
|
||||
Scenario: Customer_6
|
||||
Given I need a "res.partner" with oid: scen.customer_6
|
||||
And having:
|
||||
| name | value |
|
||||
| name | customer_6 |
|
||||
| credit_policy_id | by name: 3 time policy |
|
||||
|
||||
@account_credit_control_customer_partial_pay
|
||||
Scenario: A customer who like to do partial payments
|
||||
Given I need a "res.partner" with oid: scen.customer_partial_pay
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Scrooge McDuck |
|
||||
| zip | 1000 |
|
||||
| city | Duckburg |
|
||||
| email | openerp@locahost.dummy |
|
||||
| phone | |
|
||||
| street | Duckstreet |
|
||||
|
||||
|
||||
@account_credit_control_customer_multiple_payterm
|
||||
Scenario: A customer who use payment terms in 2 times
|
||||
Given I need a "res.partner" with oid: scen.customer_multiple_payterm
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Donald Duck |
|
||||
| zip | 1100 |
|
||||
| city | Duckburg |
|
||||
| email | openerp@locahost.dummy |
|
||||
| phone | |
|
||||
| street | Duckstreet |
|
||||
|
||||
@account_credit_control_customer_multiple_payterm2
|
||||
Scenario: A customer who use payment terms in 2 times
|
||||
Given I need a "res.partner" with oid: scen.customer_multiple_payterm2
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Gus Goose |
|
||||
| type | default |
|
||||
| name | Gus Goose |
|
||||
| zip | 1100 |
|
||||
| city | Duckburg |
|
||||
| email | openerp@locahost.dummy |
|
||||
| phone | |
|
||||
| street | Duckstreet |
|
||||
@@ -1,588 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# OERPScenario, OpenERP Functional Tests
|
||||
# Copyright 2012 Camptocamp SA
|
||||
# Author Nicolas Bessi
|
||||
##############################################################################
|
||||
|
||||
|
||||
@account_credit_control @account_credit_control_setup @account_credit_control_base_data @account_credit_control_invoices
|
||||
|
||||
Feature: Invoices creation
|
||||
|
||||
##################### Partner 1 ##########################################################
|
||||
|
||||
@inv_1
|
||||
Scenario: Create invoice 1
|
||||
|
||||
Given I need a "account.invoice" with oid: scen._inv_1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_1 |
|
||||
| date_invoice | 2013-01-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv1_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_1 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_1
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv1_line2
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 2 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_1 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_1
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_2
|
||||
Scenario: Create invoice 2
|
||||
Given I need a "account.invoice" with oid: scen._inv_2
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_2 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv2_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1200 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_2 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_2
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
@inv_3
|
||||
Scenario: Create invoice 3
|
||||
Given I need a "account.invoice" with oid: scen._inv_3
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_3 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv3_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_3 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_3
|
||||
And I open the credit invoice
|
||||
|
||||
##################### Customer 2 ##########################################################
|
||||
|
||||
@inv_4
|
||||
Scenario: Create invoice 4
|
||||
|
||||
Given I need a "account.invoice" with oid: scen._inv_4
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_4 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv4_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_4 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_4
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
|
||||
@inv_5
|
||||
Scenario: Create invoice 5
|
||||
Given I need a "account.invoice" with oid: scen._inv_5
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_5 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv5_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1200 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_5 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_5
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
@inv_6
|
||||
Scenario: Create invoice 6
|
||||
Given I need a "account.invoice" with oid: scen._inv_6
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_6 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Days End of Month |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv6_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_6 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_6
|
||||
And I open the credit invoice
|
||||
|
||||
##################### Customer 3 ##########################################################
|
||||
|
||||
@inv_7
|
||||
Scenario: Create invoice 7
|
||||
|
||||
Given I need a "account.invoice" with oid: scen._inv_7
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_7 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv7_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_7 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_7
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
|
||||
@inv_8
|
||||
Scenario: Create invoice 8
|
||||
Given I need a "account.invoice" with oid: scen._inv_8
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_8 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv8_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1200 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_8 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_8
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
@inv_9
|
||||
Scenario: Create invoice 9
|
||||
Given I need a "account.invoice" with oid: scen._inv_9
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_9 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv9_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_9 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_9
|
||||
And I open the credit invoice
|
||||
|
||||
##################### Customer 4 ##########################################################
|
||||
|
||||
@inv_10
|
||||
Scenario: Create invoice 10
|
||||
|
||||
Given I need a "account.invoice" with oid: scen._inv_10
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_10 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30% Advance End 30 Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv10_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_10 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_10
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
|
||||
@inv_11
|
||||
Scenario: Create invoice 11
|
||||
Given I need a "account.invoice" with oid: scen._inv_11
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_11 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30% Advance End 30 Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv11_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1200 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_11 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_11
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
@inv_12
|
||||
Scenario: Create invoice 12
|
||||
Given I need a "account.invoice" with oid: scen._inv_12
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_12 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30% Advance End 30 Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv12_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_12 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_12
|
||||
And I open the credit invoice
|
||||
|
||||
##################### Customer 5 ##########################################################
|
||||
|
||||
@inv_13
|
||||
Scenario: Create invoice 13
|
||||
|
||||
Given I need a "account.invoice" with oid: scen._inv_13
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_13 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv13_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1000 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_13 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_13
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
|
||||
@inv_14
|
||||
Scenario: Create invoice 14
|
||||
Given I need a "account.invoice" with oid: scen._inv_14
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_14 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv14_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1200 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_14 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_14
|
||||
And I open the credit invoice
|
||||
|
||||
|
||||
@inv_15
|
||||
Scenario: Create invoice 15
|
||||
Given I need a "account.invoice" with oid: scen._inv_15
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: USD |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
|
||||
Given I need a "account.invoice.line" with oid: scen._inv15_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_15 |
|
||||
Given I find a "account.invoice" with oid: scen._inv_15
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_16
|
||||
Scenario: Create invoice 16
|
||||
Given I need a "account.invoice" with oid: scen._inv_16
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_16 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
And I need a "account.invoice.line" with oid: scen._inv16_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_16 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_16
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_17
|
||||
Scenario: Create invoice 17
|
||||
Given I need a "account.invoice" with oid: scen._inv_17
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_17 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_partial_pay |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
And I need a "account.invoice.line" with oid: scen._inv17_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_17 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_17
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_18
|
||||
Scenario: Create invoice 18
|
||||
Given I need a "account.invoice" with oid: scen._inv_18
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_18 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_multiple_payterm |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30% Advance End 30 Days |
|
||||
| type | out_invoice |
|
||||
|
||||
And I need a "account.invoice.line" with oid: scen._inv18_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_18 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_18
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_19
|
||||
Scenario: Create invoice 19
|
||||
Given I need a "account.invoice" with oid: scen._inv_19
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_19 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_multiple_payterm2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30% Advance End 30 Days |
|
||||
| type | out_invoice |
|
||||
And I need a "account.invoice.line" with oid: scen._inv19_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 1500 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_19 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_19
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_20
|
||||
Scenario: Create invoice 20
|
||||
Given I need a "account.invoice" with oid: scen._inv_20
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_20_test_tolerance |
|
||||
| date_invoice | 2013-03-23 |
|
||||
| partner_id | by oid: scen.customer_6 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
And I need a "account.invoice.line" with oid: scen._inv20_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 0.09 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_20 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_20
|
||||
And I open the credit invoice
|
||||
|
||||
@inv_20
|
||||
Scenario: Create invoice 21 (this receivable account must not be chased-> no credit line creation)
|
||||
Given I need a "account.invoice" with oid: scen._inv_21
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_21_test_receivable_account_excluded |
|
||||
| date_invoice | 2013-03-25 |
|
||||
| partner_id | by oid: scen.customer_6 |
|
||||
| account_id | by name: Debtors GBP |
|
||||
| journal_id | by name: Sales |
|
||||
| currency_id | by name: EUR |
|
||||
| payment_term | by name: 30 Net Days |
|
||||
| type | out_invoice |
|
||||
|
||||
And I need a "account.invoice.line" with oid: scen._inv21_line1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | invoice line 1 |
|
||||
| quantity | 1 |
|
||||
| price_unit | 6666 |
|
||||
| account_id | by name: Sales |
|
||||
| invoice_id | by oid: scen._inv_21 |
|
||||
Then I find a "account.invoice" with oid: scen._inv_21
|
||||
And I open the credit invoice
|
||||
@@ -1,29 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_jan
|
||||
|
||||
Feature: Ensure that mail credit line generation first pass is correct
|
||||
|
||||
Scenario: clean data
|
||||
Given I clean all the credit lines
|
||||
#Given I unreconcile and clean all move line
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run1
|
||||
And having:
|
||||
| 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 | 2013-01-18 | Debtors | 3 time policy | 2013-01-31 | customer_4 | email | 1 | SI_10 | 10 days net | draft | 300 | |
|
||||
@@ -1,33 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_feb
|
||||
|
||||
Feature: Ensure that mail 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"
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run2
|
||||
And having:
|
||||
| name | value |
|
||||
| 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 | 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 | |
|
||||
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_mar
|
||||
|
||||
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"
|
||||
|
||||
@pay_invoice_si_19_part1
|
||||
Scenario: I pay a part of the first part of the invoice SI 19,
|
||||
Given I need a "account.bank.statement" with oid: scen.state_control_eur_1
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_19_part1 |
|
||||
| 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"
|
||||
And I set the voucher paid amount to "300"
|
||||
And I save the voucher
|
||||
And I should have a "account.bank.statement.line" with name: "SI_19" and amount: "1050"
|
||||
And I set the voucher paid amount to "0"
|
||||
And I save the voucher
|
||||
Then I modify the line amount to "0"
|
||||
Given I need a "account.bank.statement" with oid: scen.state_control_eur_1
|
||||
And I set bank statement end-balance
|
||||
When I confirm bank statement
|
||||
Then My invoice "SI_19" is in state "open" reconciled with a residual amount of "1200.0"
|
||||
|
||||
@account_credit_control_run_month_mar
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run3
|
||||
And having:
|
||||
| name | value |
|
||||
| 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 | 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 | |
|
||||
@@ -1,44 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_apr
|
||||
|
||||
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"
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run4
|
||||
And having:
|
||||
| name | value |
|
||||
| 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 | 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 | |
|
||||
@@ -1,103 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_may
|
||||
|
||||
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"
|
||||
|
||||
@pay_invoice_si_16
|
||||
Scenario: I pay entirely the invoice SI 16, so it should no longer appear in the credit control lines
|
||||
Given I need a "account.bank.statement" with oid: scen.voucher_statement_si_16
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_16 |
|
||||
| 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
|
||||
Then My invoice "SI_16" is in state "paid" reconciled with a residual amount of "0.0"
|
||||
|
||||
@pay_invoice_si_17
|
||||
Scenario: I pay entirely the invoice SI 17, so it should no longer appear in the credit control lines
|
||||
Given I need a "account.bank.statement" with oid: scen.voucher_statement_si_17
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_17 |
|
||||
| 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"
|
||||
And I save the voucher
|
||||
And I modify the line amount to "1000"
|
||||
And I need a "account.bank.statement" with oid: scen.voucher_statement_si_17
|
||||
And I set bank statement end-balance
|
||||
When I confirm bank statement
|
||||
Then My invoice "SI_17" is in state "open" reconciled with a residual amount of "500.0"
|
||||
|
||||
@pay_invoice_si_18_part1
|
||||
Scenario: I pay the first part of the invoice SI 18, so it should no longer appear in the credit control lines however, the second move lines should still appears
|
||||
Given I need a "account.bank.statement" with oid: scen.voucher_statement_si_18
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_18_part1 |
|
||||
| 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"
|
||||
And I save the voucher
|
||||
And I modify the line amount to "450"
|
||||
And I should have a "account.bank.statement.line" with name: "SI_18" and amount: "1050"
|
||||
And I set the voucher paid amount to "0"
|
||||
And I save the voucher
|
||||
Then I modify the line amount to "0"
|
||||
And I need a "account.bank.statement" with oid: scen.voucher_statement_si_18
|
||||
And I set bank statement end-balance
|
||||
When I confirm bank statement
|
||||
Then My invoice "SI_18" is in state "open" reconciled with a residual amount of "1050.0"
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run5
|
||||
And having:
|
||||
| name | value |
|
||||
| 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 | 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 | |
|
||||
@@ -1,38 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_jun
|
||||
|
||||
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"
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run6
|
||||
And having:
|
||||
| name | value |
|
||||
| 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 | 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 | |
|
||||
@@ -1,35 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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_jul
|
||||
|
||||
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"
|
||||
|
||||
@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 | 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 | 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 | |
|
||||
@@ -1,30 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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"
|
||||
@@ -1,42 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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"
|
||||
@@ -1,145 +0,0 @@
|
||||
import time
|
||||
from behave import given, when
|
||||
from support import model
|
||||
|
||||
@given(u'I configure the following accounts on the credit control policy with oid: "{policy_oid}"')
|
||||
def impl(ctx, policy_oid):
|
||||
policy = model('credit.control.policy').get(policy_oid)
|
||||
assert policy, 'No policy % found' % policy_oid
|
||||
acc_obj = model('account.account')
|
||||
accounts = []
|
||||
for row in ctx.table:
|
||||
acc = acc_obj.get(['code = %s' % row['account code']])
|
||||
assert acc, "Account with code %s not found" % row['account code']
|
||||
accounts.append(acc)
|
||||
policy.write({'account_ids': [x.id for x in accounts]})
|
||||
|
||||
|
||||
@when(u'I launch the credit run')
|
||||
def impl(ctx):
|
||||
assert ctx.found_item
|
||||
# Must be a cleaner way to do it
|
||||
assert 'credit.control.run' == ctx.found_item._model._name
|
||||
ctx.found_item.generate_credit_lines()
|
||||
|
||||
@given(u'I clean all the credit lines')
|
||||
def impl(ctx):
|
||||
model('credit.control.line').browse([]).unlink()
|
||||
|
||||
@then(u'my credit run should be in state "done"')
|
||||
def impl(ctx):
|
||||
assert ctx.found_item
|
||||
# Must be a cleaner way to do it
|
||||
assert model("credit.control.run").get(ctx.found_item.id).state == 'done'
|
||||
|
||||
@then(u'the generated credit lines should have the following values')
|
||||
def impl(ctx):
|
||||
def _row_to_dict(row):
|
||||
return dict((name, row[name]) for name in row.headings if row[name])
|
||||
rows = map(_row_to_dict, ctx.table)
|
||||
|
||||
def _parse_date(value):
|
||||
return time.strftime(value) if '%' in value else value
|
||||
|
||||
for row in rows:
|
||||
account = model('account.account').get(['name = %s' % row['account']])
|
||||
assert account, "no account named %s found" % row['account']
|
||||
|
||||
policy = model('credit.control.policy').get(['name = %s' % row['policy']])
|
||||
assert policy, "No policy %s found" % row['policy']
|
||||
|
||||
partner = model('res.partner').get(['name = %s' % row['partner']])
|
||||
assert partner, "No partner %s found" % row['partner']
|
||||
|
||||
maturity_date = _parse_date(row['date due'])
|
||||
move_line = model('account.move.line').get(['name = %s' % row['move line'],
|
||||
'date_maturity = %s' % maturity_date])
|
||||
assert move_line, "No move line %s found" % row['move line']
|
||||
|
||||
level = model('credit.control.policy.level').get(['name = %s' % row['policy level'],
|
||||
'policy_id = %s' % policy.id])
|
||||
assert level, "No level % found" % row['policy level']
|
||||
|
||||
domain = [['account_id', '=', account.id],
|
||||
['policy_id', '=', policy.id],
|
||||
['partner_id', '=', partner.id],
|
||||
['policy_level_id', '=', level.id],
|
||||
['amount_due', '=', row.get('amount due', 0.0)],
|
||||
['state', '=', row['state']],
|
||||
['level', '=', row.get('level', 0.0)],
|
||||
['channel', '=', row['channel']],
|
||||
['balance_due', '=', row.get('balance', 0.0)],
|
||||
['date_due', '=', _parse_date(row['date due'])],
|
||||
['date', '=', _parse_date(row['date'])],
|
||||
['move_line_id', '=', move_line.id],
|
||||
]
|
||||
if row.get('currency'):
|
||||
curreny = model('res.currency').get(['name = %s' % row['currency']])
|
||||
assert curreny, "No currency %s found" % row['currency']
|
||||
domain.append(('currency_id', '=', curreny.id))
|
||||
|
||||
lines = model('credit.control.line').search(domain)
|
||||
assert lines, "no line found for %s" % repr(row)
|
||||
assert len(lines) == 1, "Too many lines found for %s" % repr(row)
|
||||
date_lines = model('credit.control.line').search([('date', '=', ctx.found_item.date)])
|
||||
assert len(date_lines) == len(ctx.table.rows), "Too many lines generated"
|
||||
|
||||
|
||||
def open_invoice(ctx):
|
||||
assert ctx.found_item
|
||||
ctx.found_item._send('invoice_open')
|
||||
# _send refresh object
|
||||
assert ctx.found_item.state == 'open'
|
||||
|
||||
@then(u'I open the credit invoice')
|
||||
def impl(ctx):
|
||||
open_invoice(ctx)
|
||||
|
||||
@given(u'I open the credit invoice')
|
||||
def impl(ctx):
|
||||
open_invoice(ctx)
|
||||
|
||||
@given(u'there is "{state}" credit lines')
|
||||
def impl(ctx, state):
|
||||
assert model('credit.control.line').search(['state = %s' % state])
|
||||
|
||||
@given(u'I mark all draft email to state "{state}"')
|
||||
def impl(ctx, state):
|
||||
wiz = model('credit.control.marker').create({'name': state})
|
||||
lines = model('credit.control.line').search([('state', '=', 'draft')])
|
||||
assert lines
|
||||
ctx.lines = lines
|
||||
wiz.write({'line_ids': lines})
|
||||
wiz.mark_lines()
|
||||
|
||||
@then(u'the draft line should be in state "{state}"')
|
||||
def impl(ctx, state):
|
||||
assert ctx.lines
|
||||
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)
|
||||
@@ -1,76 +0,0 @@
|
||||
# -*- 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)
|
||||
@@ -1,97 +0,0 @@
|
||||
from support import *
|
||||
import datetime
|
||||
|
||||
@step('I import invoice "{inv_name}" using import invoice button')
|
||||
def impl(ctx, inv_name):
|
||||
invoice = model('account.invoice').get([('name', '=', inv_name)])
|
||||
assert invoice
|
||||
bank_statement = ctx.found_item
|
||||
for line in bank_statement.line_ids:
|
||||
line.unlink()
|
||||
lines = model('account.move.line').browse([('move_id', '=', invoice.move_id.id),
|
||||
('account_id', '=', invoice.account_id.id)])
|
||||
|
||||
wizard = model('account.statement.from.invoice.lines').create({'line_ids': lines})
|
||||
wizard.populate_statement({'statement_id': bank_statement.id})
|
||||
|
||||
@given(u'I should have a "account.bank.statement.line" with name: "{name}" and amount: "{amount}"')
|
||||
def impl(ctx, name, amount):
|
||||
assert ctx.found_item
|
||||
line = model('account.bank.statement.line').get([('name', '=', name),
|
||||
('amount', '=', amount),
|
||||
('statement_id', '=', ctx.found_item.id)])
|
||||
assert line
|
||||
ctx.line = line
|
||||
|
||||
@given(u'I set the voucher paid amount to "{amount}"')
|
||||
def impl(ctx, amount):
|
||||
assert ctx.line
|
||||
voucher = model('account.voucher').get(ctx.line.voucher_id.id)
|
||||
assert voucher
|
||||
|
||||
vals = voucher.onchange_amount(float(amount),
|
||||
voucher.payment_rate,
|
||||
voucher.partner_id.id,
|
||||
voucher.journal_id.id if voucher.journal_id else False,
|
||||
voucher.currency_id.id if voucher.currency_id else False,
|
||||
voucher.type,
|
||||
voucher.date,
|
||||
voucher.payment_rate,
|
||||
voucher.company_id.id if voucher.company_id else false)
|
||||
vals = vals['value']
|
||||
vals.update({'amount': ctx.line.voucher_id.amount})
|
||||
voucher_line_ids = []
|
||||
voucher_line_dr_ids = []
|
||||
v_l_obj = model('account.voucher.line')
|
||||
for v_line_vals in vals.get('line_cr_ids', []) or []:
|
||||
v_line_vals['voucher_id'] = voucher.id
|
||||
voucher_line_ids.append(v_l_obj.create(v_line_vals).id)
|
||||
vals['line_cr_ids'] = voucher_line_ids
|
||||
|
||||
for v_line_vals in vals.get('line_dr_ids', []) or []:
|
||||
v_line_vals['voucher_id'] = voucher.id
|
||||
voucher_line_dr_ids.append(v_l_obj.create(v_line_vals).id)
|
||||
vals['line_dr_ids'] = voucher_line_ids
|
||||
|
||||
voucher.write(vals)
|
||||
ctx.vals = vals
|
||||
ctx.voucher = voucher
|
||||
|
||||
@given(u'I save the voucher')
|
||||
def impl(ctx):
|
||||
assert True
|
||||
|
||||
@given(u'I modify the line amount to "{amount}"')
|
||||
@then(u'I modify the line amount to "{amount}"')
|
||||
def impl(ctx, amount):
|
||||
assert ctx.line
|
||||
# we have to change voucher amount before chaning statement line amount
|
||||
if ctx.line.voucher_id:
|
||||
model('account.voucher').write([ctx.line.voucher_id.id],
|
||||
{'amount': float(amount)})
|
||||
ctx.line.write({'amount': float(amount)})
|
||||
|
||||
@step('My invoice "{inv_name}" is in state "{state}" reconciled with a residual amount of "{amount:f}"')
|
||||
def impl(ctx, inv_name, state, amount):
|
||||
invoice = model('account.invoice').get([('name', '=', inv_name)])
|
||||
assert_almost_equal(invoice.residual, amount)
|
||||
assert_equal(invoice.state, state)
|
||||
|
||||
@step('I modify the bank statement line amount to {amount:f}')
|
||||
def impl(ctx, amount):
|
||||
line = ctx.found_item.voucher_id.line_cr_ids[0]
|
||||
#ctx.voucher = model('account.voucher').get(ctx.found_item.voucher_id.id)
|
||||
ctx.found_item.on_change('onchange_amount', 'amount', (), amount)
|
||||
|
||||
@then(u'I set bank statement end-balance')
|
||||
@given(u'I set bank statement end-balance')
|
||||
def impl(ctx):
|
||||
assert ctx.found_item, "No statement found"
|
||||
ctx.found_item.write({'balance_end_real': ctx.found_item.balance_end})
|
||||
assert ctx.found_item.balance_end == ctx.found_item.balance_end_real
|
||||
|
||||
@when(u'I confirm bank statement')
|
||||
def impl(ctx):
|
||||
assert ctx.found_item
|
||||
assert_equal(ctx.found_item._model._name, 'account.bank.statement')
|
||||
ctx.found_item.button_confirm_bank()
|
||||
@@ -1,21 +0,0 @@
|
||||
"id","perm_create","perm_unlink","group_id/id","name","model_id/id","perm_read","perm_write"
|
||||
"account_credit_control.ir_model_access_270",1,1,"group_account_credit_control_manager","credit_control_manager_line","account_credit_control.model_credit_control_line",1,1
|
||||
"account_credit_control.ir_model_access_271",1,1,"group_account_credit_control_user","credit_control_user_line","account_credit_control.model_credit_control_line",1,1
|
||||
"account_credit_control.ir_model_access_272",0,0,"group_account_credit_control_info","credit_control_info_line","account_credit_control.model_credit_control_line",1,0
|
||||
"account_credit_control.ir_model_access_273",1,1,"group_account_credit_control_manager","credit_control_manager_mail_template","email_template.model_email_template",1,1
|
||||
"account_credit_control.ir_model_access_274",1,1,"group_account_credit_control_manager","credit_control_manager_mail_template_preview","email_template.model_email_template_preview",1,1
|
||||
"account_credit_control.ir_model_access_275",1,1,"group_account_credit_control_manager","credit_control_manager_mail_message","mail.model_mail_message",1,1
|
||||
"account_credit_control.ir_model_access_276",1,0,"group_account_credit_control_user","credit_control_user_mail_message","mail.model_mail_message",1,1
|
||||
"account_credit_control.ir_model_access_277",0,0,"group_account_credit_control_info","credit_control_info_mail_message","mail.model_mail_message",1,0
|
||||
"account_credit_control.ir_model_access_281",1,1,"group_account_credit_control_manager","credit_control_mananger_run","account_credit_control.model_credit_control_run",1,1
|
||||
"account_credit_control.ir_model_access_282",1,1,"group_account_credit_control_user","credit_control_user_run","account_credit_control.model_credit_control_run",1,1
|
||||
"account_credit_control.ir_model_access_283",0,0,"group_account_credit_control_info","credit_control_info_run","account_credit_control.model_credit_control_run",1,0
|
||||
"account_credit_control.ir_model_access_284",1,1,"group_account_credit_control_manager","credit_control_manager_policy","account_credit_control.model_credit_control_policy",1,1
|
||||
"account_credit_control.ir_model_access_285",0,0,"group_account_credit_control_user","credit_control_user_policy","account_credit_control.model_credit_control_policy",1,0
|
||||
"account_credit_control.ir_model_access_286",0,0,"group_account_credit_control_info","credit_control_info_policy","account_credit_control.model_credit_control_policy",1,0
|
||||
"account_credit_control.ir_model_access_287",1,1,"group_account_credit_control_manager","credit_control_manager_level","account_credit_control.model_credit_control_policy_level",1,1
|
||||
"account_credit_control.ir_model_access_288",0,0,"group_account_credit_control_user","credit_control_user_level","account_credit_control.model_credit_control_policy_level",1,0
|
||||
"account_credit_control.ir_model_access_289",0,0,"group_account_credit_control_info","credit_control_info_level","account_credit_control.model_credit_control_policy_level",1,0
|
||||
"account_credit_control.ir_model_access_290",0,0,"account.group_account_user","credit_control_fin_user_line","account_credit_control.model_credit_control_line",1,0
|
||||
"account_credit_control.ir_model_access_291",0,0,"account.group_account_invoice","credit_control_fin_invoice_line","account_credit_control.model_credit_control_line",1,0
|
||||
"account_credit_control.ir_model_access_292",1,1,"account.group_account_manager","credit_control_fin_manager_line","account_credit_control.model_credit_control_line",1,1
|
||||
|
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from . import credit_control_emailer
|
||||
from . import credit_control_marker
|
||||
from . import credit_control_printer
|
||||
from . import credit_control_communication
|
||||
from . import credit_control_policy_changer
|
||||
@@ -1,183 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 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 netsvc
|
||||
import logging
|
||||
from openerp.osv.orm import TransientModel, fields
|
||||
|
||||
logger = logging.getLogger('credit.control.line.mailing')
|
||||
|
||||
|
||||
class CreditCommunication(TransientModel):
|
||||
"""Shell class used to provide a base model to email template and reporting.
|
||||
Il use this approche in version 7 a browse record will exist even if not saved"""
|
||||
_name = "credit.control.communication"
|
||||
_description = "credit control communication"
|
||||
_rec_name = 'partner_id'
|
||||
_columns = {'partner_id': fields.many2one('res.partner', 'Partner', required=True),
|
||||
|
||||
'current_policy_level': fields.many2one('credit.control.policy.level',
|
||||
'Level', required=True),
|
||||
|
||||
'credit_control_line_ids': fields.many2many('credit.control.line',
|
||||
rel='comm_credit_rel',
|
||||
string='Credit Lines'),
|
||||
|
||||
'company_id': fields.many2one('res.company', 'Company',
|
||||
required=True),
|
||||
|
||||
'user_id': fields.many2one('res.users', 'User')}
|
||||
|
||||
_defaults = {'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(
|
||||
cr, uid, 'credit.control.policy', context=c),
|
||||
'user_id': lambda s, cr, uid, c: uid}
|
||||
|
||||
def get_email(self, cr, uid, com_id, context=None):
|
||||
"""Return a valid email for customer"""
|
||||
if isinstance(com_id, list):
|
||||
assert len(com_id) == 1, "get_email only support one id as parameter"
|
||||
com_id = com_id[0]
|
||||
form = self.browse(cr, uid, com_id, context=context)
|
||||
contact = form.get_contact_address()
|
||||
return contact.email
|
||||
|
||||
def get_contact_address(self, cr, uid, com_id, context=None):
|
||||
pmod = self.pool['res.partner']
|
||||
if isinstance(com_id, list):
|
||||
com_id = com_id[0]
|
||||
form = self.browse(cr, uid, com_id, context=context)
|
||||
part = form.partner_id
|
||||
add_ids = part.address_get(adr_pref=['invoice']) or {}
|
||||
add_id = add_ids.get('invoice', add_ids.get('default', False))
|
||||
return pmod.browse(cr, uid, add_id, context)
|
||||
|
||||
def _get_credit_lines(self, cr, uid, line_ids, partner_id, level_id, context=None):
|
||||
"""Return credit lines related to a partner and a policy level"""
|
||||
cr_line_obj = self.pool.get('credit.control.line')
|
||||
cr_l_ids = cr_line_obj.search(cr,
|
||||
uid,
|
||||
[('id', 'in', line_ids),
|
||||
('partner_id', '=', partner_id),
|
||||
('policy_level_id', '=', level_id)],
|
||||
context=context)
|
||||
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_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, credit_control_line.currency_id")
|
||||
|
||||
cr.execute(sql, (tuple(line_ids),))
|
||||
res = cr.dictfetchall()
|
||||
for level_assoc in res:
|
||||
data = {}
|
||||
data['credit_control_line_ids'] = \
|
||||
[(6, 0, self._get_credit_lines(cr, uid, line_ids,
|
||||
level_assoc['partner_id'],
|
||||
level_assoc['policy_level_id'],
|
||||
context=context))]
|
||||
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
|
||||
|
||||
def _generate_emails(self, cr, uid, comms, context=None):
|
||||
"""Generate email message using template related to level"""
|
||||
cr_line_obj = self.pool.get('credit.control.line')
|
||||
email_temp_obj = self.pool.get('email.template')
|
||||
email_message_obj = self.pool.get('mail.mail')
|
||||
att_obj = self.pool.get('ir.attachment')
|
||||
email_ids = []
|
||||
essential_fields = ['subject',
|
||||
'body_html',
|
||||
'email_from',
|
||||
'email_to']
|
||||
|
||||
for comm in comms:
|
||||
# we want to use a local cr in order to send the maximum
|
||||
# of email
|
||||
template = comm.current_policy_level.email_template_id.id
|
||||
email_values = {}
|
||||
cl_ids = [cl.id for cl in comm.credit_control_line_ids]
|
||||
email_values = email_temp_obj.generate_email(cr, uid,
|
||||
template,
|
||||
comm.id,
|
||||
context=context)
|
||||
email_values['body_html'] = email_values['body']
|
||||
email_values['type'] = 'email'
|
||||
|
||||
email_id = email_message_obj.create(cr, uid, email_values, context=context)
|
||||
|
||||
state = 'sent'
|
||||
# The mail will not be send, however it will be in the pool, in an
|
||||
# error state. So we create it, link it with the credit control line
|
||||
# and put this latter in a `email_error` state we not that we have a
|
||||
# problem with the email
|
||||
if any(not email_values.get(field) for field in essential_fields):
|
||||
state = 'email_error'
|
||||
|
||||
cr_line_obj.write(
|
||||
cr, uid, cl_ids,
|
||||
{'mail_message_id': email_id,
|
||||
'state': state},
|
||||
context=context)
|
||||
att_ids = []
|
||||
for att in email_values.get('attachments', []):
|
||||
attach_fname = att[0]
|
||||
attach_datas = att[1]
|
||||
data_attach = {
|
||||
'name': attach_fname,
|
||||
'datas': attach_datas,
|
||||
'datas_fname': attach_fname,
|
||||
'res_model': 'mail.mail',
|
||||
'res_id': email_id,
|
||||
'type': 'binary',
|
||||
}
|
||||
att_ids.append(att_obj.create(cr, uid, data_attach, context=context))
|
||||
email_message_obj.write(cr, uid, [email_id],
|
||||
{'attachment_ids': [(6, 0, att_ids)]},
|
||||
context=context)
|
||||
email_ids.append(email_id)
|
||||
return email_ids
|
||||
|
||||
def _generate_report(self, cr, uid, comms, context=None):
|
||||
"""Will generate a report by inserting mako template of related policy template"""
|
||||
service = netsvc.LocalService('report.credit_control_summary')
|
||||
ids = [x.id for x in comms]
|
||||
result, format = service.create(cr, uid, ids, {}, {})
|
||||
return result
|
||||
|
||||
def _mark_credit_line_as_sent(self, cr, uid, comms, context=None):
|
||||
line_ids = []
|
||||
for comm in comms:
|
||||
line_ids += [x.id for x in comm.credit_control_line_ids]
|
||||
l_obj = self.pool.get('credit.control.line')
|
||||
l_obj.write(cr, uid, line_ids, {'state': 'sent'}, context=context)
|
||||
return line_ids
|
||||
@@ -1,82 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlEmailer(orm.TransientModel):
|
||||
"""Send emails for each selected credit control lines."""
|
||||
|
||||
_name = "credit.control.emailer"
|
||||
_description = """Mass credit line emailer"""
|
||||
_rec_name = 'id'
|
||||
|
||||
def _get_line_ids(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = False
|
||||
if (context.get('active_model') == 'credit.control.line' and
|
||||
context.get('active_ids')):
|
||||
res = self._filter_line_ids(
|
||||
cr, uid,
|
||||
context['active_ids'],
|
||||
context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'line_ids': fields.many2many(
|
||||
'credit.control.line',
|
||||
string='Credit Control Lines',
|
||||
domain="[('state', '=', 'to_be_sent'), ('channel', '=', 'email')]"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'line_ids': _get_line_ids,
|
||||
}
|
||||
|
||||
def _filter_line_ids(self, cr, uid, active_ids, context=None):
|
||||
"""filter lines to use in the wizard"""
|
||||
line_obj = self.pool.get('credit.control.line')
|
||||
domain = [('state', '=', 'to_be_sent'),
|
||||
('id', 'in', active_ids),
|
||||
('channel', '=', 'email')]
|
||||
return line_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
def email_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"
|
||||
comm_obj = self.pool.get('credit.control.communication')
|
||||
if isinstance(wiz_id, list):
|
||||
wiz_id = wiz_id[0]
|
||||
form = self.browse(cr, uid, wiz_id, context)
|
||||
|
||||
if not form.line_ids:
|
||||
raise orm.except_orm(_('Error'), _('No credit control lines selected.'))
|
||||
|
||||
line_ids = [l.id for l in form.line_ids]
|
||||
filtered_ids = self._filter_line_ids(
|
||||
cr, uid, line_ids, context)
|
||||
comms = comm_obj._generate_comm_from_credit_line_ids(
|
||||
cr, uid, filtered_ids, context=context)
|
||||
comm_obj._generate_emails(cr, uid, comms, context=context)
|
||||
return {}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<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="arch" type="xml">
|
||||
<form string="Mailer" version="7.0">
|
||||
<separator string="Send emails for the selected lines" colspan="4"/>
|
||||
<newline/>
|
||||
<notebook>
|
||||
<page string="Lines">
|
||||
<field name="line_ids" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
</notebook>
|
||||
<newline/>
|
||||
<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>
|
||||
|
||||
<!-- for menu -->
|
||||
<act_window name="Send By Email"
|
||||
res_model="credit.control.emailer"
|
||||
src_model="credit.control.line"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="open_credit_line_emailer_wizard_menu_action"/>
|
||||
|
||||
<!-- for button -->
|
||||
<record id="open_credit_line_emailer_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Send By Email</field>
|
||||
<field name="res_model">credit.control.emailer</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="credit_line_emailer_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="help">Send an email for the selected lines.</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,100 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlMarker(orm.TransientModel):
|
||||
"""Change the state of lines in mass"""
|
||||
|
||||
_name = 'credit.control.marker'
|
||||
_description = 'Mass marker'
|
||||
|
||||
def _get_line_ids(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = False
|
||||
if (context.get('active_model') == 'credit.control.line' and
|
||||
context.get('active_ids')):
|
||||
res = self._filter_line_ids(
|
||||
cr, uid,
|
||||
context['active_ids'],
|
||||
context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.selection([('ignored', 'Ignored'),
|
||||
('to_be_sent', 'Ready To Send'),
|
||||
('sent', 'Done')],
|
||||
'Mark as', required=True),
|
||||
'line_ids': fields.many2many(
|
||||
'credit.control.line',
|
||||
string='Credit Control Lines',
|
||||
domain="[('state', '!=', 'sent')]"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'name': 'to_be_sent',
|
||||
'line_ids': _get_line_ids,
|
||||
}
|
||||
|
||||
def _filter_line_ids(self, cr, uid, active_ids, context=None):
|
||||
"""get line to be marked filter done lines"""
|
||||
line_obj = self.pool.get('credit.control.line')
|
||||
domain = [('state', '!=', 'sent'), ('id', 'in', active_ids)]
|
||||
return line_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
def _mark_lines(self, cr, uid, filtered_ids, state, context=None):
|
||||
"""write hook"""
|
||||
line_obj = self.pool.get('credit.control.line')
|
||||
if not state:
|
||||
raise ValueError(_('state can not be empty'))
|
||||
line_obj.write(cr, uid, filtered_ids, {'state': state}, context=context)
|
||||
return filtered_ids
|
||||
|
||||
def mark_lines(self, cr, uid, wiz_id, context=None):
|
||||
"""Write state of selected credit lines to the one in entry
|
||||
done credit line will be ignored"""
|
||||
assert not (isinstance(wiz_id, list) and len(wiz_id) > 1), \
|
||||
"wiz_id: only one id expected"
|
||||
if isinstance(wiz_id, list):
|
||||
wiz_id = wiz_id[0]
|
||||
form = self.browse(cr, uid, wiz_id, context)
|
||||
|
||||
if not form.line_ids:
|
||||
raise orm.except_orm(_('Error'), _('No credit control lines selected.'))
|
||||
|
||||
line_ids = [l.id for l in form.line_ids]
|
||||
|
||||
filtered_ids = self._filter_line_ids(cr, uid, line_ids, context)
|
||||
if not filtered_ids:
|
||||
raise except_osv(_('Information'),
|
||||
_('No lines will be changed. All the selected lines are already done.'))
|
||||
|
||||
self._mark_lines(cr, uid, filtered_ids, form.name, context)
|
||||
|
||||
return {'domain': unicode([('id', 'in', filtered_ids)]),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'view_id': False,
|
||||
'res_model': 'credit.control.line',
|
||||
'type': 'ir.actions.act_window'}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<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="arch" type="xml">
|
||||
<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/>
|
||||
<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>
|
||||
|
||||
<!-- for menu -->
|
||||
<act_window name="Change Lines' State"
|
||||
res_model="credit.control.marker"
|
||||
src_model="credit.control.line"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="open_credit_line_marker_wizard_menu_action"/>
|
||||
|
||||
<record id="open_credit_line_marker_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Change Lines' State</field>
|
||||
<field name="res_model">credit.control.marker</field>
|
||||
<field name="src_model">credit.control.line</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="credit_line_marker_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="help">Change the state of the selected lines.</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,178 +0,0 @@
|
||||
# -*- 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
|
||||
@@ -1,65 +0,0 @@
|
||||
<?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>
|
||||
@@ -1,109 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi, Guewen Baconnier
|
||||
# Copyright 2012 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 base64
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlPrinter(orm.TransientModel):
|
||||
"""Print lines"""
|
||||
|
||||
_name = "credit.control.printer"
|
||||
_rec_name = 'id'
|
||||
_description = 'Mass printer'
|
||||
|
||||
def _get_line_ids(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = False
|
||||
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',
|
||||
string='Credit Control Lines'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'mark_as_sent': True,
|
||||
'line_ids': _get_line_ids,
|
||||
}
|
||||
|
||||
def _filter_line_ids(self, cr, uid, active_ids, context=None):
|
||||
"""filter lines to use in the wizard"""
|
||||
line_obj = self.pool.get('credit.control.line')
|
||||
domain = [('state', '=', 'to_be_sent'),
|
||||
('id', 'in', active_ids),
|
||||
('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"
|
||||
comm_obj = self.pool.get('credit.control.communication')
|
||||
if isinstance(wiz_id, list):
|
||||
wiz_id = wiz_id[0]
|
||||
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.'))
|
||||
|
||||
line_ids = self._get_line_ids(cr,
|
||||
uid,
|
||||
form.line_ids,
|
||||
self._credit_line_predicate,
|
||||
context=context)
|
||||
|
||||
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),
|
||||
'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)
|
||||
|
||||
return {'type': 'ir.actions.act_window',
|
||||
'res_model': 'credit.control.printer',
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'res_id': form.id,
|
||||
'views': [(False, 'form')],
|
||||
'target': 'new',
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="credit_line_printer_form" model="ir.ui.view">
|
||||
<field name="name">credit.line.printer.form</field>
|
||||
<field name="model">credit.control.printer</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lines report" version="7.0">
|
||||
<separator string="Print the selected lines" colspan="4"/>
|
||||
<newline/>
|
||||
<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')]}" />
|
||||
</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/>
|
||||
<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')]}"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- for menu -->
|
||||
<act_window name="Print Lines"
|
||||
res_model="credit.control.printer"
|
||||
src_model="credit.control.line"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="open_credit_line_printer_wizard_menu_action"/>
|
||||
|
||||
<record id="open_credit_line_printer_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Print Lines</field>
|
||||
<field name="res_model">credit.control.printer</field>
|
||||
<field name="src_model">credit.control.line</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="credit_line_printer_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="help">Print selected lines</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user