← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~akretion-team/account-closing/70-forecast-prepaid into lp:account-closing

 

Alexis de Lattre has proposed merging lp:~akretion-team/account-closing/70-forecast-prepaid into lp:account-closing.

Requested reviews:
  Account Core Editors (account-core-editors)

For more details, see:
https://code.launchpad.net/~akretion-team/account-closing/70-forecast-prepaid/+merge/210066

The main change in this MP is the addition of one new feature : the ability to compute forecasts of prepaid expense and prepaid revenue. This is important when working on budgets ; it allows the Accountant to easily compute the amount of prepaid revenue and prepaid expense between 2 dates in the future (you can also use it for dates in the past...).

This feature used to be available in the module "account_prepaid_reporting" from lp:~akretion-team/+junk/70-prepaid-reporting, but this module had a lot of duplicate code with the module account_cutoff_prepaid and it was based on two TransientModels which caused some bugs in some scenarios when doing CSV exports. So I eventually decided to try to integrate this feature inside the module account_cutoff_prepaid ; I am happy with the result (it avoids code duplication and only introduce a few lines of additional code) so I propose it for inclusion in the official branch.
-- 
https://code.launchpad.net/~akretion-team/account-closing/70-forecast-prepaid/+merge/210066
Your team Account Core Editors is requested to review the proposed merge of lp:~akretion-team/account-closing/70-forecast-prepaid into lp:account-closing.
=== modified file 'account_cutoff_base/account_cutoff.py'
--- account_cutoff_base/account_cutoff.py	2013-12-24 15:31:15 +0000
+++ account_cutoff_base/account_cutoff.py	2014-03-09 00:20:56 +0000
@@ -61,7 +61,7 @@
 
     _columns = {
         'cutoff_date': fields.date(
-            'Cut-off Date', required=True, readonly=True,
+            'Cut-off Date', readonly=True,
             states={'draft': [('readonly', False)]},
             track_visibility='always'),
         'type': fields.selection([
@@ -75,7 +75,7 @@
             'account.move', 'Cut-off Journal Entry', readonly=True),
         'move_label': fields.char(
             'Label of the Cut-off Journal Entry',
-            size=64, required=True, readonly=True,
+            size=64, readonly=True,
             states={'draft': [('readonly', False)]},
             help="This label will be written in the 'Name' field of the "
             "Cut-off Account Move Lines and in the 'Reference' field of "
@@ -83,10 +83,9 @@
         'cutoff_account_id': fields.many2one(
             'account.account', 'Cut-off Account',
             domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
-            required=True, readonly=True,
-            states={'draft': [('readonly', False)]}),
+            readonly=True, states={'draft': [('readonly', False)]}),
         'cutoff_journal_id': fields.many2one(
-            'account.journal', 'Cut-off Account Journal', required=True,
+            'account.journal', 'Cut-off Account Journal',
             readonly=True, states={'draft': [('readonly', False)]}),
         'total_cutoff_amount': fields.function(
             _compute_total_cutoff, type='float', string="Total Cut-off Amount",
@@ -165,12 +164,15 @@
         )]
 
     def cutoff_date_onchange(
-            self, cr, uid, ids, type, cutoff_date, move_label):
+            self, cr, uid, ids, type, cutoff_date, move_label, context=None):
+        if context is None:
+            context = {}
         res = {'value': {}}
         if type and cutoff_date:
-            context = {'type': type, 'cutoff_date': cutoff_date}
+            ctx = context.copy()
+            ctx.update({'type': type, 'cutoff_date': cutoff_date})
             res['value']['move_label'] = self._default_move_label(
-                cr, uid, context=context)
+                cr, uid, context=ctx)
         return res
 
     def back2draft(self, cr, uid, ids, context=None):

