[MIG] account_credit_control: Renamed and migrated to 6.1

This commit is contained in:
@
2012-10-22 13:06:14 +02:00
committed by Pedro M. Baeza
parent 49587eb35b
commit d3305d3566
32 changed files with 5151 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# -*- 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 run
from . import line
from . import account
from . import partner
from . import policy
from . import company
import wizard
import report

View File

@@ -0,0 +1,80 @@
# -*- 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/>.
#
##############################################################################
{'name' : 'Account Credit Control',
'version' : '0.1',
'author' : 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Finance',
'complexity': "normal",
'depends' : ['base', 'account', 'email_template', 'report_webkit'],
'description': """
Credit Control
==============
Configuration
-------------
Configure the policies and policy levels in ``Accounting > Configuration >
Credit Control > Credit Policies``.
You can define as many policy levels as you need.
Configure a tolerance for the Credit control and a default policy
applied on all partners in each company, under the Accounting tab.
You are able to specify a particular policy for one partner or one invoice.
Usage
-----
Menu entries are located in ``Accounting > Periodical Processing > Credit
Control``.
Create a new "run" in the ``Credit Control Run`` menu with the controlling date.
Then, use the ``Compute credit lines`` button. All the credit control lines will
be generated. You can find them in the ``Credit Control Lines`` menu.
On each generated line, you have many choices:
* Send a email
* Print a letter
* Change the state (so you can ignore or reopen lines)
""",
'website': 'http://www.camptocamp.com',
'init_xml': ["data.xml",
],
'update_xml': ["line_view.xml",
"account_view.xml",
"partner_view.xml",
"policy_view.xml",
"run_view.xml",
"company_view.xml",
"wizard/credit_control_emailer_view.xml",
"wizard/credit_control_marker_view.xml",
"wizard/credit_control_printer_view.xml",
"report/report.xml",
"security/ir.model.access.csv",
],
'demo_xml': ["credit_control_demo.xml"],
'tests': [],
'installable': True,
'license': 'AGPL-3',
'application': True
}

View File

@@ -0,0 +1,73 @@
# -*- 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.orm import Model, fields
class AccountAccount(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)
}
class AccountInvoice(Model):
"""Add a link to a credit control policy on account.account"""
_inherit = "account.invoice"
_columns = {
'credit_policy_id': fields.many2one('credit.control.policy',
'Credit Control Policy',
help=("The Credit Control Policy "
"used for this invoice. "
"If nothing is defined, "
"it will use the account "
"setting or the partner "
"setting.")),
'credit_control_line_ids': fields.one2many('credit.control.line',
'invoice_id',
string='Credit Lines',
readonly=True)
}
def action_move_create(self, cr, uid, ids, context=None):
""" Write the id of the invoice in the generated moves. """
res = super(AccountInvoice, self).action_move_create(cr, uid, ids, context=context)
for inv in self.browse(cr, uid, ids, context=context):
if inv.move_id:
for line in inv.move_id.line_id:
line.write({'invoice_id': inv.id})
return res
class AccountMoveLine(Model):
_inherit = "account.move.line"
_columns = {'invoice_id': fields.many2one('account.invoice', 'Invoice')}

View File

@@ -0,0 +1,30 @@
<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,group_account_credit_control_info">
<field name="credit_policy_id" widget="selection"/>
<newline/>
<field name="credit_control_line_ids" colspan="4" nolabel="1"/>
</page>
</notebook>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,40 @@
# -*- 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.orm import Model, fields
class ResCompany(Model):
_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 overriden on partners or invoices.")),
}
_defaults = {"credit_control_tolerance": 0.1}

View File

@@ -0,0 +1,16 @@
<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>

View File

@@ -0,0 +1,33 @@
<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>

View File

@@ -0,0 +1,236 @@
<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="body_html"><![CDATA[
<%page args="object, user=None, ctx=None, quote=None, format_exception=True, mode='email'" />
%if mode != 'pdf':
<!-- your css here -->
<style type="text/css">
</style>
%endif
<div>
<p>Dear ${object.partner_id.name or ''},</p>
<pre class="custom_text">${object.current_policy_level.custom_text}</pre>
<table style="border: 1px solid" width="100%">
<caption><b>Summary</b></caption>
<tr>
<th>date due</th>
<th>Amount due</th>
<th>Amount balance</th>
<th>Invoice number</th>
</tr>
%for line in object.credit_control_line_ids:
<tr>
<td>${line.date_due}</td>
<td>${line.amount_due}</td>
<td>${line.balance_due}</td>
%if line.invoice_id:
<td>${line.invoice_id.number}</td>
%else:
<td>n/a</td>
%endif
%endfor
</table>
<br/>
<br/>
<p>If you have any question, do not hesitate to contact us.</p>
<p>Thank you for choosing ${object.company_id.name}! </p>
-- more info here --
<p>${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''}<br/>
${object.company_id.name}<br/>
% if object.company_id.street:
${object.company_id.street or ''}<br/>
% endif
% if object.company_id.street2:
${object.company_id.street2}<br/>
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip or ''} ${object.company_id.city or ''}<br/>
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>
% endif
% if object.company_id.phone:
Phone: ${object.company_id.phone}<br/>
% endif
% if object.company_id.website:
${object.company_id.website or ''}<br/>
% endif
]]></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>
<!-- 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">Dear Sir or Madam,
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">Dear Sir or Madam,
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">Dear Sir or Madam,
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">Dear Sir or Madam,
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">Dear Sir or Madam,
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>

View File

