Merge lp:~akretion-team/account-closing/61-cutoff-modules-with-forecast into lp:~account-core-editors/account-closing/6.1

Proposed by Alexis de Lattre
Status: Needs review
Proposed branch: lp:~akretion-team/account-closing/61-cutoff-modules-with-forecast
Merge into: lp:~account-core-editors/account-closing/6.1
Diff against target: 3530 lines (+3315/-0)
36 files modified
account_cutoff_accrual_base/__init__.py (+25/-0)
account_cutoff_accrual_base/__openerp__.py (+46/-0)
account_cutoff_accrual_base/account.py (+36/-0)
account_cutoff_accrual_base/account_cutoff.py (+57/-0)
account_cutoff_accrual_base/account_cutoff_view.xml (+72/-0)
account_cutoff_accrual_base/account_view.xml (+27/-0)
account_cutoff_accrual_base/company.py (+37/-0)
account_cutoff_accrual_base/company_view.xml (+26/-0)
account_cutoff_accrual_base/i18n/account_cutoff_accrual_base.pot (+119/-0)
account_cutoff_accrual_picking/__init__.py (+23/-0)
account_cutoff_accrual_picking/__openerp__.py (+61/-0)
account_cutoff_accrual_picking/account_cutoff.py (+220/-0)
account_cutoff_accrual_picking/account_cutoff_view.xml (+54/-0)
account_cutoff_accrual_picking/i18n/account_cutoff_accrual_picking.pot (+93/-0)
account_cutoff_base/__init__.py (+24/-0)
account_cutoff_base/__openerp__.py (+47/-0)
account_cutoff_base/account_cutoff.py (+438/-0)
account_cutoff_base/account_cutoff_view.xml (+218/-0)
account_cutoff_base/company.py (+35/-0)
account_cutoff_base/company_view.xml (+27/-0)
account_cutoff_base/i18n/account_cutoff_base.pot (+403/-0)
account_cutoff_base/security/ir.model.access.csv (+9/-0)
account_cutoff_prepaid/__init__.py (+26/-0)
account_cutoff_prepaid/__openerp__.py (+57/-0)
account_cutoff_prepaid/account.py (+150/-0)
account_cutoff_prepaid/account_cutoff.py (+253/-0)
account_cutoff_prepaid/account_cutoff_view.xml (+146/-0)
account_cutoff_prepaid/account_invoice_view.xml (+53/-0)
account_cutoff_prepaid/account_view.xml (+53/-0)
account_cutoff_prepaid/company.py (+37/-0)
account_cutoff_prepaid/company_view.xml (+27/-0)
account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot (+289/-0)
account_cutoff_prepaid/migrations/6.1.0.2/pre-migration.py (+29/-0)
account_cutoff_prepaid/product.py (+36/-0)
account_cutoff_prepaid/product_demo.xml (+25/-0)
account_cutoff_prepaid/product_view.xml (+37/-0)
To merge this branch: bzr merge lp:~akretion-team/account-closing/61-cutoff-modules-with-forecast
Reviewer Review Type Date Requested Status
Account Core Editors Pending
Review via email: mp+210067@code.launchpad.net

Description of the change

This is the backport to OpenERP 6.1 of my cut-off modules : account_cutoff_base, account_cutoff_accrual_base, account_cutoff_accrual_picking, account_cutoff_prepaid. It also includes the code of the "prepaid forecast" feature, which is under review here : https://code.launchpad.net/~akretion-team/account-closing/70-forecast-prepaid/+merge/210066

To post a comment you must log in.

Unmerged revisions

43. By Alexis de Lattre

Add POT files.

42. By Alexis de Lattre

Delete lines when changing the "forecast" param.
Small code enhancements.

41. By Alexis de Lattre

Remove a print.

40. By Alexis de Lattre

Add support for prepaid forecasts
Add context in on_change (for web_context_tunnel)

39. By Alexis de Lattre

Backport latest enhancements from v7.0 branch.

38. By Alexis de Lattre

Backport to OpenERP 6.1
prepaid cutoffs : don't take into account the move lines dated after cut-off date.

37. By Alexis de Lattre

Remove the unnecessary "and True or False" after 'xxx' not in context.get('type', '-')

36. By Alexis de Lattre

Forgot to move some code to the new _prepare function.

35. By Alexis de Lattre

Add _prepare functions to allow to inherit before create
Use assert
Remove .keys()
No space before colon
PEP8/Flake8 : getting closer to compliancy

34. By Alexis de Lattre