=== modified file 'account_cutoff_base/account_cutoff_view.xml'
--- account_cutoff_base/account_cutoff_view.xml	2013-10-15 19:35:48 +0000
+++ account_cutoff_base/account_cutoff_view.xml	2014-03-09 00:20:56 +0000
@@ -35,15 +35,15 @@
                 </div>
                 <group name="top">
                     <group name="general-params">
-                        <field name="cutoff_date" on_change="cutoff_date_onchange(type, cutoff_date, move_label)"/>
+                        <field name="cutoff_date" on_change="cutoff_date_onchange(type, cutoff_date, move_label, context)"/>
                         <field name="total_cutoff_amount" widget="monetary" options="{'currency_field': 'company_currency_id'}"/>
                         <field name="company_id" groups="base.group_multi_company" widget="selection" />
                         <field name="company_currency_id" invisible="1"/>
                     </group>
                     <group name="accounting-params">
-                        <field name="cutoff_journal_id"/>
-                        <field name="cutoff_account_id"/>
-                        <field name="move_label"/>
+                        <field name="cutoff_journal_id" required="1"/>
+                        <field name="cutoff_account_id" required="1"/>
+                        <field name="move_label" required="1"/>
                         <field name="move_id"/>
                     </group>
                 </group>

=== modified file 'account_cutoff_prepaid/__openerp__.py'
--- account_cutoff_prepaid/__openerp__.py	2013-09-09 21:28:50 +0000
+++ account_cutoff_prepaid/__openerp__.py	2014-03-09 00:20:56 +0000
@@ -23,7 +23,7 @@
 
 {
     'name': 'Account Cut-off Prepaid',
-    'version': '0.1',
+    'version': '0.2',
     'category': 'Accounting & Finance',
     'license': 'AGPL-3',
     'summary': 'Prepaid Expense, Prepaid Revenue',

=== modified file 'account_cutoff_prepaid/account_cutoff.py'
--- account_cutoff_prepaid/account_cutoff.py	2013-12-24 15:31:15 +0000
+++ account_cutoff_prepaid/account_cutoff.py	2014-03-09 00:20:56 +0000
@@ -23,6 +23,7 @@
 
 from openerp.osv import orm, fields
 from openerp.tools.translate import _
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
 from datetime import datetime
 
 
@@ -34,6 +35,13 @@
             'account.journal', id1='cutoff_id', id2='journal_id',
             string='Source Journals', readonly=True,
             states={'draft': [('readonly', False)]}),
+        'forecast': fields.boolean(
+            'Forecast',
+            readonly=True, states={'draft': [('readonly', False)]},
+            help="The Forecast mode allows the user to compute "
+            "the prepaid revenue/expense between 2 dates in the future."),
+        'start_date': fields.date('Start Date'),
+        'end_date': fields.date('End Date'),
     }
 
     def _get_default_source_journals(self, cr, uid, context=None):
@@ -58,32 +66,71 @@
         }
 
     _sql_constraints = [(
-        'date_type_company_uniq',
-        'unique(cutoff_date, company_id, type)',
-        'A cut-off of the same type already exists with this cut-off date !'
+        'date_type_forecast_company_uniq',
+        'unique(cutoff_date, company_id, type, forecast, start_date, end_date)',
+        'A cut-off of the same type already exists with the same date(s) !'
         )]
 
+    def _check_start_end_dates(self, cr, uid, ids):
+        for prepaid in self.browse(cr, uid, ids):
+            if prepaid.forecast and prepaid.start_date and prepaid.end_date \
+                    and prepaid.start_date > prepaid.end_date:
+                return False
+        return True
+
+    _constraints = [
+        (_check_start_end_dates, "The start date is after the end date!",
+            ['start_date', 'end_date', 'forecast']),
+    ]
+
+    def forecast_onchange(self, cr, uid, ids, forecast, context=None):
+        res = {'value': {}}
+        line_ids = self.pool['account.cutoff.line'].search(
+            cr, uid, [('parent_id', 'in', ids)], context=context)
+        self.pool['account.cutoff.line'].unlink(
+            cr, uid, line_ids, context=context)
+        if forecast:
+            res['value']['cutoff_date'] = False
+        else:
+            res['value']['start_date'] = False
+            res['value']['end_date'] = False
+        return res
+
     def _prepare_prepaid_lines(
             self, cr, uid, ids, aml, cur_cutoff, mapping, context=None):