@@ -0,0 +1,787 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_credit_control
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 6.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-11-07 13:23+0000\n"
"PO-Revision-Date: 2012-11-07 13:23+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.2_time_1
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_1
msgid "Dear Sir or Madam,\n"
"\n"
"Our records indicate that we have not received the payment of the\n"
"above mentioned invoice (copy attached for your convenience). If it\n"
"has already been sent, please disregard this notice. If not, please\n"
"proceed with payment within 10 days.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
""
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy.level,custom_text:0
msgid "Custom Message"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_mailer
msgid "Mass credit line mailer"
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "More..."
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Group By..."
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.credit_control_run
#: model:ir.ui.menu,name:account_credit_control.credit_control_run_menu
msgid "Credit Control Run"
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy.level,computation_mode:0
msgid "Compute Mode"
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_emailer_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_emailer_wizard_menu_action
msgid "Send By Email"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_line
msgid "A credit control line"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,move_line_id:0
msgid "Move line"
msgstr ""
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_info
msgid "Credit Control Info"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_emailer
msgid "Mass credit line emailer"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,account_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_account_account
msgid "Account"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Due Date"
msgstr ""
#. module: account_credit_control
#: field:credit.control.communication,current_policy_level:0
#: field:credit.control.line,level:0
#: view:credit.control.lines:0
#: field:credit.control.policy.level,level:0
msgid "Level"
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy.level,delay_days:0
msgid "Delay (in days)"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_communication
msgid "credit control communication"
msgstr ""
#. module: account_credit_control
#: sql_constraint:account.move.line:0
msgid "Wrong credit or debit value in accounting entry !"
msgstr ""
#. module: account_credit_control
#: constraint:account.account:0
msgid "Error ! You can not create recursive accounts."
msgstr ""
#. module: account_credit_control
#: view:credit.control.emailer:0
msgid "Send emails for the selected lines"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_marker
msgid "Mass marker"
msgstr ""
#. module: account_credit_control
#: field:account.invoice,credit_policy_id:0
#: field:res.company,credit_policy_id:0
#: field:res.partner,credit_policy_id:0
msgid "Credit Control Policy"
msgstr ""
#. module: account_credit_control
#: view:account.invoice:0
msgid "Credit control"
msgstr ""
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal."
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "New lines"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,date_sent:0
msgid "Sent date"
msgstr ""
#. module: account_credit_control
#: view:credit.control.policy:0
#: field:credit.control.policy,account_ids:0
msgid "Accounts"
msgstr ""
#. module: account_credit_control
#: field:credit.control.communication,partner_id:0
#: field:credit.control.line,partner_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_res_partner
msgid "Partner"
msgstr ""
#. module: account_credit_control
#: view:credit.control.emailer:0
msgid "Send the emails"
msgstr ""
#. module: account_credit_control
#: view:credit.control.marker:0
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_marker_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_marker_wizard_menu_action
msgid "Change Lines' State"
msgstr ""
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_2
msgid "Dear Sir or Madam,\n"
"\n"
"Our records indicate that we have not yet received the payment of the\n"
"above mentioned invoice (copy attached for your convenience) despite\n"
"our first reminder. If it has already been sent, please disregard\n"
"this notice. If not, please proceed with payment within 5 days.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
""
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy.level,policy_id:0
msgid "Related Policy"
msgstr ""
#. module: account_credit_control
#: sql_constraint:account.account:0
msgid "The code of the account must be unique per company !"
msgstr ""
#. module: account_credit_control
#: constraint:res.company:0
msgid "Error! You can not create recursive companies."
msgstr ""
#. module: account_credit_control
#: view:credit.control.policy:0
#: view:credit.control.policy.level:0
msgid "Mail and reporting"
msgstr ""
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Print"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,channel:0
#: selection:credit.control.policy.level,channel:0
msgid "Email"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,channel:0
#: view:credit.control.lines:0
#: field:credit.control.policy.level,channel:0
msgid "Channel"
msgstr ""
#. module: account_credit_control
#: help:credit.control.run,manual_ids:0
msgid "If a credit control line has been generated on a policy and the policy has been changed meantime, it has to be handled manually"
msgstr ""
#. module: account_credit_control
#: field:credit.control.printer,state:0
msgid "state"
msgstr ""
#. module: account_credit_control
#: field:credit.control.run,report:0
msgid "Report"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Due Date, End Of Month"
msgstr ""
#. module: account_credit_control
#: field:credit.control.marker,name:0
msgid "Mark as"
msgstr ""
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.2_time_2
msgid "Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our reminder.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
""
msgstr ""
#. module: account_credit_control
#: view:credit.control.run:0
#: field:credit.control.run,policy_ids:0
msgid "Policies"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,date_due:0
msgid "Due date"
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy,do_nothing:0
msgid "Do nothing"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,currency_id:0
msgid "Currency"
msgstr ""
#. module: account_credit_control
#: constraint:account.account:0
msgid "Configuration Error! \n"
"You can not define children to an account with internal type different of \"View\"! "
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_printer
msgid "Mass printer"
msgstr ""
#. module: account_credit_control
#: field:credit.control.communication,company_id:0
#: field:credit.control.line,company_id:0
#: field:credit.control.policy,company_id:0
msgid "Company"
msgstr ""
#. module: account_credit_control
#: view:credit.control.marker:0
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_marker_wizard
msgid "Change the state of the selected lines."
msgstr ""
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Print the selected lines"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
#: selection:credit.control.marker,name:0
#: selection:credit.control.run,state:0
msgid "Draft"
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Credit policy"
msgstr ""
#. module: account_credit_control
#: view:credit.control.policy:0
#: view:credit.control.policy.level:0
msgid "Delay Setting"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,balance_due:0
msgid "Due balance"
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Credit policy level"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_run
msgid "Credit control line generator"
msgstr ""
#. module: account_credit_control
#: field:credit.control.communication,user_id:0
msgid "User"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,channel:0
#: selection:credit.control.policy.level,channel:0
msgid "Letter"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_account_move_line
msgid "Journal Items"
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_printer_wizard
msgid "Print selected lines"
msgstr ""
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "You can not create journal items on an account of type view."
msgstr ""
#. module: account_credit_control
#: field:credit.control.emailer,line_ids:0
#: field:credit.control.marker,line_ids:0
#: field:credit.control.printer,line_ids:0
#: model:ir.actions.act_window,name:account_credit_control.credit_control_line_action
#: model:ir.ui.menu,name:account_credit_control.credit_control_line_action_menu
#: field:res.partner,credit_control_line_ids:0
msgid "Credit Control Lines"
msgstr ""
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_3
msgid "Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our two reminders.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
""
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_printer_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_printer_wizard_menu_action
msgid "Print Lines"
msgstr ""
#. module: account_credit_control
#: field:credit.control.run,date:0
msgid "Controlling Date"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_policy
msgid "Define a reminder policy"
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy.level,email_template_id:0
msgid "Email Template"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
#: selection:credit.control.marker,name:0
msgid "Ready To Send"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_res_company
msgid "Companies"
msgstr ""
#. module: account_credit_control
#: field:credit.control.printer,mark_as_sent:0
msgid "Mark letter lines as sent"
msgstr ""
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Compute Credit Control Lines"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Previous Reminder"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
msgid "Error"
msgstr ""
#. module: account_credit_control
#: sql_constraint:account.invoice:0
msgid "Invoice Number must be unique per Company!"
msgstr ""
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Report and Errors"
msgstr ""
#. module: account_credit_control
#: constraint:account.account:0
msgid "Configuration Error! \n"
"You can not select an account type with a deferral method different of \"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,state:0
#: field:credit.control.run,state:0
msgid "State"
msgstr ""
#. module: account_credit_control
#: help:credit.control.policy,do_nothing:0
msgid "For policies which should not generate lines or are obsolete"
msgstr ""
#. module: account_credit_control
#: field:account.account,credit_control_line_ids:0
#: field:account.invoice,credit_control_line_ids:0
#: field:credit.control.communication,credit_control_line_ids:0
#: model:ir.actions.act_window,name:account_credit_control.act_account_credit_relation_relation
#: model:ir.actions.act_window,name:account_credit_control.act_partner_credit_relation_relation
msgid "Credit Lines"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: selection:credit.control.marker,name:0
#: selection:credit.control.run,state:0
msgid "Done"
msgstr ""
#. module: account_credit_control
#: field:account.move.line,invoice_id:0
#: field:credit.control.line,invoice_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_account_invoice
msgid "Invoice"
msgstr ""
#. module: account_credit_control
#: view:credit.control.emailer:0
#: view:credit.control.marker:0
#: view:credit.control.printer:0
msgid "Cancel"
msgstr ""
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Close"
msgstr ""
#. module: account_credit_control
#: selection:credit.control.line,state:0
msgid "Emailing Error"
msgstr ""
#. module: account_credit_control
#: help:account.invoice,credit_policy_id:0
msgid "The Credit Control Policy used for this invoice. If nothing is defined, it will use the account setting or the partner setting."
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Run date"
msgstr ""
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_user
msgid "Credit Control User"
msgstr ""
#. module: account_credit_control
#: model:email.template,body_html:account_credit_control.email_template_credit_control_base
msgid "\n"
" <%page args=\"object, user=None, ctx=None, quote=None, format_exception=True, mode='mail'\" />\n"
" %if mode != 'pdf':\n"
" <!-- your css here -->\n"
" <style type=\"text/css\">\n"
" </style>\n"
" %endif\n"
" <div>\n"
"\n"
" <p>Dear ${object.partner_id.name or ''},</p>\n"
"\n"
" <pre class=\"custom_text\">${object.current_policy_level.custom_text}</pre>\n"
"\n"
" <table style=\"border: 1px solid\" width=\"100%\">\n"
" <caption><b>Summary</b></caption>\n"
" <tr>\n"
" <th>date due</th>\n"
" <th>Amount due</th>\n"
" <th>Amount balance</th>\n"
" <th>Invoice number</th>\n"
" </tr>\n"
"%for line in object.credit_control_line_ids:\n"
" <tr>\n"
" <td>${line.date_due}</td>\n"
" <td>${line.amount_due}</td>\n"
" <td>${line.balance_due}</td>\n"
" %if line.invoice_id:\n"
" <td>${line.invoice_id.number}</td>\n"
" %else:\n"
" <td>n/a</td>\n"
" %endif\n"
"%endfor\n"
" </table>\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p>If you have any question, do not hesitate to contact us.</p>\n"
"\n"
" <p>Thank you for choosing ${object.company_id.name}! </p>\n"
"\n"
" -- more info here --\n"
" <p>${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''}<br/>\n"
" ${object.company_id.name}<br/>\n"
" % if object.company_id.street:\n"
" ${object.company_id.street or ''}<br/>\n"
"\n"
" % endif\n"
"\n"
" % if object.company_id.street2:\n"
" ${object.company_id.street2}<br/>\n"
" % endif\n"
" % if object.company_id.city or object.company_id.zip:\n"
" ${object.company_id.zip or ''} ${object.company_id.city or ''}<br/>\n"
" % endif\n"
" % if object.company_id.country_id:\n"
" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" % if object.company_id.phone:\n"
" Phone: ${object.company_id.phone}<br/>\n"
" % endif\n"
" % if object.company_id.website:\n"
" ${object.company_id.website or ''}<br/>\n"
" % endif\n"
" "
msgstr ""
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "Company must be the same for its related account and period."
msgstr ""
#. module: account_credit_control
#: field:credit.control.run,manual_ids:0
msgid "Lines to handle manually"
msgstr ""
#. module: account_credit_control
#: model:ir.ui.menu,name:account_credit_control.base_credit_control_configuration_menu
#: model:ir.ui.menu,name:account_credit_control.base_credit_control_menu
msgid "Credit Control"
msgstr ""
#. module: account_credit_control
#: view:credit.control.policy:0
#: field:credit.control.policy,level_ids:0
msgid "Policy Levels"
msgstr ""
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "The selected account of your Journal Entry forces to provide a secondary currency. You should remove the secondary currency on the account or select a multi-currency view on the journal."
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,policy_id:0
msgid "Policy"
msgstr ""
#. module: account_credit_control
#: model:email.template,subject:account_credit_control.email_template_credit_control_base
msgid "Credit Control: (${object.current_policy_level.name or 'n/a' })"
msgstr ""
#. module: account_credit_control
#: field:credit.control.printer,report_file:0
msgid "Generated Report"
msgstr ""
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Move lines To be treated manually"
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.credit_policy_configuration_action
#: model:ir.ui.menu,name:account_credit_control.credit_policy_configuration_action_menu
msgid "Credit Control Policies"
msgstr ""
#. module: account_credit_control
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_emailer_wizard
msgid "Send an email for the selected lines."
msgstr ""
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Sent"
msgstr ""
#. module: account_credit_control
#: constraint:credit.control.policy.level:0
msgid "The smallest level can not be of type Previous Reminder"
msgstr ""
#. module: account_credit_control
#: help:credit.control.policy,account_ids:0
msgid "This policy will be active only for the selected accounts"
msgstr ""
#. module: account_credit_control
#: help:credit.control.printer,mark_as_sent:0
msgid "Only letter lines will be marked."
msgstr ""
#. module: account_credit_control
#: view:credit.control.line:0
#: view:credit.control.lines:0
msgid "Control Credit Lines"
msgstr ""
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_manager
msgid "Credit Control Manager"
msgstr ""
#. module: account_credit_control
#: sql_constraint:res.company:0
msgid "The company name must be unique !"
msgstr ""
#. module: account_credit_control
#: field:credit.control.policy,name:0
#: field:credit.control.policy.level,name:0
msgid "Name"
msgstr ""
#. module: account_credit_control
#: help:res.partner,credit_policy_id:0
msgid "The Credit Control Policyused for this partner. This setting can be forced on the invoice. If nothing is defined, it will use the company setting."
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,mail_message_id:0
msgid "Sent Email"
msgstr ""
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_policy_level
msgid "A credit control policy level"
msgstr ""
#. module: account_credit_control
#: model:ir.actions.report.xml,name:account_credit_control.report_webkit_html
msgid "Credit Summary"
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,date:0
msgid "Controlling date"
msgstr ""
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "You can not create journal items on closed account."
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,amount_due:0
msgid "Due Amount Tax incl."
msgstr ""
#. module: account_credit_control
#: field:res.company,credit_control_tolerance:0
msgid "Credit Control Tolerance"
msgstr ""
#. module: account_credit_control
#: help:res.company,credit_policy_id:0
msgid "The Credit Control Policy used on partners by default. This setting can be overriden on partners or invoices."
msgstr ""
#. module: account_credit_control
#: field:credit.control.line,policy_level_id:0
msgid "Overdue Level"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,965 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_credit_control
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 6.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-11-07 15:35+0000\n"
"PO-Revision-Date: 2012-11-07 16:41+0100\n"
"Last-Translator: Guewen Baconnier <guewen.baconnier@camptocamp.com>\n"
"Language-Team: FR\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.2_time_1
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_1
msgid ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we have not received the payment of the\n"
"above mentioned invoice (copy attached for your convenience). If it\n"
"has already been sent, please disregard this notice. If not, please\n"
"proceed with payment within 10 days.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
msgstr ""
"Madame, Monsieur,\n"
"\n"
"Il résulte d'une récente révision de nos comptes que la facture\n"
"susmentionnée (copie ci-jointe) reste, sauf erreur, impayée à ce\n"
"jour. Si tel est bien le cas, nous vous invitons à réparer cet oubli\n"
"sous 10 jours. Dans le cas contraire, nous vous prions de nous\n"
"indiquer la date de votre paiement et vous remercions d'excuser le\n"
"présent courriel.\n"
"\n"
"Pour toute question, nous restons à votre disposition.\n"
"\n"
"Bien cordialement,\n"
#. module: account_credit_control
#: field:credit.control.policy.level,custom_text:0
msgid "Custom Message"
msgstr "Message Personnalisé"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "More..."
msgstr "Plus..."
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Group By..."
msgstr "Group By..."
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.credit_control_run
#: model:ir.ui.menu,name:account_credit_control.credit_control_run_menu
msgid "Credit Control Run"
msgstr "Contrôles de Crédit"
#. module: account_credit_control
#: field:credit.control.policy.level,computation_mode:0
msgid "Compute Mode"
msgstr "Mode de calcul"
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_emailer_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_emailer_wizard_menu_action
msgid "Send By Email"
msgstr "Envoyer par courrier électronique"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_line
msgid "A credit control line"
msgstr "Ligne de contrôle de crédit"
#. module: account_credit_control
#: field:credit.control.line,move_line_id:0
msgid "Move line"
msgstr "Écritures comptables"
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_info
msgid "Credit Control Info"
msgstr "Informations de contrôle de crédit"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_emailer
msgid "Mass credit line emailer"
msgstr "Envoi de courriers électroniques en masse"
#. module: account_credit_control
#: field:credit.control.line,account_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_account_account
msgid "Account"
msgstr "Compte"
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Due Date"
msgstr "Date d'échéance"
#. module: account_credit_control
#: field:credit.control.communication,current_policy_level:0
#: field:credit.control.line,level:0
#: view:credit.control.lines:0
#: field:credit.control.policy.level,level:0
msgid "Level"
msgstr "Niveau"
#. module: account_credit_control
#: field:credit.control.policy.level,delay_days:0
msgid "Delay (in days)"
msgstr "Délai (en jours)"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_communication
msgid "credit control communication"
msgstr "Communication de contrôle de crédit"
#. module: account_credit_control
#: sql_constraint:account.move.line:0
msgid "Wrong credit or debit value in accounting entry !"
msgstr "Mauvaise entrée de crédit ou de débit dans la comptabilité !"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "These lines are ready to send by email or by letter using the Actions."
msgstr "These lines are ready to send by email or by letter using the Actions."
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_marker
msgid "Mass marker"
msgstr "Changer d'état en masse"
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
#: selection:credit.control.marker,name:0
msgid "Ignored"
msgstr "Ignoré"
#. module: account_credit_control
#: view:credit.control.emailer:0
msgid "Send emails for the selected lines"
msgstr "Envoyer des courriers électroniques pour les lignes sélectionnées"
#. module: account_credit_control
#: constraint:account.account:0
msgid "Error ! You can not create recursive accounts."
msgstr "La création de comptes récursifs est interdite"
#. module: account_credit_control
#: field:account.invoice,credit_policy_id:0
#: field:res.company,credit_policy_id:0
#: field:res.partner,credit_policy_id:0
msgid "Credit Control Policy"
msgstr "Politique de contrôle de crédit"
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal."
msgstr ""
"La date de l'entrée de journal n'est pas dans la période choisie. Il\n"
"faut changer la date ou supprimer la contrainte du journal."
#. module: account_credit_control
#: field:credit.control.line,date_sent:0
msgid "Sent date"
msgstr "Date d'envoi"
#. module: account_credit_control
#: view:credit.control.policy:0
#: field:credit.control.policy,account_ids:0
msgid "Accounts"
msgstr "Comptes"
#. module: account_credit_control
#: field:credit.control.communication,partner_id:0
#: field:credit.control.line,partner_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_res_partner
msgid "Partner"
msgstr "Partenaire"
#. module: account_credit_control
#: view:credit.control.emailer:0
msgid "Send the emails"
msgstr "Envoyer les courriers électroniques"
#. module: account_credit_control
#: view:credit.control.marker:0
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_marker_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_marker_wizard_menu_action
msgid "Change Lines' State"
msgstr "Changer l'état des lignes"
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_2
msgid ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we have not yet received the payment of the\n"
"above mentioned invoice (copy attached for your convenience) despite\n"
"our first reminder. If it has already been sent, please disregard\n"
"this notice. If not, please proceed with payment within 5 days.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
msgstr ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we have not yet received the payment of the\n"
"above mentioned invoice (copy attached for your convenience) despite\n"
"our first reminder. If it has already been sent, please disregard\n"
"this notice. If not, please proceed with payment within 5 days.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
#. module: account_credit_control
#: field:credit.control.policy.level,policy_id:0
msgid "Related Policy"
msgstr "Politique liée"
#. module: account_credit_control
#: sql_constraint:account.account:0
msgid "The code of the account must be unique per company !"
msgstr "Le code du compte doit être unique pour une société donnée."
#. module: account_credit_control
#: constraint:res.company:0
msgid "Error! You can not create recursive companies."
msgstr "Il est interdit de créer des sociétés récursives."
#. module: account_credit_control
#: view:credit.control.policy:0
#: view:credit.control.policy.level:0
msgid "Mail and reporting"
msgstr "Courriers et rapports"
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Print"
msgstr "Imprimer"
#. module: account_credit_control
#: selection:credit.control.line,channel:0
#: selection:credit.control.policy.level,channel:0
msgid "Email"
msgstr "Email"
#. module: account_credit_control
#: field:credit.control.line,channel:0
#: view:credit.control.lines:0
#: field:credit.control.policy.level,channel:0
msgid "Channel"
msgstr "Canal"
#. module: account_credit_control
#: help:credit.control.run,manual_ids:0
msgid "If a credit control line has been generated on a policy and the policy has been changed meantime, it has to be handled manually"
msgstr ""
"Si une ligne de contrôle de crédit a été générée sur une politique et\n"
"que la politique a changé entre temps, il faut traiter cette ligne manuellement."
#. module: account_credit_control
#: field:credit.control.printer,state:0
msgid "state"
msgstr "état"
#. module: account_credit_control
#: field:credit.control.run,report:0
msgid "Report"
msgstr "Rapport"
#. module: account_credit_control
#: help:credit.control.line,state:0
msgid ""
"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."
msgstr ""
"Les lignes \"Brouillon\" nécessitent d'être triées.\n"
"Les lignes \"Ignorées\" sont celles pour lesquelles rien ne doit être envoyé.\n"
"Les lignes brouillon et ignorées seront régénérées lors du prochain lancement du contrôle de crédit."
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Due Date, End Of Month"
msgstr "Date due, fin de mois"
#. module: account_credit_control
#: field:credit.control.marker,name:0
msgid "Mark as"
msgstr "Marquer comme"
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.2_time_2
msgid ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our reminder.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
msgstr ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our reminder.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "An error has occured during the sending of the email."
msgstr "Une erreur s'est produit durant l'envoi du mail."
#. module: account_credit_control
#: view:credit.control.run:0
#: field:credit.control.run,policy_ids:0
msgid "Policies"
msgstr "Politiques"
#. module: account_credit_control
#: field:credit.control.line,date_due:0
msgid "Due date"
msgstr "Date d'échéance"
#. module: account_credit_control
#: field:credit.control.policy,do_nothing:0
msgid "Do nothing"
msgstr "Ne rien faire"
#. module: account_credit_control
#: field:credit.control.line,currency_id:0
msgid "Currency"
msgstr "Devise"
#. module: account_credit_control
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not define children to an account with internal type different of \"View\"! "
msgstr ""
"Configuration Error! \n"
"You can not define children to an account with internal type different of \"View\"! "
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_printer
msgid "Mass printer"
msgstr "Impression groupée"
#. module: account_credit_control
#: field:credit.control.communication,company_id:0
#: field:credit.control.line,company_id:0
#: field:credit.control.policy,company_id:0
msgid "Company"
msgstr "Société"
#. module: account_credit_control
#: view:credit.control.marker:0
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_marker_wizard
msgid "Change the state of the selected lines."
msgstr "Changer l'état des lignes sélectionnées."
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Lines which have been ignored from previous runs."
msgstr "Lignes qui ont été ignorées lors des précédents lancement."
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Print the selected lines"
msgstr "Imprimer les lignes sélectionnées"
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
#: selection:credit.control.run,state:0
msgid "Draft"
msgstr "Brouillon"
#. module: account_credit_control
#: view:credit.control.marker:0
msgid "Warning: you will maybe not be able to revert this operation."
msgstr "Attention: vous ne pourrez peut-être pas annuler cette opération."
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Credit policy"
msgstr "Politique de crédit"
#. module: account_credit_control
#: view:credit.control.policy:0
#: view:credit.control.policy.level:0
msgid "Delay Setting"
msgstr "Réglage du délai"
#. module: account_credit_control
#: field:credit.control.line,balance_due:0
msgid "Due balance"
msgstr "Solde du"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Credit policy level"
msgstr "Niveau de politique de crédit"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_run
msgid "Credit control line generator"
msgstr "Générateur de ligne de contrôle de crédit"
#. module: account_credit_control
#: field:credit.control.communication,user_id:0
msgid "User"
msgstr "Utilisateur"
#. module: account_credit_control
#: selection:credit.control.line,channel:0
#: selection:credit.control.policy.level,channel:0
msgid "Letter"
msgstr "Lettre"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_account_move_line
msgid "Journal Items"
msgstr "Écritures comptables"
#. module: account_credit_control
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_printer_wizard
msgid "Print selected lines"
msgstr "Imprimer les lignes sélectionnées"
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "You can not create journal items on an account of type view."
msgstr "La création de comptes récursifs est interdite"
#. module: account_credit_control
#: field:credit.control.emailer,line_ids:0
#: field:credit.control.marker,line_ids:0
#: field:credit.control.printer,line_ids:0
#: model:ir.actions.act_window,name:account_credit_control.credit_control_line_action
#: model:ir.ui.menu,name:account_credit_control.credit_control_line_action_menu
#: field:res.partner,credit_control_line_ids:0
msgid "Credit Control Lines"
msgstr "Lignes de contrôle de crédit"
#. module: account_credit_control
#: model:credit.control.policy.level,custom_text:account_credit_control.3_time_3
msgid ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our two reminders.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
msgstr ""
"Dear Sir or Madam,\n"
"\n"
"Our records indicate that we still have not received the payment of\n"
"the above mentioned invoice (copy attached) despite our two reminders.\n"
"If payment have already been sent, please disregard this notice. If\n"
"not, please proceed with payment. If your payment has not been\n"
"received in the next 5 days, your file will be transfered to our debt\n"
"collection agency.\n"
"\n"
"Should you need us to arrange a payment plan for you, please advise.\n"
"A customer account statement is enclosed for you convenience.\n"
"\n"
"Thank you in advance for your anticipated cooperation in this matter.\n"
"\n"
"Best regards,\n"
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_printer_wizard
#: model:ir.actions.act_window,name:account_credit_control.open_credit_line_printer_wizard_menu_action
msgid "Print Lines"
msgstr "Imprimer les lignes"
#. module: account_credit_control
#: field:credit.control.run,date:0
msgid "Controlling Date"
msgstr "Date de contrôle"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_policy
msgid "Define a reminder policy"
msgstr "Définir une politique de rappel"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Lines already sent."
msgstr "Déjà envoyé."
#. module: account_credit_control
#: field:credit.control.policy.level,email_template_id:0
msgid "Email Template"
msgstr "Modèle de courrier électronique"
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
#: selection:credit.control.marker,name:0
msgid "Ready To Send"
msgstr "Prêt à envoyer"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: account_credit_control
#: field:credit.control.printer,mark_as_sent:0
msgid "Mark letter lines as sent"
msgstr "Marquer les lignes \"lettre\" comme envoyées"
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Compute Credit Control Lines"
msgstr "Calcul des lignes de contrôle de crédit"
#. module: account_credit_control
#: selection:credit.control.policy.level,computation_mode:0
msgid "Previous Reminder"
msgstr "Rappel précédent"
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: view:credit.control.lines:0
msgid "Error"
msgstr "Erreur"
#. module: account_credit_control
#: sql_constraint:account.invoice:0
msgid "Invoice Number must be unique per Company!"
msgstr "Le code du compte doit être unique pour une société donnée."
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Report and Errors"
msgstr "Rapport et erreurs"
#. module: account_credit_control
#: constraint:account.account:0
msgid ""
"Configuration Error! \n"
"You can not select an account type with a deferral method different of \"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
msgstr ""
"Configuration Error! \n"
"You can not select an account type with a deferral method different of \"Unreconciled\" for accounts with internal type \"Payable/Receivable\"! "
#. module: account_credit_control
#: field:credit.control.line,state:0
#: field:credit.control.run,state:0
msgid "State"
msgstr "État"
#. module: account_credit_control
#: help:credit.control.policy,do_nothing:0
msgid "For policies which should not generate lines or are obsolete"
msgstr ""
"Pour les politiques qui ne devraient pas générer de lignes ou qui sont\n"
"obsolètes"
#. module: account_credit_control
#: field:account.account,credit_control_line_ids:0
#: field:account.invoice,credit_control_line_ids:0
#: field:credit.control.communication,credit_control_line_ids:0
#: model:ir.actions.act_window,name:account_credit_control.act_account_credit_relation_relation
#: model:ir.actions.act_window,name:account_credit_control.act_partner_credit_relation_relation
msgid "Credit Lines"
msgstr "Lignes de crédit"
#. module: account_credit_control
#: selection:credit.control.line,state:0
#: selection:credit.control.marker,name:0
#: selection:credit.control.run,state:0
msgid "Done"
msgstr "Terminé"
#. module: account_credit_control
#: field:account.move.line,invoice_id:0
#: field:credit.control.line,invoice_id:0
#: view:credit.control.lines:0
#: model:ir.model,name:account_credit_control.model_account_invoice
msgid "Invoice"
msgstr "Facture"
#. module: account_credit_control
#: view:credit.control.emailer:0
#: view:credit.control.marker:0
#: view:credit.control.printer:0
msgid "Cancel"
msgstr "Annuler"
#. module: account_credit_control
#: view:credit.control.printer:0
msgid "Close"
msgstr "Fermer"
#. module: account_credit_control
#: selection:credit.control.line,state:0
msgid "Emailing Error"
msgstr "Erreur d'envoi de message"
#. module: account_credit_control
#: help:account.invoice,credit_policy_id:0
msgid "The Credit Control Policy used for this invoice. If nothing is defined, it will use the account setting or the partner setting."
msgstr ""
"La politique de contrôle de crédit utilisée par cette facture. Par\n"
"défault, la politique définie au niveau du Compte ou du Partenaire est\n"
"utilisée."
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Run date"
msgstr "Date de lancement"
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_user
msgid "Credit Control User"
msgstr "Utilisateur du contrôle de crédit"
#. module: account_credit_control
#: model:email.template,body_html:account_credit_control.email_template_credit_control_base
msgid ""
"\n"
" <%page args=\"object, user=None, ctx=None, quote=None, format_exception=True, mode='mail'\" />\n"
" %if mode != 'pdf':\n"
" <!-- your css here -->\n"
" <style type=\"text/css\">\n"
" </style>\n"
" %endif\n"
" <div>\n"
"\n"
" <p>Dear ${object.partner_id.name or ''},</p>\n"
"\n"
" <pre class=\"custom_text\">${object.current_policy_level.custom_text}</pre>\n"
"\n"
" <table style=\"border: 1px solid\" width=\"100%\">\n"
" <caption><b>Summary</b></caption>\n"
" <tr>\n"
" <th>date due</th>\n"
" <th>Amount due</th>\n"
" <th>Amount balance</th>\n"
" <th>Invoice number</th>\n"
" </tr>\n"
"%for line in object.credit_control_line_ids:\n"
" <tr>\n"
" <td>${line.date_due}</td>\n"
" <td>${line.amount_due}</td>\n"
" <td>${line.balance_due}</td>\n"
" %if line.invoice_id:\n"
" <td>${line.invoice_id.number}</td>\n"
" %else:\n"
" <td>n/a</td>\n"
" %endif\n"
"%endfor\n"
" </table>\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p>If you have any question, do not hesitate to contact us.</p>\n"
"\n"
" <p>Thank you for choosing ${object.company_id.name}! </p>\n"
"\n"
" -- more info here --\n"
" <p>${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''}<br/>\n"
" ${object.company_id.name}<br/>\n"
" % if object.company_id.street:\n"
" ${object.company_id.street or ''}<br/>\n"
"\n"
" % endif\n"
"\n"
" % if object.company_id.street2:\n"
" ${object.company_id.street2}<br/>\n"
" % endif\n"
" % if object.company_id.city or object.company_id.zip:\n"
" ${object.company_id.zip or ''} ${object.company_id.city or ''}<br/>\n"
" % endif\n"
" % if object.company_id.country_id:\n"
" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" % if object.company_id.phone:\n"
" Phone: ${object.company_id.phone}<br/>\n"
" % endif\n"
" % if object.company_id.website:\n"
" ${object.company_id.website or ''}<br/>\n"
" % endif\n"
" "
msgstr ""
"\n"
" <%page args=\"object, user=None, ctx=None, quote=None, format_exception=True, mode='mail'\" />\n"
" %if mode != 'pdf':\n"
" <!-- your css here -->\n"
" <style type=\"text/css\">\n"
" </style>\n"
" %endif\n"
" <div>\n"
"\n"
" <p>Cher ${object.partner_id.name or ''},</p>\n"
"\n"
" <pre class=\"custom_text\">${object.current_policy_level.custom_text}</pre>\n"
"\n"
" <table style=\"border: 1px solid\" width=\"100%\">\n"
" <caption><b>Summary</b></caption>\n"
" <tr>\n"
" <th>Date due</th>\n"
" <th>Somme due</th>\n"
" <th>Solde du</th>\n"
" <th>Numéro de facture</th>\n"
" </tr>\n"
"%for line in object.credit_control_line_ids:\n"
" <tr>\n"
" <td>${line.date_due}</td>\n"
" <td>${line.amount_due}</td>\n"
" <td>${line.balance_due}</td>\n"
" %if line.invoice_id:\n"
" <td>${line.invoice_id.number}</td>\n"
" %else:\n"
" <td>n/a</td>\n"
" %endif\n"
"%endfor\n"
" </table>\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p>Si vous avez des questions n'hésitez pas à nous contacter.</p>\n"
"\n"
" <p>Merci d'avoir choisi ${object.company_id.name}! </p>\n"
"\n"
" -- more info here --\n"
" <p>${object.user_id.name} ${object.user_id.user_email and '<%s>'%(object.user_id.user_email) or ''}<br/>\n"
" ${object.company_id.name}<br/>\n"
" % if object.company_id.street:\n"
" ${object.company_id.street or ''}<br/>\n"
"\n"
" % endif\n"
"\n"
" % if object.company_id.street2:\n"
" ${object.company_id.street2}<br/>\n"
" % endif\n"
" % if object.company_id.city or object.company_id.zip:\n"
" ${object.company_id.zip or ''} ${object.company_id.city or ''}<br/>\n"
" % endif\n"
" % if object.company_id.country_id:\n"
" ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" % if object.company_id.phone:\n"
" Téléphone : ${object.company_id.phone}<br/>\n"
" % endif\n"
" % if object.company_id.website:\n"
" ${object.company_id.website or ''}<br/>\n"
" % endif\n"
" "
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "Company must be the same for its related account and period."
msgstr "Company must be the same for its related account and period."
#. module: account_credit_control
#: field:credit.control.run,manual_ids:0
msgid "Lines to handle manually"
msgstr "Lignes à traiter manuellement"
#. module: account_credit_control
#: view:account.invoice:0
#: model:ir.ui.menu,name:account_credit_control.base_credit_control_configuration_menu
#: model:ir.ui.menu,name:account_credit_control.base_credit_control_menu
msgid "Credit Control"
msgstr "Contrôle de crédit"
#. module: account_credit_control
#: view:credit.control.policy:0
#: field:credit.control.policy,level_ids:0
msgid "Policy Levels"
msgstr "Niveaux de politique"
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "The selected account of your Journal Entry forces to provide a secondary currency. You should remove the secondary currency on the account or select a multi-currency view on the journal."
msgstr "The selected account of your Journal Entry forces to provide a secondary currency. You should remove the secondary currency on the account or select a multi-currency view on the journal."
#. module: account_credit_control
#: field:credit.control.line,policy_id:0
msgid "Policy"
msgstr "Politique"
#. module: account_credit_control
#: model:email.template,subject:account_credit_control.email_template_credit_control_base
msgid "Credit Control: (${object.current_policy_level.name or 'n/a' })"
msgstr "Contrôle de crédit : (${object.current_policy_level.name or 'n/a' })"
#. module: account_credit_control
#: field:credit.control.printer,report_file:0
msgid "Generated Report"
msgstr "Rapport généré"
#. module: account_credit_control
#: view:credit.control.run:0
msgid "Move lines To be treated manually"
msgstr "Lignes à traiter manuellement"
#. module: account_credit_control
#: model:ir.actions.act_window,name:account_credit_control.credit_policy_configuration_action
#: model:ir.ui.menu,name:account_credit_control.credit_policy_configuration_action_menu
msgid "Credit Control Policies"
msgstr "Politique de contrôle de crédit"
#. module: account_credit_control
#: model:ir.actions.act_window,help:account_credit_control.open_credit_line_emailer_wizard
msgid "Send an email for the selected lines."
msgstr "Envoyer un courrier électronique pour les lignes sélectionnées"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Sent"
msgstr "Envoyer"
#. module: account_credit_control
#: constraint:credit.control.policy.level:0
msgid "The smallest level can not be of type Previous Reminder"
msgstr "Le niveau le plus bas ne peut pas être de type \"Rappel Précédent\""
#. module: account_credit_control
#: help:credit.control.policy,account_ids:0
msgid "This policy will be active only for the selected accounts"
msgstr "Cette politique sera activée pour les comptes sélectionnés"
#. module: account_credit_control
#: help:credit.control.printer,mark_as_sent:0
msgid "Only letter lines will be marked."
msgstr "Seules les lignes \"lettre\" seront marquées."
#. module: account_credit_control
#: view:credit.control.line:0
#: view:credit.control.lines:0
msgid "Control Credit Lines"
msgstr "Lignes de contrôle de crédit"
#. module: account_credit_control
#: model:res.groups,name:account_credit_control.group_account_credit_control_manager
msgid "Credit Control Manager"
msgstr "Gestionnaire de contrôle de crédit"
#. module: account_credit_control
#: sql_constraint:res.company:0
msgid "The company name must be unique !"
msgstr "The company name must be unique !"
#. module: account_credit_control
#: field:credit.control.policy,name:0
#: field:credit.control.policy.level,name:0
msgid "Name"
msgstr "Nom"
#. module: account_credit_control
#: help:res.partner,credit_policy_id:0
msgid "The Credit Control Policyused for this partner. This setting can be forced on the invoice. If nothing is defined, it will use the company setting."
msgstr ""
"Politique de contrôle de crédit pour ce partenaire. Il est possible de\n"
"forcer ce réglage pour une facture donnée. Par défaut, la politique de\n"
"la société est utilisée."
#. module: account_credit_control
#: field:credit.control.line,mail_message_id:0
msgid "Sent Email"
msgstr "Envoyer le courrier électronique"
#. module: account_credit_control
#: model:ir.model,name:account_credit_control.model_credit_control_policy_level
msgid "A credit control policy level"
msgstr "Un niveau de politique de contrôle de crédit"
#. module: account_credit_control
#: model:ir.actions.report.xml,name:account_credit_control.report_webkit_html
msgid "Credit Summary"
msgstr "Synthèse du crédit"
#. module: account_credit_control
#: field:credit.control.line,date:0
msgid "Controlling date"
msgstr "Date de contrôle"
#. module: account_credit_control
#: constraint:account.move.line:0
msgid "You can not create journal items on closed account."
msgstr "La création de comptes récursifs est interdite"
#. module: account_credit_control
#: view:credit.control.lines:0
msgid "Draft lines have to be triaged."
msgstr "Les lignes en brouillon doivent être triées."
#. module: account_credit_control
#: field:credit.control.line,amount_due:0
msgid "Due Amount Tax incl."
msgstr "Somme dûe TTC"
#. module: account_credit_control
#: field:res.company,credit_control_tolerance:0
msgid "Credit Control Tolerance"
msgstr "Tolérance de contrôle de crédit"
#. module: account_credit_control
#: help:res.company,credit_policy_id:0
msgid "The Credit Control Policy used on partners by default. This setting can be overriden on partners or invoices."
msgstr ""
"Politique de contrôle de crédit par défaut. Elle peut être redéfinie\n"
"au niveau des partenaires ou des factures."
#. module: account_credit_control
#: field:credit.control.line,policy_level_id:0
msgid "Overdue Level"
msgstr "Niveau de créance"
#~ msgid "Mass credit line mailer"
#~ msgstr "Envoi de mails en masse"
#~ msgid "Credit control"
#~ msgstr "Contrôle de crédit"
#~ msgid "New lines"
#~ msgstr "Nouvelles lignes"