Coding style enhancements (osv.Model -> orm.Model, from . import xxx)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'account_cutoff_accrual_base'
=== added file 'account_cutoff_accrual_base/__init__.py'
--- account_cutoff_accrual_base/__init__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/__init__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,25 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from . import company
24from . import account
25from . import account_cutoff
026
=== added file 'account_cutoff_accrual_base/__openerp__.py'
--- account_cutoff_accrual_base/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/__openerp__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,46 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cutoff Accrual Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Account Accrual Base',
26 'version': '0.1',
27 'category': 'Accounting & Finance',
28 'license': 'AGPL-3',
29 'summary': 'Base module for accrued expenses and revenues',
30 'description': """This module contains objets, fields and menu entries that are used by other accrual modules. So you need to install other accrual modules to get the additionnal functionalities :
31- the module 'account_cutoff_accrual_picking' will manage accrued expenses and revenues based on pickings.
32- a not-developped-yet module will manage accrued expenses and revenues based on timesheets.
33
34Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
35 """,
36 'author': 'Akretion',
37 'website': 'http://www.akretion.com',
38 'depends': ['account_cutoff_base'],
39 'data': [
40 'company_view.xml',
41 'account_view.xml',
42 'account_cutoff_view.xml',
43 ],
44 'installable': True,
45 'active': False,
46}
047
=== added file 'account_cutoff_accrual_base/account.py'
--- account_cutoff_accrual_base/account.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/account.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,36 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.osv import orm, fields
24
25
26class account_tax(orm.Model):
27 _inherit = 'account.tax'
28
29 _columns = {
30 'account_accrued_revenue_id': fields.many2one(
31 'account.account', 'Accrued Revenue Tax Account',
32 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
33 'account_accrued_expense_id': fields.many2one(
34 'account.account', 'Accrued Expense Tax Account',
35 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
36 }
037
=== added file 'account_cutoff_accrual_base/account_cutoff.py'
--- account_cutoff_accrual_base/account_cutoff.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/account_cutoff.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,57 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25import decimal_precision as dp
26
27
28class account_cutoff(orm.Model):
29 _inherit = 'account.cutoff'
30
31 def _inherit_default_cutoff_account_id(self, cr, uid, context=None):
32 if context is None:
33 context = {}
34 account_id = super(account_cutoff, self).\
35 _inherit_default_cutoff_account_id(
36 cr, uid, context=context)
37 type = context.get('type')
38 company = self.pool['res.users'].browse(
39 cr, uid, uid, context=context).company_id
40 if type == 'accrued_expense':
41 account_id = company.default_accrued_expense_account_id.id or False
42 elif type == 'accrued_revenue':
43 account_id = company.default_accrued_revenue_account_id.id or False
44 return account_id
45
46
47class account_cutoff_line(orm.Model):
48 _inherit = 'account.cutoff.line'
49
50 _columns = {
51 'quantity': fields.float(
52 'Quantity', digits_compute=dp.get_precision('Product UoS'),
53 readonly=True),
54 'price_unit': fields.float(
55 'Unit Price', digits_compute=dp.get_precision('Product Price'),
56 readonly=True, help="Price per unit (discount included)"),
57 }
058
=== added file 'account_cutoff_accrual_base/account_cutoff_view.xml'
--- account_cutoff_accrual_base/account_cutoff_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/account_cutoff_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,72 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<!-- Form view for lines -->
13<record id="account_cutoff_line_form" model="ir.ui.view">
14 <field name="name">accrual.account_cutoff_line</field>
15 <field name="model">account.cutoff.line</field>
16 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_form"/>
17 <field name="arch" type="xml">
18 <field name="amount" position="before">
19 <field name="quantity" invisible="'accrued' not in context.get('type', '-')"/>
20 <field name="price_unit" invisible="'accrued' not in context.get('type', '-')"/>
21 </field>
22 </field>
23</record>
24
25<!-- Tree view for lines -->
26<record id="account_cutoff_line_tree" model="ir.ui.view">
27 <field name="name">accrual.account_cutoff_line_tree</field>
28 <field name="model">account.cutoff.line</field>
29 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_tree"/>
30 <field name="arch" type="xml">
31 <field name="analytic_account_code" position="after">
32 <field name="quantity" invisible="'accrued' not in context.get('type', '-')"/>
33 <field name="price_unit" invisible="'accrued' not in context.get('type', '-')"/>
34 </field>
35 </field>
36</record>
37
38
39<record id="account_expense_accrual_action" model="ir.actions.act_window">
40 <field name="name">Accrued Expense</field>
41 <field name="res_model">account.cutoff</field>
42 <field name="view_type">form</field>
43 <field name="view_mode">tree,form</field>
44 <field name="domain">[('type', '=', 'accrued_expense')]</field>
45 <field name="context">{'type': 'accrued_expense'}</field>
46</record>
47
48
49<menuitem id="account_expense_accrual_menu"
50 parent="account_cutoff_base.cutoff_menu"
51 action="account_expense_accrual_action"
52 sequence="35"/>
53
54
55<record id="account_revenue_accrual_action" model="ir.actions.act_window">
56 <field name="name">Accrued Revenue</field>
57 <field name="res_model">account.cutoff</field>
58 <field name="view_type">form</field>
59 <field name="view_mode">tree,form</field>
60 <field name="domain">[('type', '=', 'accrued_revenue')]</field>
61 <field name="context">{'type': 'accrued_revenue'}</field>
62</record>
63
64
65<menuitem id="account_revenue_accrual_menu"
66 parent="account_cutoff_base.cutoff_menu"
67 action="account_revenue_accrual_action"
68 sequence="30"/>
69
70
71</data>
72</openerp>
073
=== added file 'account_cutoff_accrual_base/account_view.xml'
--- account_cutoff_accrual_base/account_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/account_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<record id="view_tax_form" model="ir.ui.view">
13 <field name="name">account.cutoff.accrual.view_tax_form</field>
14 <field name="model">account.tax</field>
15 <field name="inherit_id" ref="account.view_tax_form" />
16 <field name="arch" type="xml">
17 <separator string="Tax Declaration: Invoices" position="before">
18 <field name="account_accrued_revenue_id" attrs="{'invisible': [('type_tax_use', '=', 'purchase')]}"/>
19 <newline />
20 <field name="account_accrued_expense_id" attrs="{'invisible': [('type_tax_use', '=', 'sale')]}"/>
21 </separator>
22 </field>
23</record>
24
25
26</data>
27</openerp>
028
=== added file 'account_cutoff_accrual_base/company.py'
--- account_cutoff_accrual_base/company.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/company.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,37 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25
26
27class res_company(orm.Model):
28 _inherit = 'res.company'
29
30 _columns = {
31 'default_accrued_revenue_account_id': fields.many2one(
32 'account.account', 'Default Account for Accrued Revenues',
33 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
34 'default_accrued_expense_account_id': fields.many2one(
35 'account.account', 'Default Account for Accrued Expenses',
36 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
37 }
038
=== added file 'account_cutoff_accrual_base/company_view.xml'
--- account_cutoff_accrual_base/company_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/company_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,26 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<record id="view_company_form" model="ir.ui.view">
13 <field name="name">accrual.base.company.form</field>
14 <field name="model">res.company</field>
15 <field name="inherit_id" ref="account_cutoff_base.view_company_form" />
16 <field name="arch" type="xml">
17 <field name="default_cutoff_journal_id" position="after">
18 <field name="default_accrued_revenue_account_id" />
19 <field name="default_accrued_expense_account_id" />
20 </field>
21 </field>
22</record>
23
24
25</data>
26</openerp>
027
=== added directory 'account_cutoff_accrual_base/i18n'
=== added file 'account_cutoff_accrual_base/i18n/account_cutoff_accrual_base.pot'
--- account_cutoff_accrual_base/i18n/account_cutoff_accrual_base.pot 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_base/i18n/account_cutoff_accrual_base.pot 2014-03-09 00:39:34 +0000
@@ -0,0 +1,119 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * account_cutoff_accrual_base
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-03-09 00:25+0000\n"
10"PO-Revision-Date: 2014-03-09 00:25+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: account_cutoff_accrual_base
19#: sql_constraint:account.cutoff:0
20msgid "A cutoff of the same type already exists with this cut-off date !"
21msgstr ""
22
23#. module: account_cutoff_accrual_base
24#: model:ir.model,name:account_cutoff_accrual_base.model_account_cutoff_line
25msgid "Account Cut-off Line"
26msgstr ""
27
28#. module: account_cutoff_accrual_base
29#: field:res.company,default_accrued_expense_account_id:0
30msgid "Default Account for Accrued Expenses"
31msgstr ""
32
33#. module: account_cutoff_accrual_base
34#: sql_constraint:res.company:0
35msgid "The company name must be unique !"
36msgstr ""
37
38#. module: account_cutoff_accrual_base
39#: constraint:account.cutoff:0
40msgid "The start date is after the end date!"
41msgstr ""
42
43#. module: account_cutoff_accrual_base
44#: constraint:res.company:0
45msgid "Error! You can not create recursive companies."
46msgstr ""
47
48#. module: account_cutoff_accrual_base
49#: model:ir.model,name:account_cutoff_accrual_base.model_account_cutoff
50msgid "Account Cut-off"
51msgstr ""
52
53#. module: account_cutoff_accrual_base
54#: model:ir.model,name:account_cutoff_accrual_base.model_res_company
55msgid "Companies"
56msgstr ""
57
58#. module: account_cutoff_accrual_base
59#: model:ir.actions.act_window,name:account_cutoff_accrual_base.account_expense_accrual_action
60#: model:ir.ui.menu,name:account_cutoff_accrual_base.account_expense_accrual_menu
61msgid "Accrued Expense"
62msgstr ""
63
64#. module: account_cutoff_accrual_base
65#: field:account.cutoff.line,price_unit:0
66msgid "Unit Price"
67msgstr ""
68
69#. module: account_cutoff_accrual_base
70#: model:ir.actions.act_window,name:account_cutoff_accrual_base.account_revenue_accrual_action
71#: model:ir.ui.menu,name:account_cutoff_accrual_base.account_revenue_accrual_menu
72msgid "Accrued Revenue"
73msgstr ""
74
75#. module: account_cutoff_accrual_base
76#: view:account.tax:0
77msgid "Tax Declaration: Invoices"
78msgstr ""
79
80#. module: account_cutoff_accrual_base
81#: field:account.tax,account_accrued_revenue_id:0
82msgid "Accrued Revenue Tax Account"
83msgstr ""
84
85#. module: account_cutoff_accrual_base
86#: field:res.company,default_accrued_revenue_account_id:0
87msgid "Default Account for Accrued Revenues"
88msgstr ""
89
90#. module: account_cutoff_accrual_base
91#: sql_constraint:account.cutoff:0
92msgid "A cut-off of the same type already exists with the same date(s) !"
93msgstr ""
94
95#. module: account_cutoff_accrual_base
96#: help:account.cutoff.line,price_unit:0
97msgid "Price per unit (discount included)"
98msgstr ""
99
100#. module: account_cutoff_accrual_base
101#: model:ir.model,name:account_cutoff_accrual_base.model_account_tax
102msgid "account.tax"
103msgstr ""
104
105#. module: account_cutoff_accrual_base
106#: sql_constraint:account.tax:0
107msgid "Tax Name must be unique per company!"
108msgstr ""
109
110#. module: account_cutoff_accrual_base
111#: field:account.tax,account_accrued_expense_id:0
112msgid "Accrued Expense Tax Account"
113msgstr ""
114
115#. module: account_cutoff_accrual_base
116#: field:account.cutoff.line,quantity:0
117msgid "Quantity"
118msgstr ""
119
0120
=== added directory 'account_cutoff_accrual_picking'
=== added file 'account_cutoff_accrual_picking/__init__.py'
--- account_cutoff_accrual_picking/__init__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_picking/__init__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,23 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Picking module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from . import account_cutoff
024
=== added file 'account_cutoff_accrual_picking/__openerp__.py'
--- account_cutoff_accrual_picking/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_picking/__openerp__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,61 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Picking module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Account Accrual Picking',
26 'version': '0.1',
27 'category': 'Accounting & Finance',
28 'license': 'AGPL-3',
29 'summary': 'Accrued Expense & Accrued Revenue from Pickings',
30 'description': """
31Manage expense and revenue accruals from pickings
32=================================================
33
34This module generates expense and revenue accruals based on the status of pickings.
35
36For revenue accruals, OpenERP will take into account all the delivery orders in *Delivered* state that have been shipped before the cut-off date and that have *Invoice Control* = *To Be Invoiced*.
37
38For expense accruals, OpenERP will take into account all the incoming shipments in *Received* state that have been received before the cut-off date and that have *Invoice Control* = *To Be Invoiced*.
39
40The current code of the module only works when :
41
42* on sale orders, the *Create Invoice* field is set to *On Delivery Order* ;
43* for purchase orders, the *Invoicing Control* field is set to *Based on incoming shipments*.
44
45Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
46 """,
47 'author': 'Akretion',
48 'website': 'http://www.akretion.com',
49 'depends': ['account_cutoff_accrual_base', 'purchase', 'sale'],
50 'data': [
51 'account_cutoff_view.xml',
52 ],
53 'images': [
54 'images/accrued_expense_draft.jpg',
55 'images/accrued_expense_journal_entry.jpg',
56 'images/accrued_expense_done.jpg',
57 ],
58 'installable': True,
59 'active': False,
60 'application': True,
61}
062
=== added file 'account_cutoff_accrual_picking/account_cutoff.py'
--- account_cutoff_accrual_picking/account_cutoff.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_picking/account_cutoff.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,220 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Accrual Picking module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.osv import orm, fields
24from openerp.tools.translate import _
25
26
27class account_cutoff(orm.Model):
28 _inherit = 'account.cutoff'
29
30 def _prepare_lines_from_picking(
31 self, cr, uid, ids, cur_cutoff, move_line, account_mapping,
32 context=None):
33 tax_obj = self.pool['account.tax']
34 curr_obj = self.pool['res.currency']
35 company_currency_id = cur_cutoff['company_currency_id'][0]
36 assert cur_cutoff['type'] in ('accrued_expense', 'accrued_revenue'),\
37 "The field 'type' has a wrong value"
38 if cur_cutoff['type'] == 'accrued_expense':
39 account_id = move_line.product_id.property_account_expense.id
40 if not account_id:
41 account_id = move_line.product_id.categ_id.\
42 property_account_expense_categ.id
43 if not account_id:
44 raise orm.except_orm(
45 _('Error:'),
46 _("Missing expense account on product '%s' or on its "
47 "related product category.")
48 % (move_line.product_id.name))
49 currency = move_line.purchase_line_id.order_id.\
50 pricelist_id.currency_id
51 analytic_account_id = move_line.purchase_line_id.\
52 account_analytic_id.id or False
53 price_unit = move_line.purchase_line_id.price_unit
54 taxes = move_line.purchase_line_id.taxes_id
55 partner_id = move_line.purchase_line_id.order_id.partner_id.id
56 tax_account_field_name = 'account_accrued_expense_id'
57 tax_account_field_label = 'Accrued Expense Tax Account'
58
59 elif cur_cutoff['type'] == 'accrued_revenue':
60 account_id = move_line.product_id.property_account_income.id
61 if not account_id:
62 account_id = move_line.product_id.categ_id.\
63 property_account_income_categ.id
64 if not account_id:
65 raise orm.except_orm(
66 _('Error:'),
67 _("Missing income account on product '%s' or on its "
68 "related product category.")
69 % (move_line.product_id.name))
70 currency = move_line.sale_line_id.order_id.pricelist_id.currency_id
71 analytic_account_id = move_line.sale_line_id.order_id.\
72 project_id.id or False
73 discount = move_line.sale_line_id.discount
74 price_unit = move_line.sale_line_id.price_unit *\
75 (1-(discount or 0.0)/100.0)
76 taxes = move_line.sale_line_id.tax_id
77 partner_id = move_line.sale_line_id.order_id.partner_id.id
78 tax_account_field_name = 'account_accrued_revenue_id'
79 tax_account_field_label = 'Accrued Revenue Tax Account'
80
81 currency_id = currency.id
82 quantity = move_line.product_qty
83 tax_line_ids = []
84 tax_res = self.pool['account.tax'].compute_all(
85 cr, uid, taxes, price_unit, quantity,
86 move_line.product_id.id, partner_id)
87 amount = tax_res['total'] # =total without taxes
88 if cur_cutoff['type'] == 'accrued_expense':
89 amount = amount * -1
90 context_currency_compute = context.copy()
91 context_currency_compute['date'] = cur_cutoff['cutoff_date']
92 for tax_line in tax_res['taxes']:
93 tax_read = tax_obj.read(
94 cr, uid, tax_line['id'],
95 [tax_account_field_name, 'name'], context=context)
96 tax_accrual_account_id = tax_read[tax_account_field_name]
97 if not tax_accrual_account_id:
98 raise orm.except_orm(
99 _('Error:'),
100 _("Missing '%s' on tax '%s'.")
101 % (tax_account_field_label, tax_read['name']))
102 else:
103 tax_accrual_account_id = tax_accrual_account_id[0]
104 if cur_cutoff['type'] == 'accrued_expense':
105 tax_line['amount'] = tax_line['amount'] * -1
106 if company_currency_id != currency_id:
107 tax_accrual_amount = curr_obj.compute(
108 cr, uid, currency_id, company_currency_id,
109 tax_line['amount'],
110 context=context_currency_compute)
111 else:
112 tax_accrual_amount = tax_line['amount']
113 tax_line_ids.append((0, 0, {
114 'tax_id': tax_line['id'],
115 'base': curr_obj.round(
116 cr, uid, currency,
117 tax_line['price_unit'] * quantity),
118 'amount': tax_line['amount'],
119 'sequence': tax_line['sequence'],
120 'cutoff_account_id': tax_accrual_account_id,
121 'cutoff_amount': tax_accrual_amount,
122 'analytic_account_id':
123 tax_line['account_analytic_collected_id'],
124 # account_analytic_collected_id is for
125 # invoices IN and OUT
126 }))
127 if company_currency_id != currency_id:
128 amount_company_currency = curr_obj.compute(
129 cr, uid, currency_id, company_currency_id, amount,
130 context=context_currency_compute)
131 else:
132 amount_company_currency = amount
133
134 # we use account mapping here
135 if account_id in account_mapping:
136 accrual_account_id = account_mapping[account_id]
137 else:
138 accrual_account_id = account_id
139 res = {
140 'parent_id': ids[0],
141 'partner_id': partner_id,
142 'stock_move_id': move_line.id,
143 'name': move_line.name,
144 'account_id': account_id,
145 'cutoff_account_id': accrual_account_id,
146 'analytic_account_id': analytic_account_id,
147 'currency_id': currency_id,
148 'quantity': quantity,
149 'price_unit': price_unit,
150 'tax_ids': [(6, 0, [tax.id for tax in taxes])],
151 'amount': amount,
152 'cutoff_amount': amount_company_currency,
153 'tax_line_ids': tax_line_ids,
154 }
155 return res
156
157 def get_lines_from_picking(self, cr, uid, ids, context=None):
158 assert len(ids) == 1, \
159 'This function should only be used for a single id at a time'
160 pick_obj = self.pool['stock.picking']
161 line_obj = self.pool['account.cutoff.line']
162 mapping_obj = self.pool['account.cutoff.mapping']
163
164 cur_cutoff = self.read(cr, uid, ids[0], [
165 'line_ids', 'type', 'cutoff_date', 'company_id',
166 'company_currency_id',
167 ],
168 context=context)
169 # delete existing lines based on pickings
170 to_delete_line_ids = line_obj.search(
171 cr, uid, [
172 ('parent_id', '=', cur_cutoff['id']),
173 ('stock_move_id', '!=', False)
174 ],
175 context=context)
176 if to_delete_line_ids:
177 line_obj.unlink(cr, uid, to_delete_line_ids, context=context)
178 pick_type_map = {
179 'accrued_revenue': 'out',
180 'accrued_expense': 'in',
181 }
182 assert cur_cutoff['type'] in pick_type_map, \
183 "cur_cutoff['type'] should be in pick_type_map.keys()"
184 pick_ids = pick_obj.search(cr, uid, [
185 ('type', '=', pick_type_map[cur_cutoff['type']]),
186 ('state', '=', 'done'),
187 ('invoice_state', '=', '2binvoiced'),
188 ('date_done', '<=', cur_cutoff['cutoff_date'])
189 ], context=context)
190 #print "pick_ids=", pick_ids
191 # Create account mapping dict
192 account_mapping = mapping_obj._get_mapping_dict(
193 cr, uid, cur_cutoff['company_id'][0], cur_cutoff['type'],
194 context=context)
195 for picking in pick_obj.browse(cr, uid, pick_ids, context=context):
196 for move_line in picking.move_lines:
197 line_obj.create(
198 cr, uid, self._prepare_lines_from_picking(
199 cr, uid, ids, cur_cutoff, move_line,
200 account_mapping, context=context),
201 context=context)
202 return True
203
204
205class account_cutoff_line(orm.Model):
206 _inherit = 'account.cutoff.line'
207
208 _columns = {
209 'stock_move_id': fields.many2one(
210 'stock.move', 'Stock Move', readonly=True),
211 'product_id': fields.related(
212 'stock_move_id', 'product_id', type='many2one',
213 relation='product.product', string='Product', readonly=True),
214 'picking_id': fields.related(
215 'stock_move_id', 'picking_id', type='many2one',
216 relation='stock.picking', string='Picking', readonly=True),
217 'picking_date_done': fields.related(
218 'picking_id', 'date_done', type='date',
219 string='Date Done of the Picking', readonly=True),
220 }
0221
=== added file 'account_cutoff_accrual_picking/account_cutoff_view.xml'
--- account_cutoff_accrual_picking/account_cutoff_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_picking/account_cutoff_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,54 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<!-- Form view -->
13<record id="account_cutoff_form" model="ir.ui.view">
14 <field name="name">account.cutoff.picking.form</field>
15 <field name="model">account.cutoff</field>
16 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_form"/>
17 <field name="arch" type="xml">
18 <button name="create_move" position="before">
19 <button name="get_lines_from_picking" string="Re-Generate Lines from Picking" type="object" states="draft" invisible="'accrued' not in context.get('type', '-')"/>
20 </button>
21 </field>
22</record>
23
24<!-- Form view for lines -->
25<record id="account_cutoff_line_form" model="ir.ui.view">
26 <field name="name">account.cutoff.line.picking.form</field>
27 <field name="model">account.cutoff.line</field>
28 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_form"/>
29 <field name="arch" type="xml">
30 <field name="parent_id" position="after">
31 <field name="stock_move_id" invisible="'accrued' not in context.get('type', '-')"/>
32 <field name="product_id" invisible="'accrued' not in context.get('type', '-')" />
33 <field name="picking_id" invisible="'accrued' not in context.get('type', '-')"/>
34 <field name="picking_date_done" invisible="'accrued' not in context.get('type', '-')"/>
35 </field>
36 </field>
37</record>
38
39<!-- Tree view for lines -->
40<record id="account_cutoff_line_tree" model="ir.ui.view">
41 <field name="name">account.cutoff.line.picking.tree</field>
42 <field name="model">account.cutoff.line</field>
43 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_tree"/>
44 <field name="arch" type="xml">
45 <field name="parent_id" position="after">
46 <field name="stock_move_id" invisible="'accrued' not in context.get('type', '-')"/>
47 <field name="picking_date_done" invisible="'accrued' not in context.get('type', '-')"/>
48 </field>
49 </field>
50</record>
51
52
53</data>
54</openerp>
055
=== added directory 'account_cutoff_accrual_picking/i18n'
=== added file 'account_cutoff_accrual_picking/i18n/account_cutoff_accrual_picking.pot'
--- account_cutoff_accrual_picking/i18n/account_cutoff_accrual_picking.pot 1970-01-01 00:00:00 +0000
+++ account_cutoff_accrual_picking/i18n/account_cutoff_accrual_picking.pot 2014-03-09 00:39:34 +0000
@@ -0,0 +1,93 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * account_cutoff_accrual_picking
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-03-09 00:26+0000\n"
10"PO-Revision-Date: 2014-03-09 00:26+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: account_cutoff_accrual_picking
19#: sql_constraint:account.cutoff:0
20msgid "A cutoff of the same type already exists with this cut-off date !"
21msgstr ""
22
23#. module: account_cutoff_accrual_picking
24#: model:ir.model,name:account_cutoff_accrual_picking.model_account_cutoff_line
25msgid "Account Cut-off Line"
26msgstr ""
27
28#. module: account_cutoff_accrual_picking
29#: field:account.cutoff.line,product_id:0
30msgid "Product"
31msgstr ""
32
33#. module: account_cutoff_accrual_picking
34#: field:account.cutoff.line,stock_move_id:0
35msgid "Stock Move"
36msgstr ""
37
38#. module: account_cutoff_accrual_picking
39#: model:ir.model,name:account_cutoff_accrual_picking.model_account_cutoff
40msgid "Account Cut-off"
41msgstr ""
42
43#. module: account_cutoff_accrual_picking
44#: view:account.cutoff:0
45msgid "Re-Generate Lines from Picking"
46msgstr ""
47
48#. module: account_cutoff_accrual_picking
49#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:67
50#, python-format
51msgid "Missing income account on product '%s' or on its related product category."
52msgstr ""
53
54#. module: account_cutoff_accrual_picking
55#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:46
56#, python-format
57msgid "Missing expense account on product '%s' or on its related product category."
58msgstr ""
59
60#. module: account_cutoff_accrual_picking
61#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:100
62#, python-format
63msgid "Missing '%s' on tax '%s'."
64msgstr ""
65
66#. module: account_cutoff_accrual_picking
67#: sql_constraint:account.cutoff:0
68msgid "A cut-off of the same type already exists with the same date(s) !"
69msgstr ""
70
71#. module: account_cutoff_accrual_picking
72#: constraint:account.cutoff:0
73msgid "The start date is after the end date!"
74msgstr ""
75
76#. module: account_cutoff_accrual_picking
77#: field:account.cutoff.line,picking_id:0
78msgid "Picking"
79msgstr ""
80
81#. module: account_cutoff_accrual_picking
82#: field:account.cutoff.line,picking_date_done:0
83msgid "Date Done of the Picking"
84msgstr ""
85
86#. module: account_cutoff_accrual_picking
87#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:45
88#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:66
89#: code:addons/account_cutoff_accrual_picking/account_cutoff.py:99
90#, python-format
91msgid "Error:"
92msgstr ""
93
094
=== added directory 'account_cutoff_accrual_picking/images'
=== added file 'account_cutoff_accrual_picking/images/accrued_expense_done.jpg'
1Binary files account_cutoff_accrual_picking/images/accrued_expense_done.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_done.jpg 2014-03-09 00:39:34 +0000 differ95Binary files account_cutoff_accrual_picking/images/accrued_expense_done.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_done.jpg 2014-03-09 00:39:34 +0000 differ
=== added file 'account_cutoff_accrual_picking/images/accrued_expense_draft.jpg'
2Binary files account_cutoff_accrual_picking/images/accrued_expense_draft.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_draft.jpg 2014-03-09 00:39:34 +0000 differ96Binary files account_cutoff_accrual_picking/images/accrued_expense_draft.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_draft.jpg 2014-03-09 00:39:34 +0000 differ
=== added file 'account_cutoff_accrual_picking/images/accrued_expense_journal_entry.jpg'
3Binary files account_cutoff_accrual_picking/images/accrued_expense_journal_entry.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_journal_entry.jpg 2014-03-09 00:39:34 +0000 differ97Binary files account_cutoff_accrual_picking/images/accrued_expense_journal_entry.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/images/accrued_expense_journal_entry.jpg 2014-03-09 00:39:34 +0000 differ
=== added directory 'account_cutoff_accrual_picking/static'
=== added directory 'account_cutoff_accrual_picking/static/src'
=== added directory 'account_cutoff_accrual_picking/static/src/img'
=== added file 'account_cutoff_accrual_picking/static/src/img/icon.png'
4Binary files account_cutoff_accrual_picking/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/static/src/img/icon.png 2014-03-09 00:39:34 +0000 differ98Binary files account_cutoff_accrual_picking/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and account_cutoff_accrual_picking/static/src/img/icon.png 2014-03-09 00:39:34 +0000 differ
=== added directory 'account_cutoff_base'
=== added file 'account_cutoff_base/__init__.py'
--- account_cutoff_base/__init__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/__init__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,24 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from . import account_cutoff
24from . import company
025
=== added file 'account_cutoff_base/__openerp__.py'
--- account_cutoff_base/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/__openerp__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,47 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Account Cut-off Base',
26 'version': '0.1',
27 'category': 'Accounting & Finance',
28 'license': 'AGPL-3',
29 'summary': 'Base module for Account Cut-offs',
30 'description': """This module contains objets, fields and menu entries that are used by other cut-off modules. So you need to install other cut-off modules to get the additionnal functionalities :
31
32* the module *account_cutoff_prepaid* will manage prepaid cut-offs based on start date and end date,
33* the module *account_cutoff_accrual_picking* will manage the accruals based on the status of the pickings.
34
35Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
36 """,
37 'author': 'Akretion',
38 'website': 'http://www.akretion.com',
39 'depends': ['account_accountant'],
40 'data': [
41 'company_view.xml',
42 'account_cutoff_view.xml',
43 'security/ir.model.access.csv',
44 ],
45 'installable': True,
46 'active': False,
47}
048
=== added file 'account_cutoff_base/account_cutoff.py'
--- account_cutoff_base/account_cutoff.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/account_cutoff.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,438 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from openerp.osv import orm, fields
24import decimal_precision as dp
25from openerp.tools.translate import _
26from datetime import datetime
27
28
29class account_cutoff(orm.Model):
30 _name = 'account.cutoff'
31 _rec_name = 'cutoff_date'
32 _order = 'cutoff_date desc'
33 _description = 'Account Cut-off'
34
35 def copy(self, cr, uid, id, default=None, context=None):
36 if default is None:
37 default = {}
38 default.update({
39 'cutoff_date': '%d-12-31' % datetime.today().year,
40 'move_id': False,
41 'state': 'draft',
42 'line_ids': False,
43 })
44 return super(account_cutoff, self).copy(
45 cr, uid, id, default=default, context=context)
46
47 def _compute_total_cutoff(self, cr, uid, ids, name, arg, context=None):
48 res = {}
49 for cutoff in self.browse(cr, uid, ids, context=context):
50 res[cutoff.id] = 0
51 for line in cutoff.line_ids:
52 res[cutoff.id] += line.cutoff_amount
53 return res
54
55 _columns = {
56 'cutoff_date': fields.date(
57 'Cut-off Date', readonly=True,
58 states={'draft': [('readonly', False)]}),
59 'type': fields.selection([
60 ('accrued_revenue', 'Accrued Revenue'),
61 ('accrued_expense', 'Accrued Expense'),
62 ('prepaid_revenue', 'Prepaid Revenue'),
63 ('prepaid_expense', 'Prepaid Expense'),
64 ], 'Type', required=True, readonly=True,
65 states={'draft': [('readonly', False)]}),
66 'move_id': fields.many2one(
67 'account.move', 'Cut-off Journal Entry', readonly=True),
68 'move_label': fields.char(
69 'Label of the Cut-off Journal Entry',
70 size=64, readonly=True,
71 states={'draft': [('readonly', False)]},
72 help="This label will be written in the 'Name' field of the "
73 "Cut-off Account Move Lines and in the 'Reference' field of "
74 "the Cut-off Account Move."),
75 'cutoff_account_id': fields.many2one(
76 'account.account', 'Cut-off Account',
77 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
78 readonly=True, states={'draft': [('readonly', False)]}),
79 'cutoff_journal_id': fields.many2one(
80 'account.journal', 'Cut-off Account Journal',
81 readonly=True, states={'draft': [('readonly', False)]}),
82 'total_cutoff_amount': fields.function(
83 _compute_total_cutoff, type='float', string="Total Cut-off Amount",
84 readonly=True),
85 'company_id': fields.many2one(
86 'res.company', 'Company', required=True, readonly=True,
87 states={'draft': [('readonly', False)]}),
88 'company_currency_id': fields.related(
89 'company_id', 'currency_id', readonly=True, type='many2one',
90 relation='res.currency', string='Company Currency'),
91 'line_ids': fields.one2many(
92 'account.cutoff.line', 'parent_id', 'Cut-off Lines', readonly=True,
93 states={'draft': [('readonly', False)]}),
94 'state': fields.selection([
95 ('draft', 'Draft'),
96 ('done', 'Done'),
97 ],
98 'State', select=True, readonly=True,
99 help="State of the cutoff. When the Journal Entry is created, "
100 "the state is set to 'Done' and the fields become read-only."),
101 }
102
103 def _get_default_journal(self, cr, uid, context=None):
104 cur_user = self.pool['res.users'].browse(cr, uid, uid, context=context)
105 return cur_user.company_id.default_cutoff_journal_id.id or None
106
107 def _default_move_label(self, cr, uid, context=None):
108 if context is None:
109 context = {}
110 type = context.get('type')
111 cutoff_date = context.get('cutoff_date')
112 if cutoff_date:
113 cutoff_date_label = ' dated %s' % cutoff_date
114 else:
115 cutoff_date_label = ''
116 label = ''
117 if type == 'accrued_expense':
118 label = _('Accrued Expense%s') % cutoff_date_label
119 elif type == 'accrued_revenue':
120 label = _('Accrued Revenue%s') % cutoff_date_label
121 elif type == 'prepaid_revenue':
122 label = _('Prepaid Revenue%s') % cutoff_date_label
123 elif type == 'prepaid_expense':
124 label = _('Prepaid Expense%s') % cutoff_date_label
125 return label
126
127 def _default_type(self, cr, uid, context=None):
128 if context is None:
129 context = {}
130 return context.get('type')
131
132 def _inherit_default_cutoff_account_id(self, cr, uid, context=None):
133 '''Function designed to be inherited by other cutoff modules'''
134 return None
135
136 def _default_cutoff_account_id(self, cr, uid, context=None):
137 '''This function can't be inherited, so we use a second function'''
138 return self._inherit_default_cutoff_account_id(
139 cr, uid, context=context)
140
141 _defaults = {
142 'state': 'draft',
143 'company_id': lambda self, cr, uid, context:
144 self.pool['res.users'].browse(
145 cr, uid, uid, context=context).company_id.id,
146 'cutoff_journal_id': _get_default_journal,
147 'move_label': _default_move_label,
148 'type': _default_type,
149 'cutoff_account_id': _default_cutoff_account_id,
150 }
151
152 _sql_constraints = [(
153 'date_type_company_uniq',
154 'unique(cutoff_date, company_id, type)',
155 'A cutoff of the same type already exists with this cut-off date !'
156 )]
157
158 def cutoff_date_onchange(
159 self, cr, uid, ids, type, cutoff_date, move_label, context=None):
160 if context is None:
161 context = {}
162 res = {'value': {}}
163 if type and cutoff_date:
164 ctx = context.copy()
165 ctx.update({'type': type, 'cutoff_date': cutoff_date})
166 res['value']['move_label'] = self._default_move_label(
167 cr, uid, context=ctx)
168 return res
169
170 def back2draft(self, cr, uid, ids, context=None):
171 assert len(ids) == 1,\
172 'This function should only be used for a single id at a time'
173 cur_cutoff = self.browse(cr, uid, ids[0], context=context)
174 if cur_cutoff.move_id:
175 self.pool['account.move'].unlink(
176 cr, uid, [cur_cutoff.move_id.id], context=context)
177 self.write(cr, uid, ids[0], {'state': 'draft'}, context=context)
178 return True
179
180 def _prepare_move(self, cr, uid, cur_cutoff, to_provision, context=None):
181 if context is None:
182 context = {}
183 movelines_to_create = []
184 amount_total = 0
185 move_label = cur_cutoff.move_label
186 for (cutoff_account_id, analytic_account_id), amount in \
187 to_provision.items():
188 movelines_to_create.append((0, 0, {
189 'account_id': cutoff_account_id,
190 'name': move_label,
191 'debit': amount < 0 and amount * -1 or 0,
192 'credit': amount >= 0 and amount or 0,
193 'analytic_account_id': analytic_account_id,
194 }))
195 amount_total += amount
196
197 # add contre-partie
198 counterpart_amount = amount_total * -1
199 movelines_to_create.append((0, 0, {
200 'account_id': cur_cutoff.cutoff_account_id.id,
201 'debit': counterpart_amount < 0 and counterpart_amount * -1 or 0,
202 'credit': counterpart_amount >= 0 and counterpart_amount or 0,
203 'name': move_label,
204 'analytic_account_id': False,
205 }))
206
207 # Select period
208 local_ctx = context.copy()
209 local_ctx['account_period_prefer_normal'] = True
210 period_search = self.pool['account.period'].find(
211 cr, uid, cur_cutoff.cutoff_date, context=local_ctx)
212 if len(period_search) != 1:
213 raise orm.except_orm(
214 'Error:', "No matching period for date '%s'"
215 % cur_cutoff.cutoff_date)
216 period_id = period_search[0]
217
218 res = {
219 'journal_id': cur_cutoff.cutoff_journal_id.id,
220 'date': cur_cutoff.cutoff_date,
221 'period_id': period_id,
222 'ref': move_label,
223 'line_id': movelines_to_create,
224 }
225 return res
226
227 def create_move(self, cr, uid, ids, context=None):
228 assert len(ids) == 1, \
229 'This function should only be used for a single id at a time'
230 move_obj = self.pool['account.move']
231 cur_cutoff = self.browse(cr, uid, ids[0], context=context)
232 if cur_cutoff.move_id:
233 raise orm.except_orm(
234 _('Error:'),
235 _("The Cut-off Journal Entry already exists. You should "
236 "delete it before running this function."))
237 if not cur_cutoff.line_ids:
238 raise orm.except_orm(
239 _('Error:'),
240 _("There are no lines on this Cut-off, so we can't create "
241 "a Journal Entry."))
242 to_provision = {}
243 # key = (cutoff_account_id, analytic_account_id)
244 # value = amount
245 for line in cur_cutoff.line_ids:
246 # if it is already present
247 if (
248 line.cutoff_account_id.id,
249 line.analytic_account_id.id or False
250 ) in to_provision:
251 to_provision[(
252 line.cutoff_account_id.id,
253 line.analytic_account_id.id or False
254 )] += line.cutoff_amount
255 else:
256 # if not already present
257 to_provision[(
258 line.cutoff_account_id.id,
259 line.analytic_account_id.id or False
260 )] = line.cutoff_amount
261 # Same for tax lines
262 for tax_line in line.tax_line_ids:
263 if (
264 tax_line.cutoff_account_id.id,
265 tax_line.analytic_account_id.id or False
266 ) in to_provision:
267 to_provision[(
268 tax_line.cutoff_account_id.id,
269 tax_line.analytic_account_id.id or False
270 )] += tax_line.cutoff_amount
271 else:
272 to_provision[(
273 tax_line.cutoff_account_id.id,
274 tax_line.analytic_account_id.id or False
275 )] = tax_line.cutoff_amount
276
277 vals = self._prepare_move(
278 cr, uid, cur_cutoff, to_provision, context=context)
279 move_id = move_obj.create(cr, uid, vals, context=context)
280 move_obj.validate(cr, uid, [move_id], context=context)
281 self.write(cr, uid, ids[0], {
282 'move_id': move_id,
283 'state': 'done',
284 }, context=context)
285
286 action = {
287 'name': 'Cut-off Account Move',
288 'view_type': 'form',
289 'view_mode': 'form,tree',
290 'res_id': move_id,
291 'res_model': 'account.move',
292 'type': 'ir.actions.act_window',
293 'nodestroy': True,
294 'target': 'current',
295 }
296 return action
297
298
299class account_cutoff_line(orm.Model):
300 _name = 'account.cutoff.line'
301 _description = 'Account Cut-off Line'
302
303 _columns = {
304 'parent_id': fields.many2one(
305 'account.cutoff', 'Cut-off', ondelete='cascade'),
306 'name': fields.char('Description', size=64),
307 'company_currency_id': fields.related(
308 'parent_id', 'company_currency_id', type='many2one',
309 relation='res.currency', string="Company Currency", readonly=True),
310 'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
311 'account_id': fields.many2one(
312 'account.account', 'Account',
313 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
314 required=True, readonly=True),
315 'cutoff_account_id': fields.many2one(
316 'account.account', 'Cut-off Account',
317 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
318 required=True, readonly=True),
319 'cutoff_account_code': fields.related(
320 'cutoff_account_id', 'code', type='char',
321 string='Cut-off Account Code', readonly=True),
322 'analytic_account_id': fields.many2one(
323 'account.analytic.account', 'Analytic Account',
324 domain=[('type', 'not in', ('view', 'template'))],
325 readonly=True),
326 'analytic_account_code': fields.related(
327 'analytic_account_id', 'code', type='char',
328 string='Analytic Account Code', readonly=True),
329 'currency_id': fields.many2one(
330 'res.currency', 'Amount Currency', readonly=True,
331 help="Currency of the 'Amount' field."),
332 'amount': fields.float(
333 'Amount', digits_compute=dp.get_precision('Account'),
334 readonly=True,
335 help="Amount that is used as base to compute the Cut-off Amount. "
336 "This Amount is in the 'Amount Currency', which may be different "
337 "from the 'Company Currency'."),
338 'cutoff_amount': fields.float(
339 'Cut-off Amount', digits_compute=dp.get_precision('Account'),
340 readonly=True,
341 help="Cut-off Amount without taxes in the Company Currency."),
342 'tax_ids': fields.many2many(
343 'account.tax', id1='cutoff_line_id', id2='tax_id', string='Taxes',
344 readonly=True),
345 'tax_line_ids': fields.one2many(
346 'account.cutoff.tax.line', 'parent_id', 'Cut-off Tax Lines',
347 readonly=True),
348 }
349
350
351class account_cutoff_tax_line(orm.Model):
352 _name = 'account.cutoff.tax.line'
353 _description = 'Account Cut-off Tax Line'
354
355 _columns = {
356 'parent_id': fields.many2one(
357 'account.cutoff.line', 'Account Cut-off Line',
358 ondelete='cascade', required=True),
359 'tax_id': fields.many2one('account.tax', 'Tax', required=True),
360 'cutoff_account_id': fields.many2one(
361 'account.account', 'Cut-off Account',
362 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
363 required=True, readonly=True),
364 'analytic_account_id': fields.many2one(
365 'account.analytic.account', 'Analytic Account',
366 domain=[('type', 'not in', ('view', 'template'))],
367 readonly=True),
368 'base': fields.float(
369 'Base', digits_compute=dp.get_precision('Account'),
370 readonly=True, help="Base Amount in the currency of the PO."),
371 'amount': fields.float(
372 'Tax Amount', digits_compute=dp.get_precision('Account'),
373 readonly=True, help='Tax Amount in the currency of the PO.'),
374 'sequence': fields.integer('Sequence', readonly=True),
375 'cutoff_amount': fields.float(
376 'Cut-off Tax Amount', digits_compute=dp.get_precision('Account'),
377 readonly=True,
378 help="Tax Cut-off Amount in the company currency."),
379 'currency_id': fields.related(
380 'parent_id', 'currency_id', type='many2one',
381 relation='res.currency', string='Currency', readonly=True),
382 'company_currency_id': fields.related(
383 'parent_id', 'company_currency_id',
384 type='many2one', relation='res.currency',
385 string="Company Currency", readonly=True),
386 }
387
388
389class account_cutoff_mapping(orm.Model):
390 _name = 'account.cutoff.mapping'
391 _description = 'Account Cut-off Mapping'
392 _rec_name = 'account_id'
393
394 _columns = {
395 'company_id': fields.many2one('res.company', 'Company', required=True),
396 'account_id': fields.many2one(
397 'account.account', 'Regular Account',
398 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
399 required=True),
400 'cutoff_account_id': fields.many2one(
401 'account.account', 'Cut-off Account',
402 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')],
403 required=True),
404 'cutoff_type': fields.selection([
405 ('all', 'All Cut-off Types'),
406 ('accrued_revenue', 'Accrued Revenue'),
407 ('accrued_expense', 'Accrued Expense'),
408 ('prepaid_revenue', 'Prepaid Revenue'),
409 ('prepaid_expense', 'Prepaid Expense'),
410 ], 'Cut-off Type', required=True),
411 }
412
413 _defaults = {
414 'company_id': lambda self, cr, uid, context:
415 self.pool['res.users'].browse(
416 cr, uid, uid, context=context).company_id.id,
417 }
418
419 def _get_mapping_dict(
420 self, cr, uid, company_id, cutoff_type='all', context=None):
421 '''return a dict with:
422 key = ID of account,
423 value = ID of cutoff_account'''
424 if cutoff_type == 'all':
425 cutoff_type_filter = ('all')
426 else:
427 cutoff_type_filter = ('all', cutoff_type)
428 mapping_ids = self.search(
429 cr, uid, [
430 ('company_id', '=', company_id),
431 ('cutoff_type', 'in', cutoff_type_filter),
432 ],
433 context=context)
434 mapping_read = self.read(cr, uid, mapping_ids, context=context)
435 mapping = {}
436 for item in mapping_read:
437 mapping[item['account_id'][0]] = item['cutoff_account_id'][0]
438 return mapping
0439
=== added file 'account_cutoff_base/account_cutoff_view.xml'
--- account_cutoff_base/account_cutoff_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/account_cutoff_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,218 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<menuitem id="cutoff_menu"
13 parent="account.menu_finance_periodical_processing"
14 name="Cut-offs"
15 sequence="24"
16 groups="account.group_account_user,account.group_account_manager,account.group_account_invoice"/>
17
18<!-- Form view -->
19<record id="account_cutoff_form" model="ir.ui.view">
20 <field name="name">account.cutoff.form</field>
21 <field name="model">account.cutoff</field>
22 <field name="type">form</field>
23 <field name="arch" type="xml">
24 <form string="Cut-offs">
25 <group name="general-params" colspan="2" col="2">
26 <field name="type" readonly="1" />
27 <field name="cutoff_date" on_change="cutoff_date_onchange(type, cutoff_date, move_label, context)" required="1"/>
28 <field name="total_cutoff_amount" />
29 <field name="company_currency_id" />
30 <field name="company_id" groups="base.group_multi_company" widget="selection" />
31 </group>
32 <group name="accounting-params" colspan="2" col="2">
33 <field name="cutoff_journal_id" required="1"/>
34 <field name="cutoff_account_id" required="1"/>
35 <field name="move_label" required="1"/>
36 <field name="move_id"/>
37 </group>
38 <button name="create_move" string="Create Journal Entry" type="object" states="draft" attrs="{'invisible': ['|', ('line_ids', '=', False), ('state', '=', 'done')]}"/>
39 <newline />
40 <field name="line_ids" nolabel="1" context="{'type': type}" colspan="4"/>
41 <group colspan="4">
42 <field name="state" widget="statusbar" />
43 <button name="back2draft" string="Back to Draft" type="object" states="done" />
44 </group>
45 </form>
46 </field>
47</record>
48
49<!-- Tree view -->
50<record id="account_cutoff_tree" model="ir.ui.view">
51 <field name="name">account.cutoff.tree</field>
52 <field name="model">account.cutoff</field>
53 <field name="type">tree</field>
54 <field name="arch" type="xml">
55 <tree string="Cut-offs" colors="blue:state=='draft'">
56 <field name="type" invisible="context.get('type')" />
57 <field name="cutoff_date" />
58 <field name="total_cutoff_amount"/>
59 <field name="company_currency_id"/>
60 <field name="state"/>
61 </tree>
62 </field>
63</record>
64
65<!-- Search view -->
66<record id="account_cutoff_filter" model="ir.ui.view">
67 <field name="name">account.cutoff.filter</field>
68 <field name="model">account.cutoff</field>
69 <field name="type">search</field>
70 <field name="arch" type="xml">
71 <search string="Search Cut-offs">
72 <filter name="draft" string="Draft" domain="[('state', '=', 'draft')]" icon="terp-document-new" />
73 <filter name="done" string="Done" domain="[('state', '=', 'done')]" icon="terp-camera_test" />
74 </search>
75 </field>
76</record>
77
78<!-- Form view for lines -->
79<record id="account_cutoff_line_form" model="ir.ui.view">
80 <field name="name">account.cutoff.line.form</field>
81 <field name="model">account.cutoff.line</field>
82 <field name="type">form</field>
83 <field name="arch" type="xml">
84 <form string="Cut-off Lines">
85 <group name="source" string="Source" colspan="4" col="4">
86 <field name="parent_id" invisible="not context.get('account_cutoff_line_main_view', False)"/>
87 <field name="partner_id"/>
88 <field name="name"/>
89 <field name="account_id"/>
90 <field name="cutoff_account_id"/>
91 <field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
92 <field name="tax_ids" invisible="'accrued' not in context.get('type', '-')"/>
93 <field name="amount" />
94 <field name="currency_id" />
95 </group>
96 <group name="cutoff" string="Cut-off Computation" colspan="4" col="4">
97 <field name="cutoff_amount" />
98 <field name="company_currency_id" />
99 <field name="tax_line_ids" nolabel="1" invisible="'accrued' not in context.get('type', '-')" colspan="4"/>
100 </group>
101 </form>
102 </field>
103</record>
104
105<!-- Tree view for lines -->
106<record id="account_cutoff_line_tree" model="ir.ui.view">
107 <field name="name">account.cutoff.line.tree</field>
108 <field name="model">account.cutoff.line</field>
109 <field name="type">tree</field>
110 <field name="arch" type="xml">
111 <tree string="Cut-off Lines">
112 <field name="parent_id" invisible="not context.get('account_cutoff_line_main_view', False)"/>
113 <field name="partner_id"/>
114 <field name="name"/>
115 <field name="cutoff_account_code"/>
116 <field name="analytic_account_code" groups="analytic.group_analytic_accounting"/>
117 <field name="tax_ids" invisible="'accrued' not in context.get('type', '-')"/>
118 <field name="amount"/>
119 <field name="currency_id"/>
120 <field name="cutoff_amount"/>
121 <field name="company_currency_id"/>
122 </tree>
123 </field>
124</record>
125
126<!-- Form view for tax lines -->
127<record id="account_cutoff_tax_line_form" model="ir.ui.view">
128 <field name="name">account.cutoff.tax.line.form</field>
129 <field name="model">account.cutoff.tax.line</field>
130 <field name="type">form</field>
131 <field name="arch" type="xml">
132 <form string="Cut-off Tax Lines">
133 <group name="tax" string="Tax">
134 <field name="parent_id" invisible="not context.get('account_cutoff_tax_line_main_view', False)"/>
135 <field name="tax_id"/>
136 <field name="sequence"/>
137 <field name="cutoff_account_id"/>
138 <field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
139 <field name="base"/>
140 <field name="amount"/>
141 <field name="currency_id"/>
142 </group>
143 <group name="cutoff" string="Cut-off Computation">
144 <field name="cutoff_amount"/>
145 <field name="company_currency_id"/>
146 </group>
147 </form>
148 </field>
149</record>
150
151<!-- Tree view for tax lines -->
152<record id="account_cutoff_tax_line_tree" model="ir.ui.view">
153 <field name="name">account.cutoff.tax.line.tree</field>
154 <field name="model">account.cutoff.tax.line</field>
155 <field name="type">tree</field>
156 <field name="arch" type="xml">
157 <tree string="Cut-off Tax Lines">
158 <field name="parent_id" invisible="not context.get('account_cutoff_tax_line_main_view', False)"/>
159 <field name="tax_id"/>
160 <field name="cutoff_account_id"/>
161 <field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
162 <field name="base"/>
163 <field name="amount"/>
164 <field name="currency_id"/>
165 <field name="cutoff_amount"/>
166 <field name="company_currency_id"/>
167 <field name="sequence" invisible="True"/>
168 </tree>
169 </field>
170</record>
171
172<!-- Form view for account mappings -->
173<record id="account_cutoff_mapping_form" model="ir.ui.view">
174 <field name="name">account.cutoff.mapping.form</field>
175 <field name="model">account.cutoff.mapping</field>
176 <field name="type">form</field>
177 <field name="arch" type="xml">
178 <form string="Account Cut-off Mapping">
179 <field name="company_id" groups="base.group_multi_company" widget="selection" invisible="not context.get('account_cutoff_mapping_main_view', False)" />
180 <field name="account_id"/>
181 <field name="cutoff_account_id"/>
182 <field name="cutoff_type"/>
183 </form>
184 </field>
185</record>
186
187<!-- Tree view for account mappings -->
188<record id="account_cutoff_mapping_tree" model="ir.ui.view">
189 <field name="name">account.cutoff.mapping.tree</field>
190 <field name="model">account.cutoff.mapping</field>
191 <field name="type">tree</field>
192 <field name="arch" type="xml">
193 <tree string="Account Cut-off Mapping" editable="bottom">
194 <field name="company_id" groups="base.group_multi_company" widget="selection" invisible="not context.get('account_cutoff_mapping_main_view', False)" />
195 <field name="account_id"/>
196 <field name="cutoff_account_id"/>
197 <field name="cutoff_type"/>
198 </tree>
199 </field>
200</record>
201
202<!-- Action for account mappings -->
203<record id="account_cutoff_mapping_action" model="ir.actions.act_window">
204 <field name="name">Cut-off Account Mapping</field>
205 <field name="res_model">account.cutoff.mapping</field>
206 <field name="view_type">form</field>
207 <field name="view_mode">tree,form</field>
208 <field name="context">{'account_cutoff_mapping_main_view': True}</field>
209</record>
210
211<!-- Menu entry for account mapping -->
212<menuitem id="account_cutoff_mapping_menu"
213 parent="account.account_account_menu"
214 action="account_cutoff_mapping_action"
215 sequence="100"/>
216
217</data>
218</openerp>
0219
=== added file 'account_cutoff_base/company.py'
--- account_cutoff_base/company.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/company.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,35 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Base module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25
26
27class res_company(orm.Model):
28 _inherit = 'res.company'
29
30 _columns = {
31 'default_cutoff_journal_id': fields.many2one(
32 'account.journal', 'Default Cut-off Journal'),
33 'cutoff_account_mapping_ids': fields.one2many(
34 'account.cutoff.mapping', 'company_id', 'Cut-off Account Mapping'),
35 }
036
=== added file 'account_cutoff_base/company_view.xml'
--- account_cutoff_base/company_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/company_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<record id="view_company_form" model="ir.ui.view">
13 <field name="name">cutoff.company.form</field>
14 <field name="model">res.company</field>
15 <field name="inherit_id" ref="base.view_company_form" />
16 <field name="arch" type="xml">
17 <field name="currency_id" position="after">
18 <group name="cutoff" string="Cut-offs" colspan="2" col="2">
19 <field name="default_cutoff_journal_id" />
20 </group>
21 </field>
22 </field>
23</record>
24
25
26</data>
27</openerp>
028
=== added directory 'account_cutoff_base/i18n'
=== added file 'account_cutoff_base/i18n/account_cutoff_base.pot'
--- account_cutoff_base/i18n/account_cutoff_base.pot 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/i18n/account_cutoff_base.pot 2014-03-09 00:39:34 +0000
@@ -0,0 +1,403 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * account_cutoff_base
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-03-09 00:22+0000\n"
10"PO-Revision-Date: 2014-03-09 00:22+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: account_cutoff_base
19#: field:account.cutoff,line_ids:0
20#: view:account.cutoff.line:0
21msgid "Cut-off Lines"
22msgstr ""
23
24#. module: account_cutoff_base
25#: field:account.cutoff,move_id:0
26msgid "Cut-off Journal Entry"
27msgstr ""
28
29#. module: account_cutoff_base
30#: constraint:account.cutoff:0
31msgid "The start date is after the end date!"
32msgstr ""
33
34#. module: account_cutoff_base
35#: help:account.cutoff,move_label:0
36msgid "This label will be written in the 'Name' field of the Cut-off Account Move Lines and in the 'Reference' field of the Cut-off Account Move."
37msgstr ""
38
39#. module: account_cutoff_base
40#: view:account.cutoff:0
41msgid "Search Cut-offs"
42msgstr ""
43
44#. module: account_cutoff_base
45#: help:account.cutoff,state:0
46msgid "State of the cutoff. When the Journal Entry is created, the state is set to 'Done' and the fields become read-only."
47msgstr ""
48
49#. module: account_cutoff_base
50#: constraint:res.company:0
51msgid "Error! You can not create recursive companies."
52msgstr ""
53
54#. module: account_cutoff_base
55#: field:account.cutoff.mapping,cutoff_type:0
56msgid "Cut-off Type"
57msgstr ""
58
59#. module: account_cutoff_base
60#: code:addons/account_cutoff_base/account_cutoff.py:235
61#, python-format
62msgid "The Cut-off Journal Entry already exists. You should delete it before running this function."
63msgstr ""
64
65#. module: account_cutoff_base
66#: view:account.cutoff.line:0
67msgid "Source"
68msgstr ""
69
70#. module: account_cutoff_base
71#: field:account.cutoff,state:0
72msgid "State"
73msgstr ""
74
75#. module: account_cutoff_base
76#: field:account.cutoff.line,cutoff_account_code:0
77msgid "Cut-off Account Code"
78msgstr ""
79
80#. module: account_cutoff_base
81#: selection:account.cutoff,type:0
82#: selection:account.cutoff.mapping,cutoff_type:0
83msgid "Prepaid Expense"
84msgstr ""
85
86#. module: account_cutoff_base
87#: code:addons/account_cutoff_base/account_cutoff.py:240
88#, python-format
89msgid "There are no lines on this Cut-off, so we can't create a Journal Entry."
90msgstr ""
91
92#. module: account_cutoff_base
93#: view:account.cutoff.mapping:0
94#: model:ir.model,name:account_cutoff_base.model_account_cutoff_mapping
95msgid "Account Cut-off Mapping"
96msgstr ""
97
98#. module: account_cutoff_base
99#: help:account.cutoff.tax.line,amount:0
100msgid "Tax Amount in the currency of the PO."
101msgstr ""
102
103#. module: account_cutoff_base
104#: selection:account.cutoff,type:0
105#: selection:account.cutoff.mapping,cutoff_type:0
106msgid "Accrued Revenue"
107msgstr ""
108
109#. module: account_cutoff_base
110#: field:account.cutoff.line,partner_id:0
111msgid "Partner"
112msgstr ""
113
114#. module: account_cutoff_base
115#: field:account.cutoff,cutoff_date:0
116msgid "Cut-off Date"
117msgstr ""
118
119#. module: account_cutoff_base
120#: field:account.cutoff.line,name:0
121msgid "Description"
122msgstr ""
123
124#. module: account_cutoff_base
125#: field:account.cutoff,type:0
126msgid "Type"
127msgstr ""
128
129#. module: account_cutoff_base
130#: field:account.cutoff,company_id:0
131#: field:account.cutoff.mapping,company_id:0
132msgid "Company"
133msgstr ""
134
135#. module: account_cutoff_base
136#: field:account.cutoff,cutoff_journal_id:0
137msgid "Cut-off Account Journal"
138msgstr ""
139
140#. module: account_cutoff_base
141#: model:ir.model,name:account_cutoff_base.model_account_cutoff_tax_line
142msgid "Account Cut-off Tax Line"
143msgstr ""
144
145#. module: account_cutoff_base
146#: selection:account.cutoff,type:0
147#: selection:account.cutoff.mapping,cutoff_type:0
148msgid "Prepaid Revenue"
149msgstr ""
150
151#. module: account_cutoff_base
152#: help:account.cutoff.line,currency_id:0
153msgid "Currency of the 'Amount' field."
154msgstr ""
155
156#. module: account_cutoff_base
157#: selection:account.cutoff,type:0
158#: selection:account.cutoff.mapping,cutoff_type:0
159msgid "Accrued Expense"
160msgstr ""
161
162#. module: account_cutoff_base
163#: field:account.cutoff,total_cutoff_amount:0
164msgid "Total Cut-off Amount"
165msgstr ""
166
167#. module: account_cutoff_base
168#: field:account.cutoff,company_currency_id:0
169#: field:account.cutoff.line,company_currency_id:0
170#: field:account.cutoff.tax.line,company_currency_id:0
171msgid "Company Currency"
172msgstr ""
173
174#. module: account_cutoff_base
175#: field:account.cutoff.tax.line,base:0
176msgid "Base"
177msgstr ""
178
179#. module: account_cutoff_base
180#: field:res.company,default_cutoff_journal_id:0
181msgid "Default Cut-off Journal"
182msgstr ""
183
184#. module: account_cutoff_base
185#: view:account.cutoff:0
186#: selection:account.cutoff,state:0
187msgid "Done"
188msgstr ""
189
190#. module: account_cutoff_base
191#: field:account.cutoff.line,parent_id:0
192msgid "Cut-off"
193msgstr ""
194
195#. module: account_cutoff_base
196#: view:account.cutoff:0
197msgid "Back to Draft"
198msgstr ""
199
200#. module: account_cutoff_base
201#: code:addons/account_cutoff_base/account_cutoff.py:234
202#: code:addons/account_cutoff_base/account_cutoff.py:239
203#, python-format
204msgid "Error:"
205msgstr ""
206
207#. module: account_cutoff_base
208#: sql_constraint:account.cutoff:0
209msgid "A cutoff of the same type already exists with this cut-off date !"
210msgstr ""
211
212#. module: account_cutoff_base
213#: field:account.cutoff.tax.line,parent_id:0
214#: model:ir.model,name:account_cutoff_base.model_account_cutoff_line
215msgid "Account Cut-off Line"
216msgstr ""
217
218#. module: account_cutoff_base
219#: field:account.cutoff.line,account_id:0
220msgid "Account"
221msgstr ""
222
223#. module: account_cutoff_base
224#: field:account.cutoff.line,tax_line_ids:0
225#: view:account.cutoff.tax.line:0
226msgid "Cut-off Tax Lines"
227msgstr ""
228
229#. module: account_cutoff_base
230#: sql_constraint:res.company:0
231msgid "The company name must be unique !"
232msgstr ""
233
234#. module: account_cutoff_base
235#: field:account.cutoff.tax.line,cutoff_amount:0
236msgid "Cut-off Tax Amount"
237msgstr ""
238
239#. module: account_cutoff_base
240#: help:account.cutoff.tax.line,cutoff_amount:0
241msgid "Tax Cut-off Amount in the company currency."
242msgstr ""
243
244#. module: account_cutoff_base
245#: model:ir.model,name:account_cutoff_base.model_account_cutoff
246msgid "Account Cut-off"
247msgstr ""
248
249#. module: account_cutoff_base
250#: field:account.cutoff.tax.line,amount:0
251msgid "Tax Amount"
252msgstr ""
253
254#. module: account_cutoff_base
255#: model:ir.model,name:account_cutoff_base.model_res_company
256msgid "Companies"
257msgstr ""
258
259#. module: account_cutoff_base
260#: field:account.cutoff.line,tax_ids:0
261msgid "Taxes"
262msgstr ""
263
264#. module: account_cutoff_base
265#: view:account.cutoff:0
266#: model:ir.ui.menu,name:account_cutoff_base.cutoff_menu
267#: view:res.company:0
268msgid "Cut-offs"
269msgstr ""
270
271#. module: account_cutoff_base
272#: view:account.cutoff:0
273msgid "Create Journal Entry"
274msgstr ""
275
276#. module: account_cutoff_base
277#: field:account.cutoff.line,currency_id:0
278msgid "Amount Currency"
279msgstr ""
280
281#. module: account_cutoff_base
282#: field:account.cutoff.mapping,account_id:0
283msgid "Regular Account"
284msgstr ""
285
286#. module: account_cutoff_base
287#: field:account.cutoff,move_label:0
288msgid "Label of the Cut-off Journal Entry"
289msgstr ""
290
291#. module: account_cutoff_base
292#: code:addons/account_cutoff_base/account_cutoff.py:124
293#, python-format
294msgid "Prepaid Expense%s"
295msgstr ""
296
297#. module: account_cutoff_base
298#: view:account.cutoff.line:0
299#: view:account.cutoff.tax.line:0
300msgid "Cut-off Computation"
301msgstr ""
302
303#. module: account_cutoff_base
304#: selection:account.cutoff.mapping,cutoff_type:0
305msgid "All Cut-off Types"
306msgstr ""
307
308#. module: account_cutoff_base
309#: help:account.cutoff.tax.line,base:0
310msgid "Base Amount in the currency of the PO."
311msgstr ""
312
313#. module: account_cutoff_base
314#: code:addons/account_cutoff_base/account_cutoff.py:120
315#, python-format
316msgid "Accrued Revenue%s"
317msgstr ""
318
319#. module: account_cutoff_base
320#: field:account.cutoff.tax.line,sequence:0
321msgid "Sequence"
322msgstr ""
323
324#. module: account_cutoff_base
325#: view:account.cutoff.tax.line:0
326#: field:account.cutoff.tax.line,tax_id:0
327msgid "Tax"
328msgstr ""
329
330#. module: account_cutoff_base
331#: field:account.cutoff.line,amount:0
332msgid "Amount"
333msgstr ""
334
335#. module: account_cutoff_base
336#: field:account.cutoff,cutoff_account_id:0
337#: field:account.cutoff.line,cutoff_account_id:0
338#: field:account.cutoff.mapping,cutoff_account_id:0
339#: field:account.cutoff.tax.line,cutoff_account_id:0
340msgid "Cut-off Account"
341msgstr ""
342
343#. module: account_cutoff_base
344#: field:account.cutoff.line,analytic_account_id:0
345#: field:account.cutoff.tax.line,analytic_account_id:0
346msgid "Analytic Account"
347msgstr ""
348
349#. module: account_cutoff_base
350#: field:account.cutoff.tax.line,currency_id:0
351msgid "Currency"
352msgstr ""
353
354#. module: account_cutoff_base
355#: field:account.cutoff.line,analytic_account_code:0
356msgid "Analytic Account Code"
357msgstr ""
358
359#. module: account_cutoff_base
360#: model:ir.actions.act_window,name:account_cutoff_base.account_cutoff_mapping_action
361#: model:ir.ui.menu,name:account_cutoff_base.account_cutoff_mapping_menu
362#: field:res.company,cutoff_account_mapping_ids:0
363msgid "Cut-off Account Mapping"
364msgstr ""
365
366#. module: account_cutoff_base
367#: code:addons/account_cutoff_base/account_cutoff.py:122
368#, python-format
369msgid "Prepaid Revenue%s"
370msgstr ""
371
372#. module: account_cutoff_base
373#: help:account.cutoff.line,amount:0
374msgid "Amount that is used as base to compute the Cut-off Amount. This Amount is in the 'Amount Currency', which may be different from the 'Company Currency'."
375msgstr ""
376
377#. module: account_cutoff_base
378#: sql_constraint:account.cutoff:0
379msgid "A cut-off of the same type already exists with the same date(s) !"
380msgstr ""
381
382#. module: account_cutoff_base
383#: view:account.cutoff:0
384#: selection:account.cutoff,state:0
385msgid "Draft"
386msgstr ""
387
388#. module: account_cutoff_base
389#: help:account.cutoff.line,cutoff_amount:0
390msgid "Cut-off Amount without taxes in the Company Currency."
391msgstr ""
392
393#. module: account_cutoff_base
394#: code:addons/account_cutoff_base/account_cutoff.py:118
395#, python-format
396msgid "Accrued Expense%s"
397msgstr ""
398
399#. module: account_cutoff_base
400#: field:account.cutoff.line,cutoff_amount:0
401msgid "Cut-off Amount"
402msgstr ""
403
0404
=== added directory 'account_cutoff_base/security'
=== added file 'account_cutoff_base/security/ir.model.access.csv'
--- account_cutoff_base/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ account_cutoff_base/security/ir.model.access.csv 2014-03-09 00:39:34 +0000
@@ -0,0 +1,9 @@
1id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2access_account_cutoff_mapping,Full access on account.cutoff.mapping,model_account_cutoff_mapping,account.group_account_manager,1,1,1,1
3access_account_cutoff_mapping_user,Read access on account.cutoff.mapping,model_account_cutoff_mapping,base.group_user,1,0,0,0
4access_account_cutoff,Full access on account.cutoff,model_account_cutoff,account.group_account_manager,1,1,1,1
5access_account_cutoff_read,Read access on account.cutoff,model_account_cutoff,account.group_account_user,1,0,0,0
6access_account_cutoff_line,Full access on account.cutoff.line,model_account_cutoff_line,account.group_account_manager,1,1,1,1
7access_account_cutoff_line_read,Read access on account.cutoff.line,model_account_cutoff_line,account.group_account_user,1,0,0,0
8access_account_cutoff_tax_line,Full access on account.cutoff.tax.line,model_account_cutoff_tax_line,account.group_account_manager,1,1,1,1
9access_account_cutoff_tax_line_read,Read access on account.cutoff.tax.line,model_account_cutoff_tax_line,account.group_account_user,1,0,0,0
010
=== added directory 'account_cutoff_prepaid'
=== added file 'account_cutoff_prepaid/__init__.py'
--- account_cutoff_prepaid/__init__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/__init__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,26 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23from . import company
24from . import product
25from . import account
26from . import account_cutoff
027
=== added file 'account_cutoff_prepaid/__openerp__.py'
--- account_cutoff_prepaid/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/__openerp__.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,57 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24{
25 'name': 'Account Cut-off Prepaid',
26 'version': '0.2',
27 'category': 'Accounting & Finance',
28 'license': 'AGPL-3',
29 'summary': 'Prepaid Expense, Prepaid Revenue',
30 'description': """
31Manage prepaid expense and revenue based on start and end dates
32===============================================================
33
34This module adds a **Start Date** and **End Date** field on invoice lines. For example, if you have an insurance contrat for your company that run from April 1st 2013 to March 31st 2014, you will enter these dates as start and end dates on the supplier invoice line. If your fiscal year ends on December 31st 2013, 3 months of expenses are part of the 2014 fiscal year and should not be part of the 2013 fiscal year. So, thanks to this module, you will create a *Prepaid Expense* on December 31st 2013 and OpenERP will identify this expense with the 3 months that are after the cut-off date and propose to generate the appropriate cut-off journal entry.
35
36Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
37 """,
38 'author': 'Akretion',
39 'website': 'http://www.akretion.com',
40 'depends': ['account_cutoff_base'],
41 'data': [
42 'company_view.xml',
43 'product_view.xml',
44 'account_invoice_view.xml',
45 'account_view.xml',
46 'account_cutoff_view.xml',
47 ],
48 'demo': ['product_demo.xml'],
49 'images': [
50 'images/prepaid_revenue_draft.jpg',
51 'images/prepaid_revenue_journal_entry.jpg',
52 'images/prepaid_revenue_done.jpg',
53 ],
54 'installable': True,
55 'active': False,
56 'application': True,
57}
058
=== added file 'account_cutoff_prepaid/account.py'
--- account_cutoff_prepaid/account.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/account.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,150 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25from openerp.tools.translate import _
26
27
28class account_invoice_line(orm.Model):
29 _inherit = 'account.invoice.line'
30
31 _columns = {
32 'start_date': fields.date('Start Date'),
33 'end_date': fields.date('End Date'),
34 }
35
36 def _check_start_end_dates(self, cr, uid, ids):
37 for invline in self.browse(cr, uid, ids):
38 if invline.start_date and not invline.end_date:
39 raise orm.except_orm(
40 _('Error:'),
41 _("Missing End Date for invoice line with "
42 "Description '%s'.")
43 % (invline.name))
44 if invline.end_date and not invline.start_date:
45 raise orm.except_orm(
46 _('Error:'),
47 _("Missing Start Date for invoice line with "
48 "Description '%s'.")
49 % (invline.name))
50 if invline.end_date and invline.start_date and \
51 invline.start_date > invline.end_date:
52 raise orm.except_orm(
53 _('Error:'),
54 _("Start Date should be before or be the same as "
55 "End Date for invoice line with Description '%s'.")
56 % (invline.name))
57 # Note : we can't check invline.product_id.must_have_dates
58 # have start_date and end_date here, because it would
59 # block automatic invoice generation. So we do the check
60 # upon validation of the invoice (see below the function
61 # action_move_create)
62 return True
63
64 _constraints = [
65 (_check_start_end_dates, "Error msg in raise",
66 ['start_date', 'end_date', 'product_id']),
67 ]
68
69 def move_line_get_item(self, cr, uid, line, context=None):
70 res = super(account_invoice_line, self).move_line_get_item(
71 cr, uid, line, context=context)
72 res['start_date'] = line.start_date
73 res['end_date'] = line.end_date
74 return res
75
76
77class account_move_line(orm.Model):
78 _inherit = "account.move.line"
79
80 _columns = {
81 'start_date': fields.date('Start Date'),
82 'end_date': fields.date('End Date'),
83 }
84
85 def _check_start_end_dates(self, cr, uid, ids):
86 for moveline in self.browse(cr, uid, ids):
87 if moveline.start_date and not moveline.end_date:
88 raise orm.except_orm(
89 _('Error:'),
90 _("Missing End Date for move line with Name '%s'.")
91 % (moveline.name))
92 if moveline.end_date and not moveline.start_date:
93 raise orm.except_orm(
94 _('Error:'),
95 _("Missing Start Date for move line with Name '%s'.")
96 % (moveline.name))
97 if moveline.end_date and moveline.start_date and \
98 moveline.start_date > moveline.end_date:
99 raise orm.except_orm(
100 _('Error:'),
101 _("Start Date should be before End Date for move line "
102 "with Name '%s'.")
103 % (moveline.name))
104 # should we check that it's related to an expense / revenue ?
105 # -> I don't think so
106 return True
107
108 _constraints = [(
109 _check_start_end_dates,
110 "Error msg in raise",
111 ['start_date', 'end_date']
112 )]
113
114
115class account_invoice(orm.Model):
116 _inherit = 'account.invoice'
117
118 def inv_line_characteristic_hashcode(self, invoice, invoice_line):
119 '''Add start and end dates to hashcode used when the option "Group
120 Invoice Lines" is active on the Account Journal'''
121 code = super(account_invoice, self).inv_line_characteristic_hashcode(
122 invoice, invoice_line)
123 hashcode = '%s-%s-%s' % (
124 code, invoice_line.get('start_date', 'False'),
125 invoice_line.get('end_date', 'False'),
126 )
127 return hashcode
128
129 def line_get_convert(self, cr, uid, x, part, date, context=None):
130 res = super(account_invoice, self).line_get_convert(
131 cr, uid, x, part, date, context=context)
132 res['start_date'] = x.get('start_date', False)
133 res['end_date'] = x.get('end_date', False)
134 return res
135
136 def action_move_create(self, cr, uid, ids, context=None):
137 '''Check that products with must_have_dates=True have
138 Start and End Dates'''
139 for invoice in self.browse(cr, uid, ids, context=context):
140 for invline in invoice.invoice_line:
141 if invline.product_id and invline.product_id.must_have_dates:
142 if not invline.start_date or not invline.end_date:
143 raise orm.except_orm(
144 _('Error:'),
145 _("Missing Start Date and End Date for invoice "
146 "line with Product '%s' which has the "
147 "property 'Must Have Start and End Dates'.")
148 % (invline.product_id.name))
149 return super(account_invoice, self).action_move_create(
150 cr, uid, ids, context=context)
0151
=== added file 'account_cutoff_prepaid/account_cutoff.py'
--- account_cutoff_prepaid/account_cutoff.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/account_cutoff.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,253 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25from openerp.tools.translate import _
26from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
27from datetime import datetime
28
29
30class account_cutoff(orm.Model):
31 _inherit = 'account.cutoff'
32
33 _columns = {
34 'source_journal_ids': fields.many2many(
35 'account.journal', id1='cutoff_id', id2='journal_id',
36 string='Source Journals', readonly=True,
37 states={'draft': [('readonly', False)]}),
38 'forecast': fields.boolean(
39 'Forecast',
40 readonly=True, states={'draft': [('readonly', False)]},
41 help="The Forecast mode allows the user to compute "
42 "the prepaid revenue/expense between 2 dates in the future."),
43 'start_date': fields.date('Start Date'),
44 'end_date': fields.date('End Date'),
45 }
46
47 def _get_default_source_journals(self, cr, uid, context=None):
48 if context is None:
49 context = {}
50 journal_obj = self.pool['account.journal']
51 res = []
52 type = context.get('type')
53 mapping = {
54 'prepaid_expense': ('purchase', 'purchase_refund'),
55 'prepaid_revenue': ('sale', 'sale_refund'),
56 }
57 if type in mapping:
58 src_journal_ids = journal_obj.search(
59 cr, uid, [('type', 'in', mapping[type])])
60 if src_journal_ids:
61 res = src_journal_ids
62 return res
63
64 _defaults = {
65 'source_journal_ids': _get_default_source_journals,
66 }
67
68 _sql_constraints = [(
69 'date_type_forecast_company_uniq',
70 'unique(cutoff_date, company_id, type, forecast, start_date, end_date)',
71 'A cut-off of the same type already exists with the same date(s) !'
72 )]
73
74 def _check_start_end_dates(self, cr, uid, ids):
75 for prepaid in self.browse(cr, uid, ids):
76 if prepaid.forecast and prepaid.start_date and prepaid.end_date \
77 and prepaid.start_date > prepaid.end_date:
78 return False
79 return True
80
81 _constraints = [
82 (_check_start_end_dates, "The start date is after the end date!",
83 ['start_date', 'end_date', 'forecast']),
84 ]
85
86 def forecast_onchange(self, cr, uid, ids, forecast, context=None):
87 res = {'value': {}}
88 line_ids = self.pool['account.cutoff.line'].search(
89 cr, uid, [('parent_id', 'in', ids)], context=context)
90 self.pool['account.cutoff.line'].unlink(
91 cr, uid, line_ids, context=context)
92 if forecast:
93 res['value']['cutoff_date'] = False
94 else:
95 res['value']['start_date'] = False
96 res['value']['end_date'] = False
97 return res
98
99 def _prepare_prepaid_lines(
100 self, cr, uid, ids, aml, cur_cutoff, mapping, context=None):
101 start_date = datetime.strptime(
102 aml['start_date'], DEFAULT_SERVER_DATE_FORMAT)
103 end_date = datetime.strptime(
104 aml['end_date'], DEFAULT_SERVER_DATE_FORMAT)
105 # Here, we compute the amount of the cutoff
106 # That's the important part !
107 total_days = (end_date - start_date).days + 1
108 if cur_cutoff['forecast']:
109 out_days = 0
110 forecast_start_date = datetime.strptime(
111 cur_cutoff['start_date'], DEFAULT_SERVER_DATE_FORMAT)
112 forecast_end_date = datetime.strptime(
113 cur_cutoff['end_date'], DEFAULT_SERVER_DATE_FORMAT)
114 if aml['end_date'] > cur_cutoff['end_date']:
115 out_days += (end_date - forecast_end_date).days
116 if aml['start_date'] < cur_cutoff['start_date']:
117 out_days += (forecast_start_date - start_date).days
118 prepaid_days = total_days - out_days
119 else:
120 cutoff_date_str = cur_cutoff['cutoff_date']
121 cutoff_date = datetime.strptime(
122 cutoff_date_str, DEFAULT_SERVER_DATE_FORMAT)
123 if aml['start_date'] > cutoff_date_str:
124 prepaid_days = total_days
125 else:
126 prepaid_days = (end_date - cutoff_date).days
127 if total_days:
128 cutoff_amount = (aml['debit'] - aml['credit'])\
129 * prepaid_days / float(total_days)
130 else:
131 raise orm.except_orm(
132 _('Error:'),
133 "Should never happen. Total days should always be > 0")
134
135 # we use account mapping here
136 if aml['account_id'][0] in mapping:
137 cutoff_account_id = mapping[aml['account_id'][0]]
138 else:
139 cutoff_account_id = aml['account_id'][0]
140
141 res = {
142 'parent_id': ids[0],
143 'move_line_id': aml['id'],
144 'partner_id': aml['partner_id'] and aml['partner_id'][0] or False,
145 'name': aml['name'],
146 'start_date': aml['start_date'],
147 'end_date': aml['end_date'],
148 'account_id': aml['account_id'][0],
149 'cutoff_account_id': cutoff_account_id,
150 'analytic_account_id':
151 aml['analytic_account_id'] and aml['analytic_account_id'][0]
152 or False,
153 'total_days': total_days,
154 'prepaid_days': prepaid_days,
155 'amount': aml['credit'] - aml['debit'],
156 'currency_id': cur_cutoff['company_currency_id'][0],
157 'cutoff_amount': cutoff_amount,
158 }
159 return res
160
161 def get_prepaid_lines(self, cr, uid, ids, context=None):
162 assert len(ids) == 1,\
163 'This function should only be used for a single id at a time'
164 aml_obj = self.pool['account.move.line']
165 line_obj = self.pool['account.cutoff.line']
166 mapping_obj = self.pool['account.cutoff.mapping']
167 cur_cutoff = self.read(
168 cr, uid, ids[0], [
169 'line_ids', 'source_journal_ids', 'cutoff_date', 'company_id',
170 'type', 'company_currency_id', 'forecast', 'start_date',
171 'end_date',
172 ],
173 context=context)
174 src_journal_ids = cur_cutoff['source_journal_ids']
175 if not src_journal_ids:
176 raise orm.except_orm(
177 _('Error:'), _("You should set at least one Source Journal."))
178 cutoff_date_str = cur_cutoff['cutoff_date']
179 # Delete existing lines
180 if cur_cutoff['line_ids']:
181 line_obj.unlink(cr, uid, cur_cutoff['line_ids'], context=context)
182
183 if cur_cutoff['forecast']:
184 domain = [
185 ('start_date', '<=', cur_cutoff['end_date']),
186 ('end_date', '>=', cur_cutoff['start_date']),
187 ('journal_id', 'in', src_journal_ids)
188 ]
189 else:
190 domain = [
191 ('start_date', '!=', False),
192 ('journal_id', 'in', src_journal_ids),
193 ('end_date', '>', cutoff_date_str),
194 ('date', '<=', cutoff_date_str)
195 ]
196
197 # Search for account move lines in the source journals
198 aml_ids = aml_obj.search(cr, uid, domain, context=context)
199 # Create mapping dict
200 mapping = mapping_obj._get_mapping_dict(
201 cr, uid, cur_cutoff['company_id'][0], cur_cutoff['type'],
202 context=context)
203
204 # Loop on selected account move lines to create the cutoff lines
205 for aml in aml_obj.read(
206 cr, uid, aml_ids, [
207 'credit', 'debit', 'start_date', 'end_date', 'account_id',
208 'analytic_account_id', 'partner_id', 'name'
209 ],
210 context=context):
211
212 line_obj.create(
213 cr, uid, self._prepare_prepaid_lines(
214 cr, uid, ids, aml, cur_cutoff, mapping, context=context),
215 context=context)
216 return True
217
218 def _inherit_default_cutoff_account_id(self, cr, uid, context=None):
219 if context is None:
220 context = {}
221 account_id = super(account_cutoff, self).\
222 _inherit_default_cutoff_account_id(cr, uid, context=context)
223 type = context.get('type')
224 company = self.pool['res.users'].browse(
225 cr, uid, uid, context=context).company_id
226 if type == 'prepaid_revenue':
227 account_id = company.default_prepaid_revenue_account_id.id or False
228 elif type == 'prepaid_expense':
229 account_id = company.default_prepaid_expense_account_id.id or False
230 return account_id
231
232
233class account_cutoff_line(orm.Model):
234 _inherit = 'account.cutoff.line'
235
236 _columns = {
237 'move_line_id': fields.many2one(
238 'account.move.line', 'Accout Move Line', readonly=True),
239 'move_date': fields.related(
240 'move_line_id', 'date', type='date',
241 string='Account Move Date', readonly=True),
242 'invoice_id': fields.related(
243 'move_line_id', 'invoice', type='many2one',
244 relation='account.invoice', string='Invoice', readonly=True),
245 'start_date': fields.date('Start Date', readonly=True),
246 'end_date': fields.date('End Date', readonly=True),
247 'total_days': fields.integer('Total Number of Days', readonly=True),
248 'prepaid_days': fields.integer(
249 'Prepaid Days', readonly=True,
250 help="In regular mode, this is the number of days after the "
251 "cut-off date. In forecast mode, this is the number of days "
252 "between the start date and the end date."),
253 }
0254
=== added file 'account_cutoff_prepaid/account_cutoff_view.xml'
--- account_cutoff_prepaid/account_cutoff_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/account_cutoff_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,146 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013-2014 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<!-- Tree view -->
13<record id="account_cutoff_tree" model="ir.ui.view">
14 <field name="name">account.cutoff.prepaid.tree</field>
15 <field name="model">account.cutoff</field>
16 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_tree"/>
17 <field name="arch" type="xml">
18 <field name="cutoff_date" position="after">
19 <field name="forecast" invisible="'prepaid' not in context.get('type', '-')"/>
20 <field name="start_date" invisible="'prepaid' not in context.get('type', '-')"/>
21 <field name="end_date" invisible="'prepaid' not in context.get('type', '-')"/>
22 </field>
23 </field>
24</record>
25
26<!-- Form view -->
27<record id="account_cutoff_form" model="ir.ui.view">
28 <field name="name">account.cutoff.prepaid.form</field>
29 <field name="model">account.cutoff</field>
30 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_form"/>
31 <field name="arch" type="xml">
32 <field name="type" position="after">
33 <field name="forecast"
34 invisible="'prepaid' not in context.get('type', '-')"
35 on_change="forecast_onchange(forecast, context)"/>
36 <field name="start_date"
37 attrs="{'invisible': [('forecast', '=', False)], 'required': [('forecast', '=', True)]}"/>
38 <field name="end_date"
39 attrs="{'invisible': [('forecast', '=', False)], 'required': [('forecast', '=', True)]}"/>
40 </field>
41 <field name="cutoff_date" position="attributes">
42 <attribute name="attrs">{'invisible': [('forecast', '=', True)], 'required': [('forecast', '=', False)]}</attribute>
43 <attribute name="required">0</attribute>
44 </field>
45 <group name="accounting-params" position="attributes">
46 <attribute name="attrs">{'invisible': [('forecast', '=', True)]}</attribute>
47 </group>
48 <field name="cutoff_journal_id" position="attributes">
49 <attribute name="required">0</attribute>
50 <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
51 </field>
52 <field name="cutoff_account_id" position="attributes">
53 <attribute name="required">0</attribute>
54 <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
55 </field>
56 <field name="move_label" position="attributes">
57 <attribute name="required">0</attribute>
58 <attribute name="attrs">{'required': [('forecast', '=', False)]}</attribute>
59 </field>
60 <button name="create_move" position="attributes">
61 <attribute name="attrs">{'invisible': [('forecast', '=', True)]}</attribute>
62 </button>
63 <button name="create_move" position="before">
64 <button name="get_prepaid_lines" string="Re-Generate Lines" type="object" states="draft" invisible="'prepaid' not in context.get('type', '-')"/>
65 </button>
66 <field name="cutoff_date" position="after">
67 <field name="source_journal_ids" invisible="'prepaid' not in context.get('type', '-')"/>
68 </field>
69 </field>
70</record>
71
72<!-- Form view for lines -->
73<record id="account_cutoff_line_form" model="ir.ui.view">
74 <field name="name">account.cutoff.line.prepaid.form</field>
75 <field name="model">account.cutoff.line</field>
76 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_form"/>
77 <field name="arch" type="xml">
78 <field name="parent_id" position="after">
79 <field name="move_line_id" invisible="'prepaid' not in context.get('type', '-')"/>
80 <field name="move_date" invisible="'prepaid' not in context.get('type', '-')" />
81 <field name="invoice_id" invisible="'prepaid' not in context.get('type', '-')" />
82 </field>
83 <field name="name" position="after">
84 <field name="start_date" invisible="'prepaid' not in context.get('type', '-')"/>
85 <field name="end_date" invisible="'prepaid' not in context.get('type', '-')"/>
86 </field>
87 <field name="cutoff_amount" position="before">
88 <field name="total_days" invisible="'prepaid' not in context.get('type', '-')"/>
89 <field name="prepaid_days" invisible="'prepaid' not in context.get('type', '-')"/>
90 </field>
91 </field>
92</record>
93
94<!-- Tree view for lines -->
95<record id="account_cutoff_line_tree" model="ir.ui.view">
96 <field name="name">account.cutoff.line.prepaid.tree</field>
97 <field name="model">account.cutoff.line</field>
98 <field name="inherit_id" ref="account_cutoff_base.account_cutoff_line_tree"/>
99 <field name="arch" type="xml">
100 <field name="parent_id" position="after">
101 <field name="move_line_id" invisible="'prepaid' not in context.get('type', '-')"/>
102 </field>
103 <field name="analytic_account_code" position="after">
104 <field name="start_date" invisible="'prepaid' not in context.get('type', '-')"/>
105 <field name="end_date" invisible="'prepaid' not in context.get('type', '-')"/>
106 <field name="total_days" string="Days Total" invisible="'prepaid' not in context.get('type', '-')"/>
107 <field name="prepaid_days" invisible="'prepaid' not in context.get('type', '-')"/>
108 </field>
109 </field>
110</record>
111
112
113<record id="account_cutoff_prepaid_expense_action" model="ir.actions.act_window">
114 <field name="name">Prepaid Expense</field>
115 <field name="res_model">account.cutoff</field>
116 <field name="view_type">form</field>
117 <field name="view_mode">tree,form</field>
118 <field name="domain">[('type', '=', 'prepaid_expense')]</field>
119 <field name="context">{'type': 'prepaid_expense'}</field>
120</record>
121
122
123<menuitem id="account_cutoff_prepaid_expense_menu"
124 parent="account_cutoff_base.cutoff_menu"
125 action="account_cutoff_prepaid_expense_action"
126 sequence="25"/>
127
128
129<record id="account_cutoff_prepaid_revenue_action" model="ir.actions.act_window">
130 <field name="name">Prepaid Revenue</field>
131 <field name="res_model">account.cutoff</field>
132 <field name="view_type">form</field>
133 <field name="view_mode">tree,form</field>
134 <field name="domain">[('type', '=', 'prepaid_revenue')]</field>
135 <field name="context">{'type': 'prepaid_revenue'}</field>
136</record>
137
138
139<menuitem id="account_cutoff_prepaid_revenue_menu"
140 parent="account_cutoff_base.cutoff_menu"
141 action="account_cutoff_prepaid_revenue_action"
142 sequence="20"/>
143
144
145</data>
146</openerp>
0147
=== added file 'account_cutoff_prepaid/account_invoice_view.xml'
--- account_cutoff_prepaid/account_invoice_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/account_invoice_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,53 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12
13<record id="view_invoice_line_tree" model="ir.ui.view">
14 <field name="name">prepaid.cutoff.invoice_line_tree</field>
15 <field name="model">account.invoice.line</field>
16 <field name="inherit_id" ref="account.view_invoice_line_tree" />
17 <field name="arch" type="xml">
18 <field name="quantity" position="before">
19 <field name="start_date" />
20 <field name="end_date" />
21 </field>
22 </field>
23</record>
24
25
26<record id="invoice_supplier_form" model="ir.ui.view">
27 <field name="name">prepaid.cutoff.invoice_supplier_form</field>
28 <field name="model">account.invoice</field>
29 <field name="inherit_id" ref="account.invoice_supplier_form" />
30 <field name="arch" type="xml">
31 <xpath expr="//field[@name='invoice_line']/tree/field[@name='account_analytic_id']" position="after">
32 <field name="start_date" />
33 <field name="end_date" />
34 </xpath>
35 </field>
36</record>
37
38
39<record id="view_invoice_line_form" model="ir.ui.view">
40 <field name="name">prepaid.cutoff.invoice_line_form</field>
41 <field name="model">account.invoice.line</field>
42 <field name="inherit_id" ref="account.view_invoice_line_form"/>
43 <field name="arch" type="xml">
44 <field name="name" position="after">
45 <field name="start_date" />
46 <field name="end_date" />
47 </field>
48 </field>
49</record>
50
51
52</data>
53</openerp>
054
=== added file 'account_cutoff_prepaid/account_view.xml'
--- account_cutoff_prepaid/account_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/account_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,53 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12
13<record id="view_move_line_form" model="ir.ui.view">
14 <field name="name">prepaid.cutoff.start.end.date.view_move_line_form</field>
15 <field name="model">account.move.line</field>
16 <field name="inherit_id" ref="account.view_move_line_form" />
17 <field name="arch" type="xml">
18 <field name="date_maturity" position="after">
19 <field name="start_date" />
20 <field name="end_date" />
21 </field>
22 </field>
23</record>
24
25
26<record id="view_move_line_form2" model="ir.ui.view">
27 <field name="name">prepaid.cutoff.start.end.date.view_move_line_form2</field>
28 <field name="model">account.move.line</field>
29 <field name="inherit_id" ref="account.view_move_line_form2" />
30 <field name="arch" type="xml">
31 <field name="date_maturity" position="after">
32 <field name="start_date" />
33 <field name="end_date" />
34 </field>
35 </field>
36</record>
37
38
39<record id="view_move_form" model="ir.ui.view">
40 <field name="name">prepaid.cutoff.start.end.date.view_move_form</field>
41 <field name="model">account.move</field>
42 <field name="inherit_id" ref="account.view_move_form" />
43 <field name="arch" type="xml">
44 <field name="date_maturity" position="after">
45 <field name="start_date" />
46 <field name="end_date" />
47 </field>
48 </field>
49</record>
50
51
52</data>
53</openerp>
054
=== added file 'account_cutoff_prepaid/company.py'
--- account_cutoff_prepaid/company.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/company.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,37 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25
26
27class res_company(orm.Model):
28 _inherit = 'res.company'
29
30 _columns = {
31 'default_prepaid_revenue_account_id': fields.many2one(
32 'account.account', 'Default Account for Prepaid Revenue',
33 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
34 'default_prepaid_expense_account_id': fields.many2one(
35 'account.account', 'Default Account for Prepaid Expense',
36 domain=[('type', '<>', 'view'), ('type', '<>', 'closed')]),
37 }
038
=== added file 'account_cutoff_prepaid/company_view.xml'
--- account_cutoff_prepaid/company_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/company_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,27 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12
13<record id="view_company_form" model="ir.ui.view">
14 <field name="name">account.prepaid.cutoff.company.form</field>
15 <field name="model">res.company</field>
16 <field name="inherit_id" ref="account_cutoff_base.view_company_form" />
17 <field name="arch" type="xml">
18 <field name="default_cutoff_journal_id" position="after">
19 <field name="default_prepaid_revenue_account_id" />
20 <field name="default_prepaid_expense_account_id" />
21 </field>
22 </field>
23</record>
24
25
26</data>
27</openerp>
028
=== added directory 'account_cutoff_prepaid/i18n'
=== added file 'account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot'
--- account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/i18n/account_cutoff_prepaid.pot 2014-03-09 00:39:34 +0000
@@ -0,0 +1,289 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * account_cutoff_prepaid
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.1\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-03-09 00:24+0000\n"
10"PO-Revision-Date: 2014-03-09 00:24+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: account_cutoff_prepaid
19#: field:account.cutoff.line,move_line_id:0
20msgid "Accout Move Line"
21msgstr ""
22
23#. module: account_cutoff_prepaid
24#: field:account.cutoff,end_date:0
25#: field:account.cutoff.line,end_date:0
26#: field:account.invoice.line,end_date:0
27#: field:account.move.line,end_date:0
28msgid "End Date"
29msgstr ""
30
31#. module: account_cutoff_prepaid
32#: help:product.template,must_have_dates:0
33msgid "If this option is active, the user will have to enter a Start Date and an End Date on the invoice lines that have this product."
34msgstr ""
35
36#. module: account_cutoff_prepaid
37#: constraint:res.company:0
38msgid "Error! You can not create recursive companies."
39msgstr ""
40
41#. module: account_cutoff_prepaid
42#: field:product.template,must_have_dates:0
43msgid "Must Have Start and End Dates"
44msgstr ""
45
46#. module: account_cutoff_prepaid
47#: field:account.cutoff,forecast:0
48msgid "Forecast"
49msgstr ""
50
51#. module: account_cutoff_prepaid
52#: field:account.cutoff,source_journal_ids:0
53msgid "Source Journals"
54msgstr ""
55
56#. module: account_cutoff_prepaid
57#: field:account.cutoff.line,move_date:0
58msgid "Account Move Date"
59msgstr ""
60
61#. module: account_cutoff_prepaid
62#: code:addons/account_cutoff_prepaid/account.py:95
63#, python-format
64msgid "Missing Start Date for move line with Name '%s'."
65msgstr ""
66
67#. module: account_cutoff_prepaid
68#: code:addons/account_cutoff_prepaid/account.py:47
69#, python-format
70msgid "Missing Start Date for invoice line with Description '%s'."
71msgstr ""
72
73#. module: account_cutoff_prepaid
74#: constraint:account.invoice.line:0
75#: constraint:account.move.line:0
76msgid "Error msg in raise"
77msgstr ""
78
79#. module: account_cutoff_prepaid
80#: constraint:account.move.line:0
81msgid "Company must be the same for its related account and period."
82msgstr ""
83
84#. module: account_cutoff_prepaid
85#: model:ir.actions.act_window,name:account_cutoff_prepaid.account_cutoff_prepaid_expense_action
86#: model:ir.ui.menu,name:account_cutoff_prepaid.account_cutoff_prepaid_expense_menu
87msgid "Prepaid Expense"
88msgstr ""
89
90#. module: account_cutoff_prepaid
91#: model:ir.actions.act_window,name:account_cutoff_prepaid.account_cutoff_prepaid_revenue_action
92#: model:ir.ui.menu,name:account_cutoff_prepaid.account_cutoff_prepaid_revenue_menu
93msgid "Prepaid Revenue"
94msgstr ""
95
96#. module: account_cutoff_prepaid
97#: code:addons/account_cutoff_prepaid/account.py:101
98#, python-format
99msgid "Start Date should be before End Date for move line with Name '%s'."
100msgstr ""
101
102#. module: account_cutoff_prepaid
103#: model:ir.model,name:account_cutoff_prepaid.model_account_move_line
104msgid "Journal Items"
105msgstr ""
106
107#. module: account_cutoff_prepaid
108#: view:account.cutoff:0
109msgid "Re-Generate Lines"
110msgstr ""
111
112#. module: account_cutoff_prepaid
113#: constraint:account.move.line:0
114msgid "You can not create journal items on an account of type view."
115msgstr ""
116
117#. module: account_cutoff_prepaid
118#: help:account.cutoff,forecast:0
119msgid "The Forecast mode allows the user to compute the prepaid revenue/expense between 2 dates in the future."
120msgstr ""
121
122#. module: account_cutoff_prepaid
123#: code:addons/account_cutoff_prepaid/account.py:40
124#: code:addons/account_cutoff_prepaid/account.py:46
125#: code:addons/account_cutoff_prepaid/account.py:53
126#: code:addons/account_cutoff_prepaid/account.py:89
127#: code:addons/account_cutoff_prepaid/account.py:94
128#: code:addons/account_cutoff_prepaid/account.py:100
129#: code:addons/account_cutoff_prepaid/account.py:144
130#: code:addons/account_cutoff_prepaid/account_cutoff.py:132
131#: code:addons/account_cutoff_prepaid/account_cutoff.py:177
132#, python-format
133msgid "Error:"
134msgstr ""
135
136#. module: account_cutoff_prepaid
137#: field:res.company,default_prepaid_revenue_account_id:0
138msgid "Default Account for Prepaid Revenue"
139msgstr ""
140
141#. module: account_cutoff_prepaid
142#: sql_constraint:account.cutoff:0
143msgid "A cutoff of the same type already exists with this cut-off date !"
144msgstr ""
145
146#. module: account_cutoff_prepaid
147#: model:ir.model,name:account_cutoff_prepaid.model_account_cutoff_line
148msgid "Account Cut-off Line"
149msgstr ""
150
151#. module: account_cutoff_prepaid
152#: sql_constraint:res.company:0
153msgid "The company name must be unique !"
154msgstr ""
155
156#. module: account_cutoff_prepaid
157#: model:product.template,name:account_cutoff_prepaid.product_insurance_contrat_product_template
158msgid "Car Insurance"
159msgstr ""
160
161#. module: account_cutoff_prepaid
162#: constraint:product.template:0
163msgid "Error: The default UOM and the purchase UOM must be in the same category."
164msgstr ""
165
166#. module: account_cutoff_prepaid
167#: model:ir.model,name:account_cutoff_prepaid.model_account_cutoff
168msgid "Account Cut-off"
169msgstr ""
170
171#. module: account_cutoff_prepaid
172#: model:ir.model,name:account_cutoff_prepaid.model_res_company
173msgid "Companies"
174msgstr ""
175
176#. module: account_cutoff_prepaid
177#: constraint:account.move.line:0
178msgid "You can not create journal items on closed account."
179msgstr ""
180
181#. module: account_cutoff_prepaid
182#: view:account.cutoff.line:0
183msgid "Days Total"
184msgstr ""
185
186#. module: account_cutoff_prepaid
187#: code:addons/account_cutoff_prepaid/account.py:54
188#, python-format
189msgid "Start Date should be before or be the same as End Date for invoice line with Description '%s'."
190msgstr ""
191
192#. module: account_cutoff_prepaid
193#: code:addons/account_cutoff_prepaid/account.py:145
194#, python-format
195msgid "Missing Start Date and End Date for invoice line with Product '%s' which has the property 'Must Have Start and End Dates'."
196msgstr ""
197
198#. module: account_cutoff_prepaid
199#: code:addons/account_cutoff_prepaid/account_cutoff.py:177
200#, python-format
201msgid "You should set at least one Source Journal."
202msgstr ""
203
204#. module: account_cutoff_prepaid
205#: code:addons/account_cutoff_prepaid/account.py:41
206#, python-format
207msgid "Missing End Date for invoice line with Description '%s'."
208msgstr ""
209
210#. module: account_cutoff_prepaid
211#: constraint:account.cutoff:0
212msgid "The start date is after the end date!"
213msgstr ""
214
215#. module: account_cutoff_prepaid
216#: sql_constraint:account.invoice:0
217msgid "Invoice Number must be unique per Company!"
218msgstr ""
219
220#. module: account_cutoff_prepaid
221#: code:addons/account_cutoff_prepaid/account.py:90
222#, python-format
223msgid "Missing End Date for move line with Name '%s'."
224msgstr ""
225
226#. module: account_cutoff_prepaid
227#: help:account.cutoff.line,prepaid_days:0
228msgid "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."
229msgstr ""
230
231#. module: account_cutoff_prepaid
232#: model:ir.model,name:account_cutoff_prepaid.model_product_template
233msgid "Product Template"
234msgstr ""
235
236#. module: account_cutoff_prepaid
237#: model:ir.model,name:account_cutoff_prepaid.model_account_invoice_line
238msgid "Invoice Line"
239msgstr ""
240
241#. module: account_cutoff_prepaid
242#: constraint:account.move.line:0
243msgid "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."
244msgstr ""
245
246#. module: account_cutoff_prepaid
247#: constraint:account.move.line:0
248msgid "The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal."
249msgstr ""
250
251#. module: account_cutoff_prepaid
252#: field:account.cutoff.line,total_days:0
253msgid "Total Number of Days"
254msgstr ""
255
256#. module: account_cutoff_prepaid
257#: field:res.company,default_prepaid_expense_account_id:0
258msgid "Default Account for Prepaid Expense"
259msgstr ""
260
261#. module: account_cutoff_prepaid
262#: field:account.cutoff.line,invoice_id:0
263#: model:ir.model,name:account_cutoff_prepaid.model_account_invoice
264msgid "Invoice"
265msgstr ""
266
267#. module: account_cutoff_prepaid
268#: sql_constraint:account.cutoff:0
269msgid "A cut-off of the same type already exists with the same date(s) !"
270msgstr ""
271
272#. module: account_cutoff_prepaid
273#: sql_constraint:account.move.line:0
274msgid "Wrong credit or debit value in accounting entry !"
275msgstr ""
276
277#. module: account_cutoff_prepaid
278#: field:account.cutoff,start_date:0
279#: field:account.cutoff.line,start_date:0
280#: field:account.invoice.line,start_date:0
281#: field:account.move.line,start_date:0
282msgid "Start Date"
283msgstr ""
284
285#. module: account_cutoff_prepaid
286#: field:account.cutoff.line,prepaid_days:0
287msgid "Prepaid Days"
288msgstr ""
289
0290
=== added directory 'account_cutoff_prepaid/images'
=== added file 'account_cutoff_prepaid/images/prepaid_revenue_done.jpg'
1Binary files account_cutoff_prepaid/images/prepaid_revenue_done.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_done.jpg 2014-03-09 00:39:34 +0000 differ291Binary files account_cutoff_prepaid/images/prepaid_revenue_done.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_done.jpg 2014-03-09 00:39:34 +0000 differ
=== added file 'account_cutoff_prepaid/images/prepaid_revenue_draft.jpg'
2Binary files account_cutoff_prepaid/images/prepaid_revenue_draft.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_draft.jpg 2014-03-09 00:39:34 +0000 differ292Binary files account_cutoff_prepaid/images/prepaid_revenue_draft.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_draft.jpg 2014-03-09 00:39:34 +0000 differ
=== added file 'account_cutoff_prepaid/images/prepaid_revenue_journal_entry.jpg'
3Binary files account_cutoff_prepaid/images/prepaid_revenue_journal_entry.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_journal_entry.jpg 2014-03-09 00:39:34 +0000 differ293Binary files account_cutoff_prepaid/images/prepaid_revenue_journal_entry.jpg 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/images/prepaid_revenue_journal_entry.jpg 2014-03-09 00:39:34 +0000 differ
=== added directory 'account_cutoff_prepaid/migrations'
=== added directory 'account_cutoff_prepaid/migrations/6.1.0.2'
=== added file 'account_cutoff_prepaid/migrations/6.1.0.2/pre-migration.py'
--- account_cutoff_prepaid/migrations/6.1.0.2/pre-migration.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/migrations/6.1.0.2/pre-migration.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,29 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Copyright (C) 2014 Akretion (http://www.akretion.com/)
5# @author: Alexis de Lattre <alexis.delattre@akretion.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22
23def migrate(cr, version):
24 if not version:
25 return
26
27 cr.execute(
28 'ALTER TABLE "account_cutoff_line" RENAME "after_cutoff_days" '
29 'TO "prepaid_days"')
030
=== added file 'account_cutoff_prepaid/product.py'
--- account_cutoff_prepaid/product.py 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/product.py 2014-03-09 00:39:34 +0000
@@ -0,0 +1,36 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Account Cut-off Prepaid module for OpenERP
5# Copyright (C) 2013 Akretion (http://www.akretion.com)
6# @author Alexis de Lattre <alexis.delattre@akretion.com>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21##############################################################################
22
23
24from openerp.osv import orm, fields
25
26
27class product_template(orm.Model):
28 _inherit = 'product.template'
29
30 _columns = {
31 'must_have_dates': fields.boolean(
32 'Must Have Start and End Dates',
33 help="If this option is active, the user will have to enter "
34 "a Start Date and an End Date on the invoice lines that have "
35 "this product."),
36 }
037
=== added file 'account_cutoff_prepaid/product_demo.xml'
--- account_cutoff_prepaid/product_demo.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/product_demo.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,25 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<record id="product_insurance_contrat" model="product.product">
13 <field name="name">Car Insurance</field>
14 <field name="default_code">CARINSUR</field>
15 <field name="type">service</field>
16 <field name="categ_id" ref="product.product_category_services0"/>
17 <field name="must_have_dates" eval="True" />
18 <field name="sale_ok" eval="True" />
19 <field name="purchase_ok" eval="True" />
20 <field name="list_price" eval="1200.0"/>
21 <field name="standard_price" eval="600.0"/>
22</record>
23
24</data>
25</openerp>
026
=== added file 'account_cutoff_prepaid/product_view.xml'
--- account_cutoff_prepaid/product_view.xml 1970-01-01 00:00:00 +0000
+++ account_cutoff_prepaid/product_view.xml 2014-03-09 00:39:34 +0000
@@ -0,0 +1,37 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4 Copyright (C) 2013 Akretion (http://www.akretion.com/)
5 @author Alexis de Lattre <alexis.delattre@akretion.com>
6 The licence is in the file __openerp__.py
7-->
8
9<openerp>
10<data>
11
12<record id="product_normal_form_view" model="ir.ui.view">
13 <field name="name">add.must.have.dates.on.product.product.form</field>
14 <field name="model">product.product</field>
15 <field name="inherit_id" ref="account.product_normal_form_view" />
16 <field name="arch" type="xml">
17 <field name="purchase_ok" position="after">
18 <field name="must_have_dates" />
19 </field>
20 </field>
21</record>
22
23
24<record id="product_template_form_view" model="ir.ui.view">
25 <field name="name">add.must.have.dates.on.product.template.form</field>
26 <field name="model">product.template</field>
27 <field name="inherit_id" ref="account.product_template_form_view" />
28 <field name="arch" type="xml">
29 <field name="purchase_ok" position="after">
30 <field name="must_have_dates" />
31 </field>
32 </field>
33</record>
34
35
36</data>
37</openerp>
038
=== added directory 'account_cutoff_prepaid/static'
=== added directory 'account_cutoff_prepaid/static/src'
=== added directory 'account_cutoff_prepaid/static/src/img'
=== added file 'account_cutoff_prepaid/static/src/img/icon.png'
1Binary files account_cutoff_prepaid/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/static/src/img/icon.png 2014-03-09 00:39:34 +0000 differ39Binary files account_cutoff_prepaid/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and account_cutoff_prepaid/static/src/img/icon.png 2014-03-09 00:39:34 +0000 differ

Subscribers

People subscribed via source and target branches