-        start_date = datetime.strptime(aml['start_date'], '%Y-%m-%d')
-        end_date = datetime.strptime(aml['end_date'], '%Y-%m-%d')
-        cutoff_date_str = cur_cutoff['cutoff_date']
-        cutoff_date = datetime.strptime(cutoff_date_str, '%Y-%m-%d')
+        start_date = datetime.strptime(
+            aml['start_date'], DEFAULT_SERVER_DATE_FORMAT)
+        end_date = datetime.strptime(
+            aml['end_date'], DEFAULT_SERVER_DATE_FORMAT)
         # Here, we compute the amount of the cutoff
         # That's the important part !
         total_days = (end_date - start_date).days + 1
-        if aml['start_date'] > cutoff_date_str:
-            after_cutoff_days = total_days
-            cutoff_amount = -1 * (aml['credit'] - aml['debit'])
+        if cur_cutoff['forecast']:
+            out_days = 0
+            forecast_start_date = datetime.strptime(
+                cur_cutoff['start_date'], DEFAULT_SERVER_DATE_FORMAT)
+            forecast_end_date = datetime.strptime(
+                cur_cutoff['end_date'], DEFAULT_SERVER_DATE_FORMAT)
+            if aml['end_date'] > cur_cutoff['end_date']:
+                out_days += (end_date - forecast_end_date).days
+            if aml['start_date'] < cur_cutoff['start_date']:
+                out_days += (forecast_start_date - start_date).days
+            prepaid_days = total_days - out_days
         else:
-            after_cutoff_days = (end_date - cutoff_date).days
-            if total_days:
-                cutoff_amount = -1 * (aml['credit'] - aml['debit'])\
-                    * after_cutoff_days / total_days
+            cutoff_date_str = cur_cutoff['cutoff_date']
+            cutoff_date = datetime.strptime(
+                cutoff_date_str, DEFAULT_SERVER_DATE_FORMAT)
+            if aml['start_date'] > cutoff_date_str:
+                prepaid_days = total_days
             else:
-                raise orm.except_orm(
-                    _('Error:'),
-                    "Should never happen. Total days should always be > 0")
+                prepaid_days = (end_date - cutoff_date).days
+        if total_days:
+            cutoff_amount = (aml['debit'] - aml['credit'])\
+                * prepaid_days / float(total_days)
+        else:
+            raise orm.except_orm(
+                _('Error:'),
+                "Should never happen. Total days should always be > 0")
 
         # we use account mapping here
         if aml['account_id'][0] in mapping:
@@ -104,7 +151,7 @@
             aml['analytic_account_id'] and aml['analytic_account_id'][0]
             or False,
             'total_days': total_days,
-            'after_cutoff_days': after_cutoff_days,
+            'prepaid_days': prepaid_days,
             'amount': aml['credit'] - aml['debit'],
             'currency_id': cur_cutoff['company_currency_id'][0],
             'cutoff_amount': cutoff_amount,
@@ -120,7 +167,8 @@
         cur_cutoff = self.read(
             cr, uid, ids[0], [
                 'line_ids', 'source_journal_ids', 'cutoff_date', 'company_id',
-                'type', 'company_currency_id'
+                'type', 'company_currency_id', 'forecast', 'start_date',
+                'end_date',
                 ],
             context=context)
         src_journal_ids = cur_cutoff['source_journal_ids']
@@ -132,13 +180,22 @@
         if cur_cutoff['line_ids']:
             line_obj.unlink(cr, uid, cur_cutoff['line_ids'], context=context)
 