View File

@@ -0,0 +1,196 @@
# -*- 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
import pooler
from openerp.osv.orm import Model, fields
from openerp.osv import osv
from openerp.tools.translate import _
logger = logging.getLogger('credit.line.control')
class CreditControlLine(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"
_columns = {
'date': fields.date('Controlling date', required=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_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.message', '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),
}
_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.id if move_line.invoice_id 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, context=None):
"""Create or update line based on levels"""
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
if open_amount > tolerance.get(line.currency_id.id, tolerance_base):
vals = self._prepare_from_move_line(
cr, uid, line, level, controlling_date, open_amount, context=context)
line_id = self.create(cr, uid, vals, context=context)
line_ids.append(line_id)
# when we have lines generated earlier in draft,
# on the same level, it means that we have left
# them, so they are to be considered as ignored
previous_draft_ids = self.search(
cr, uid,
[('move_line_id', '=', line.id),
('level', '=', level.id),
('state', '=', 'draft'),
('id', '!=', line_id)],
context=context)
if previous_draft_ids:
self.write(cr, uid, previous_draft_ids,
{'state': 'ignored'}, context=context)
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 osv.except_osv(
_('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)

View File

@@ -0,0 +1,148 @@
<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="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.lines</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Control Credit Lines">
<group>
<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."/>
<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"/>
</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="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>

View File

@@ -0,0 +1,44 @@
# -*- 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.orm import Model, fields
class ResPartner(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',
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)
}

View File

@@ -0,0 +1,25 @@
<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>

View File

@@ -0,0 +1,379 @@
# -*- 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.orm import Model, fields
from openerp.tools.translate import _
class CreditControlPolicy(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="[('reconcile', '=', True)]",
help='This policy will be active only for the selected accounts'),
}
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()
return set(move_l_obj.search(
cr, uid,
self._move_lines_domain(cr, uid, policy, controlling_date, context=context),
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",
(policy_id, tuple(lines)))
res = cr.fetchall()
if res:
different_lines.update([x[0] for x in res])
return different_lines
class CreditControlPolicyLevel(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),
'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),
}
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
# have to be generated again for the previous level
" AND state not in ('draft', 'ignored'))")
sql += " AND" + 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"
" ORDER BY credit_control_line.level desc limit 1)\n"
" AND cr_line.level = %(previous_level)s\n"
# lines from a previous level with a draft or ignored state
# have to be generated again for the previous level
" AND cr_line.state not in ('draft', 'ignored')\n"
" AND mv_line.id in %(line_ids)s\n")
sql += " AND " + 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