+        if cur_cutoff['forecast']:
+            domain = [
+                ('start_date', '<=', cur_cutoff['end_date']),
+                ('end_date', '>=', cur_cutoff['start_date']),
+                ('journal_id', 'in', src_journal_ids)
+                ]
+        else:
+            domain = [
+                ('start_date', '!=', False),
+                ('journal_id', 'in', src_journal_ids),
+                ('end_date', '>', cutoff_date_str),
+                ('date', '<=', cutoff_date_str)
+                ]
+
         # Search for account move lines in the source journals
-        aml_ids = aml_obj.search(cr, uid, [
-            ('start_date', '!=', False),
-            ('journal_id', 'in', src_journal_ids),
-            ('end_date', '>', cutoff_date_str),
-            ('date', '<=', cutoff_date_str)
-            ], context=context)
+        aml_ids = aml_obj.search(cr, uid, domain, context=context)
         # Create mapping dict
         mapping = mapping_obj._get_mapping_dict(
             cr, uid, cur_cutoff['company_id'][0], cur_cutoff['type'],
@@ -188,6 +245,9 @@
         'start_date': fields.date('Start Date', readonly=True),
         'end_date': fields.date('End Date', readonly=True),
         'total_days': fields.integer('Total Number of Days', readonly=True),
-        'after_cutoff_days': fields.integer(
-            'Number of Days after Cut-off Date', readonly=True),
+        'prepaid_days': fields.integer(
+            'Prepaid Days', readonly=True,
+            help="In regular mode, this is the number of days after the "
+            "cut-off date. In forecast mode, this is the number of days "
+            "between the start date and the end date."),
         }