View File

@@ -0,0 +1,121 @@
<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>
<field name="name"/>
<field name="do_nothing"/>
<field name="company_id"/>
<notebook colspan="4">
<page string="Policy Levels">
<field name="level_ids" nolabel="1" colspan="4" >
<tree>
<field name="name"/>
<field name="level"/>
<field name="channel"/>
<field name="delay_days"/>
<field name="computation_mode"/>
<field name="email_template_id"/>
</tree>
<form>
<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>
</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>
<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>
<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>
<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>

View File

@@ -0,0 +1 @@
from . import credit_control_summary

View File

@@ -0,0 +1,22 @@
<html>
<head>
<style type="text/css">
${css}
</style>
</head>
<body>
%for comm in objects :
<%
setLang(comm.partner_id.lang)
current_uri = '%s_policy_template' % (comm.partner_id.lang)
if not context.lookup.has_template(current_uri):
context.lookup.put_string(current_uri, comm.current_policy_level.email_template_id.body_html)
%>
<%include file="${current_uri}" args="object=comm,user=user,ctx=ctx,quote=quote,format_exception=format_exception,mode='pdf'"/>
<p style="page-break-after:always"></p>
%endfor
</body>
</html>

View File

@@ -0,0 +1,37 @@
# -*- 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)

View File

@@ -0,0 +1,12 @@
<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"/>
</data>
</openerp>

View File

@@ -0,0 +1,153 @@
# -*- 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.orm import Model, fields
from openerp.tools.translate import _
from openerp.osv.osv import except_osv
logger = logging.getLogger('credit.control.run')
class CreditControlRun(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 meantime, '
'it has to be handled manually'),
readonly=True),
}
def _get_policies(self, cr, uid, context=None):
return self.pool.get('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"""
line_obj = self.pool.get('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 except_osv(
_('Error'),
_('A run has already been executed more recently than %s') % (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 except_osv(
_('Error'),
_('Please select a policy'))
report = ''
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)
if lines:
policy_generated_ids = []
# 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)
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)
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, exc:
# in case of exception openerp will do a rollback for us and free the lock
raise except_osv(
_('Error'),
_('A credit control run is already running'
' in background, please try later.'), str(exc))
self._generate_credit_lines(cr, uid, run_id, context)
return True

View File

@@ -0,0 +1,65 @@
<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> <!-- 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>
<field name="date"/>
<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>

View File

@@ -0,0 +1,18 @@
"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
1 id perm_create perm_unlink group_id/id name model_id/id perm_read perm_write
2 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
3 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
4 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
5 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
6 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
7 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
8 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
9 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
10 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
11 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
12 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
13 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
14 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
15 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
16 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
17 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
18 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

View File

@@ -0,0 +1,24 @@
# -*- 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

View File

@@ -0,0 +1,181 @@
# -*- 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
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
logger = logging.getLogger('credit.control.line.mailing')
class CreditCommunication(TransientModel):
"""Shell calss 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_address(self, cr, uid, com_id, context=None):
"""Return a valid address for customer"""
assert not (isinstance(com_id, list) and len(com_id) > 1), \
"com_id: only one id expected"
if isinstance(com_id, list):
com_id = com_id[0]
form = self.browse(cr, uid, com_id, context=context)
part_obj = self.pool.get('res.partner')
adds = part_obj.address_get(cr, uid, [form.partner_id.id],
adr_pref=['invoice', 'default'])
add = adds.get('invoice', adds.get('default'))
add_obj = self.pool.get('res.partner.address')
if add:
return add_obj.browse(cr, uid, add, context=context)
else:
return False
def get_email(self, cr, uid, com_id, context=None):
"""Return a valid email for customer"""
assert not (isinstance(com_id, list) and len(com_id) > 1), \
"com_id: only one id expected"
if isinstance(com_id, list):
com_id = com_id[0]
form = self.browse(cr, uid, com_id, context=context)
address = form.get_address()
email = ''
if address and address.email:
email = address.email
return email
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):
if not line_ids:
return []
comms = []
sql = ("SELECT distinct partner_id, policy_level_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")
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.message')
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_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)
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

View File

@@ -0,0 +1,83 @@
# -*- 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.orm import TransientModel, fields
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
class CreditControlEmailer(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 except_osv(_('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 {}

View File

@@ -0,0 +1,44 @@
<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="type">form</field>
<field name="arch" type="xml">
<form>
<separator string="Send emails for the selected lines" colspan="4"/>
<newline/>
<field name="line_ids" colspan="4" nolabel="1" />
<newline/>
<group colspan="4">
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="email_lines" string="Send the emails" type="object" icon="gtk-execute"/>
</group>
</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>

View File

@@ -0,0 +1,101 @@
# -*- 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.orm import TransientModel, fields
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
class CreditControlMarker(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 except_osv(_('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'}

View File

@@ -0,0 +1,45 @@
<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="type">form</field>
<field name="arch" type="xml">
<form>
<separator string="Change the state of the selected lines." colspan="4"/>
<label string="Warning: you will maybe not be able to revert this operation." colspan="4"></label>
<newline/>
<field name="name" colspan="4"/>
<field name="line_ids" colspan="4" nolabel="1"/>
<newline/>
<group colspan="4">
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="mark_lines" string="Change Lines' State" type="object" icon="gtk-execute"/>
</group>
</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>

View File

@@ -0,0 +1,89 @@
# -*- 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.orm import TransientModel, fields
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
class CreditControlPrinter(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' and
context.get('active_ids')):
res = context['active_ids']
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),
'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 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 except_osv(_('Error'), _('No credit control lines selected.'))
line_ids = [l.id for l in form.line_ids]
comms = comm_obj._generate_comm_from_credit_line_ids(
cr, uid, line_ids, context=context)
report_file = comm_obj._generate_report(cr, uid, comms, context=context)
form.write({'report_file': base64.b64encode(report_file), 'state': 'done'})
if form.mark_as_sent:
filtered_ids = self._filter_line_ids(cr, uid, line_ids, context)
comm_obj._mark_credit_line_as_sent(cr, uid, comms, context=context)
return False # do not close the window, we need it to download the report

View File

@@ -0,0 +1,49 @@
<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>
<separator colspan="4" string="Print the selected lines"/>
<newline/>
<field name="mark_as_sent" colspan="4" attrs="{'invisible': [('state', '=', 'done')]}"/>
<newline/>
<field name="line_ids" colspan="4" nolabel="1"
attrs="{'invisible': [('state', '=', 'done')]}" />
<field name="report_file" colspan="4" attrs="{'invisible': [('state', '!=', 'done')]}"/>
<field name="state" invisible="1" />
<newline/>
<group colspan="4">
<button special="cancel" string="Cancel" icon='gtk-cancel' attrs="{'invisible': [('state', '==', 'done')]}"/>
<button name="print_lines" string="Print" type="object" icon="gtk-execute" attrs="{'invisible': [('state', '==', 'done')]}"/>
<button special="cancel" string="Close" icon='gtk-close' attrs="{'invisible': [('state', '!=', 'done')]}"/>
</group>
</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>