=== modified file 'account_cutoff_prepaid/account_cutoff_view.xml'
--- account_cutoff_prepaid/account_cutoff_view.xml	2013-10-15 19:35:48 +0000
+++ account_cutoff_prepaid/account_cutoff_view.xml	2014-03-09 00:20:56 +0000
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-    Copyright (C) 2013 Akretion (http://www.akretion.com/)
+    Copyright (C) 2013-2014 Akretion (http://www.akretion.com/)
     @author Alexis de Lattre <alexis.delattre@xxxxxxxxxxxx>
     The licence is in the file __openerp__.py
 -->
@@ -9,12 +9,57 @@
 <openerp>
 <data>
 
+<!-- Tree view -->
+<record id="account_cutoff_tree" model="ir.ui.view">
+    <field name="name">account.cutoff.prepaid.tree</field>
+    <field name="model">account.cutoff</field>
+    <field name="inherit_id" ref="account_cutoff_base.account_cutoff_tree"/>
+    <field name="arch" type="xml">
+        <field name="cutoff_date" position="after">
+            <field name="forecast" invisible="'prepaid' not in context.get('type', '-')"/>
+            <field name="start_date" invisible="'prepaid' not in context.get('type', '-')"/>
+            <field name="end_date" invisible="'prepaid' not in context.get('type', '-')"/>
+        </field>
+    </field>
+</record>
+
 <!-- Form view -->
 <record id="account_cutoff_form" model="ir.ui.view">
     <field name="name">account.cutoff.prepaid.form</field>
     <field name="model">account.cutoff</field>
     <field name="inherit_id" ref="account_cutoff_base.account_cutoff_form"/>
     <field name="arch" type="xml">
+        <field name="cutoff_date" position="before">
+            <field name="forecast"
+                invisible="'prepaid' not in context.get('type', '-')"
+                on_change="forecast_onchange(forecast, context)"/>
+            <field name="start_date"
+                attrs="{'invisible': [('forecast', '=', False)], 'required': [('forecast', '=', True)]}"/>
+            <field name="end_date"
+                attrs="{'invisible': [('forecast', '=', False)], 'required': [('forecast', '=', True)]}"/>
+        </field>
+        <field name="cutoff_date" position="attributes">
+            <attribute name="attrs">{'invisible': [('forecast', '=', True)], 'required': [('forecast', '=', False)]}</attribute>
+            <attribute name="required">0</attribute>
+        </field>
+        <group name="accounting-params" position="attributes">
+            <attribute name="attrs">{'invisible': [('forecast', '=', True)]}</attribute>
+        </group>
+        <field name="cutoff_journal_id" position="attributes">
+            <attribute name="required">0</attribute>
+            <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
+        </field>
+        <field name="cutoff_account_id" position="attributes">
+            <attribute name="required">0</attribute>
+            <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
+        </field>
+        <field name="move_label" position="attributes">
+            <attribute name="required">0</attribute>
+            <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
+        </field>
+        <button name="create_move" position="attributes">
+            <attribute name="attrs">{'invisible': [('forecast', '=', True)]}</attribute>
+        </button>
         <button name="back2draft" position="after">
             <button class="oe_highlight" name="get_prepaid_lines" string="Re-Generate Lines" type="object" states="draft" invisible="'prepaid' not in context.get('type', '-')"/>
         </button>
@@ -41,7 +86,7 @@
         </field>
         <field name="cutoff_amount" position="before">
             <field name="total_days" invisible="'prepaid' not in context.get('type', '-')"/>
-            <field name="after_cutoff_days" invisible="'prepaid' not in context.get('type', '-')"/>
+            <field name="prepaid_days" invisible="'prepaid' not in context.get('type', '-')"/>
         </field>
     </field>
 </record>
@@ -59,7 +104,7 @@
             <field name="start_date" invisible="'prepaid' not in context.get('type', '-')"/>
             <field name="end_date" invisible="'prepaid' not in context.get('type', '-')"/>
             <field name="total_days" string="Days Total" invisible="'prepaid' not in context.get('type', '-')"/>
-            <field name="after_cutoff_days" string="Days after Cut-off" invisible="'prepaid' not in context.get('type', '-')"/>
+            <field name="prepaid_days" string="Days after Cut-off" invisible="'prepaid' not in context.get('type', '-')"/>
         </field>
     </field>
 </record>

=== modified file 'account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot'
--- account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot	2013-12-24 15:31:15 +0000
+++ account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot	2014-03-09 00:20:56 +0000
@@ -6,8 +6,8 @@
 msgstr ""
 "Project-Id-Version: OpenERP Server 7.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-12-24 15:26+0000\n"
-"PO-Revision-Date: 2013-12-24 15:26+0000\n"
+"POT-Creation-Date: 2014-03-09 00:05+0000\n"
+"PO-Revision-Date: 2014-03-09 00:05+0000\n"
 "Last-Translator: <>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -21,6 +21,7 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: field:account.cutoff,end_date:0
 #: field:account.cutoff.line,end_date:0
 #: field:account.invoice.line,end_date:0
 #: field:account.move.line,end_date:0
@@ -38,6 +39,16 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: field:account.cutoff,forecast:0
+msgid "Forecast"
+msgstr ""
+
+#. module: account_cutoff_prepaid
+#: view:account.cutoff:0
+msgid "{'invisible': [('forecast', '=', True)], 'required': [('forecast', '=', False)]}"
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: field:res.company,default_prepaid_expense_account_id:0
 msgid "Default Account for Prepaid Expense"
 msgstr ""
@@ -65,6 +76,11 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: view:account.cutoff:0
+msgid "{'invisible': [('forecast', '=', True)]}"
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: field:account.cutoff.line,total_days:0
 msgid "Total Number of Days"
 msgstr ""
@@ -104,6 +120,11 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: help:account.cutoff,forecast:0
+msgid "The Forecast mode allows the user to compute the prepaid revenue/expense between 2 dates in the future."
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: model:ir.model,name:account_cutoff_prepaid.model_account_cutoff
 msgid "Account Cut-off"
 msgstr ""
@@ -119,16 +140,6 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
-#: sql_constraint:account.cutoff:0
-msgid "A cut-off of the same type already exists with this cut-off date !"
-msgstr ""
-
-#. module: account_cutoff_prepaid
-#: field:account.cutoff.line,after_cutoff_days:0
-msgid "Number of Days after Cut-off Date"
-msgstr ""
-
-#. module: account_cutoff_prepaid
 #: model:product.template,name:account_cutoff_prepaid.product_insurance_contrat_product_template
 msgid "Car Insurance"
 msgstr ""
@@ -141,8 +152,8 @@
 #: code:addons/account_cutoff_prepaid/account.py:94
 #: code:addons/account_cutoff_prepaid/account.py:100
 #: code:addons/account_cutoff_prepaid/account.py:144
-#: code:addons/account_cutoff_prepaid/account_cutoff.py:85
-#: code:addons/account_cutoff_prepaid/account_cutoff.py:129
+#: code:addons/account_cutoff_prepaid/account_cutoff.py:132
+#: code:addons/account_cutoff_prepaid/account_cutoff.py:177
 #, python-format
 msgid "Error:"
 msgstr ""
@@ -170,7 +181,7 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
-#: code:addons/account_cutoff_prepaid/account_cutoff.py:129
+#: code:addons/account_cutoff_prepaid/account_cutoff.py:177
 #, python-format
 msgid "You should set at least one Source Journal."
 msgstr ""
@@ -182,17 +193,32 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: constraint:account.cutoff:0
+msgid "The start date is after the end date!"
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: code:addons/account_cutoff_prepaid/account.py:90
 #, python-format
 msgid "Missing End Date for move line with Name '%s'."
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: help:account.cutoff.line,prepaid_days:0
+msgid "In regular mode, this is the number of days after the cut-off date. In forecast mode, this is the number of days between the start date and the end date."
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: model:ir.model,name:account_cutoff_prepaid.model_product_template
 msgid "Product Template"
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: view:account.cutoff:0
+msgid "{'required': [('forecast', '=', False)]}"
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: model:ir.model,name:account_cutoff_prepaid.model_account_invoice_line
 msgid "Invoice Line"
 msgstr ""
@@ -224,6 +250,12 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: sql_constraint:account.cutoff:0
+msgid "A cut-off of the same type already exists with the same date(s) !"
+msgstr ""
+
+#. module: account_cutoff_prepaid
+#: field:account.cutoff,start_date:0
 #: field:account.cutoff.line,start_date:0
 #: field:account.invoice.line,start_date:0
 #: field:account.move.line,start_date:0
@@ -236,6 +268,11 @@
 msgstr ""
 
 #. module: account_cutoff_prepaid
+#: field:account.cutoff.line,prepaid_days:0
+msgid "Prepaid Days"
+msgstr ""
+
+#. module: account_cutoff_prepaid
 #: view:product.template:0
 msgid "Sales Properties"
 msgstr ""

=== added directory 'account_cutoff_prepaid/migrations'
=== added directory 'account_cutoff_prepaid/migrations/7.0.0.2'
=== added file 'account_cutoff_prepaid/migrations/7.0.0.2/pre-migration.py'
--- account_cutoff_prepaid/migrations/7.0.0.2/pre-migration.py	1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/migrations/7.0.0.2/pre-migration.py	2014-03-09 00:20:56 +0000
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2014 Akretion (http://www.akretion.com/)
+#    @author: Alexis de Lattre <alexis.delattre@xxxxxxxxxxxx>
+#
+#    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/>.
+#
+##############################################################################
+
+
+def migrate(cr, version):
+    if not version:
+        return
+
+    cr.execute(
+        'ALTER TABLE "account_cutoff_line" RENAME "after_cutoff_days" '
+        'TO "prepaid_days"')


Follow ups