~unifield-team/unifield-wm/us-826

2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
1
# -*- coding: utf-8 -*-
2
##############################################################################
3
#
4
#    OpenERP, Open Source Management Solution
2.1.7 by jf
UF-133 [FIX] Copyright
5
#    Copyright (C) 2011 MSF, TeMPO Consulting.
2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
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
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
22
import datetime
93.3.2 by Matthieu Dietrich
UF-160: [FIX] default activation date is now 3 months ago
23
from dateutil.relativedelta import relativedelta
2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
24
from osv import fields, osv
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
25
from tools.translate import _
350.8.3 by Olivier DOSSMANN
UF-359 [IMP] Give a better method to change xml attribute in fields_view_get
26
from lxml import etree
827.8.64 by Olivier DOSSMANN
UF-1106 [FIX] FP search compatibility with selected destination in analytic distribution wizard
27
from tools.misc import flatten
1116.1.1 by jf
UF-1291: on destination (analytic.account), un-lazy m2m destination_ids + check to not delete a default destination
28
from destination_tools import many2many_sorted, many2many_notlazy
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
29
import decimal_precision as dp
827.10.3 by jf
UF-1106: FP: order tuple by account.code, FIX: summary dest by accounts
30
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
31
class analytic_account(osv.osv):
232.7.1 by Matthieu Dietrich
UF-364: retrieve parent merge
32
    _name = "account.analytic.account"
2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
33
    _inherit = "account.analytic.account"
601.1.1 by Olivier DOSSMANN
UF-814 [ADD] Change Analytic Account display
34
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
35
    def _get_active(self, cr, uid, ids, field_name, args, context=None):
36
        '''
1380.3.12 by Olivier DOSSMANN
UF-1678 [ADD] Check on analytic distribution wizard if posting/document date are compatible with Cost centers, destination and funding pool.
37
        If date out of date_start/date of given analytic account, then account is inactive.
38
        The comparison could be done via a date given in context.
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
39
        '''
40
        res = {}
1380.3.12 by Olivier DOSSMANN
UF-1678 [ADD] Check on analytic distribution wizard if posting/document date are compatible with Cost centers, destination and funding pool.
41
        cmp_date = datetime.date.today().strftime('%Y-%m-%d')
42
        if context.get('date', False):
43
            cmp_date = context.get('date')
44
        for a in self.browse(cr, uid, ids):
45
            res[a.id] = True
46
            if a.date_start > cmp_date:
47
                res[a.id] = False
1380.3.24 by Olivier DOSSMANN
UF-1678 [FIX] Today not shown in inactive analytic accounts
48
            if a.date and a.date <= cmp_date:
1380.3.12 by Olivier DOSSMANN
UF-1678 [ADD] Check on analytic distribution wizard if posting/document date are compatible with Cost centers, destination and funding pool.
49
                res[a.id] = False
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
50
        return res
51
52
    def _search_filter_active(self, cr, uid, ids, name, args, context=None):
53
        """
54
        UTP-410: Add the search on active/inactive CC
55
        """
56
        arg = []
1380.3.9 by Olivier DOSSMANN
UF-1678 [ADD] Filtering inactive analytic account on name_search for analytic distribution wizard
57
        cmp_date = datetime.date.today().strftime('%Y-%m-%d')
58
        if context.get('date', False):
59
            cmp_date = context.get('date')
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
60
        for x in args:
61
            if x[0] == 'filter_active' and x[2] == True:
1380.3.9 by Olivier DOSSMANN
UF-1678 [ADD] Filtering inactive analytic account on name_search for analytic distribution wizard
62
                arg.append(('date_start', '<=', cmp_date))
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
63
                arg.append('|')
1380.3.9 by Olivier DOSSMANN
UF-1678 [ADD] Filtering inactive analytic account on name_search for analytic distribution wizard
64
                arg.append(('date', '>', cmp_date))
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
65
                arg.append(('date', '=', False))
1380.3.13 by Olivier DOSSMANN
UF-1678 [ADD] Add a new "Inactive" filter button to show only inactive accounts.
66
            elif x[0] == 'filter_active' and x[2] == False:
67
                arg.append('|')
68
                arg.append(('date_start', '>', cmp_date))
1380.3.24 by Olivier DOSSMANN
UF-1678 [FIX] Today not shown in inactive analytic accounts
69
                arg.append(('date', '<=', cmp_date))
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
70
        return arg
71
1390.4.4 by Olivier DOSSMANN
UTP-423 [FIX] Problem with FP display: could not display analytic item that have an FP on a soft/hard closed contract. So change behaviour.
72
    def _search_closed_by_a_fp(self, cr, uid, ids, name, args, context=None):
73
        """
74
        UTP-423: Do not display analytic accounts linked to a soft/hard closed contract.
75
        """
76
        res = [('id', 'not in', [])]
77
        if args and args[0] and len(args[0]) == 3:
78
            if args[0][1] != '=':
79
                raise osv.except_osv(_('Error'), _('Operator not supported yet!'))
80
            # Search all fp_ids from soft_closed contract
81
            sql="""SELECT a.id
82
                FROM account_analytic_account a, financing_contract_contract fcc, financing_contract_funding_pool_line fcfl
83
                WHERE fcfl.contract_id = fcc.id
84
                AND fcfl.funding_pool_id = a.id
85
                AND fcc.state in ('soft_closed', 'hard_closed');"""
86
            cr.execute(sql)
87
            sql_res = cr.fetchall()
88
            if sql_res:
89
                aa_ids = self.is_blocked_by_a_contract(cr, uid, [x and x[0] for x in sql_res])
90
                if aa_ids:
91
                    if isinstance(aa_ids, (int, long)):
92
                        aa_ids = [aa_ids]
93
                    res = [('id', 'not in', aa_ids)]
94
        return res
95
1586.1.1 by jf
UF-1873 [FIX] Intermission PO/FO flow broken
96
    def _get_fake(self, cr, uid, ids, *a, **b):
97
        return {}.fromkeys(ids, False)
98
1793.2.22 by Olivier DOSSMANN
UF-1718 [FIX] Compute in output currency if "output_currency_id" is in context for Balance by analytic/general accounts.
99
    def _compute_level_tree(self, cr, uid, ids, child_ids, res, field_names, context=None):
100
        """
101
        Change balance value using output_currency_id currency in context (if exists)
102
        """
103
        # some checks
104
        if not context:
105
            context = {}
106
        res = super(analytic_account, self)._compute_level_tree(cr, uid, ids, child_ids, res, field_names, context=context)
107
        company_currency = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
108
        if context.get('output_currency_id', False):
109
            for res_id in res:
110
                if res[res_id].get('balance', False):
111
                    new_balance = self.pool.get('res.currency').compute(cr, uid, context.get('output_currency_id'), company_currency, res[res_id].get('balance'), context=context)
112
                    res[res_id].update({'balance': new_balance,})
113
        return res
114
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
115
    # @@@override analytic.analytic
116
    def _debit_credit_bal_qtty(self, cr, uid, ids, name, arg, context=None):
117
        res = {}
118
        if context is None:
119
            context = {}
120
        # use different criteria regarding analytic account category!
121
        account_type = {}
122
        for line in self.browse(cr, uid, ids, context=context):
123
            res[line.id] = {}
124
            for field in name:
125
                res[line.id].update({field: False})
126
            if line.category:
127
                if not line.category in account_type:
128
                    account_type[line.category] = []
129
                account_type[line.category].append(line.id)
130
        for cat in account_type:
131
            default_field = 'account_id'
132
            if cat == 'DEST':
133
                default_field = 'destination_id'
134
            elif cat == 'OC':
135
                default_field = 'cost_center_id'
136
            child_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', account_type[cat])]))
137
            for i in child_ids:
138
                res[i] =  {}
139
                for n in name:
140
                    res[i][n] = 0.0
141
142
            #if not child_ids:
143
            #    return res
144
145
            where_date = ''
146
            where_clause_args = [tuple(child_ids)]
147
            if context.get('from_date', False):
148
                where_date += " AND l.date >= %s"
149
                where_clause_args  += [context['from_date']]
150
            if context.get('to_date', False):
151
                where_date += " AND l.date <= %s"
152
                where_clause_args += [context['to_date']]
1793.2.48 by Olivier DOSSMANN
UF-1712 [FIX] Filtering on instance_ids field for "Balance by analytic accounts" wizard
153
            if context.get('instance_ids', False):
154
                instance_ids = context.get('instance_ids')
155
                if isinstance(instance_ids, (int, long)):
156
                    instance_ids = [instance_ids]
157
                if len(instance_ids) == 1:
158
                    where_date += " AND l.instance_id = %s"
159
                else:
160
                    where_date += " AND l.instance_id in %s"
161
                where_clause_args += tuple(instance_ids)
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
162
            # UF-1713: Add currency arg
163
            if context.get('currency_id', False):
164
                where_date += " AND l.currency_id = %s"
165
                where_clause_args += [context['currency_id']]
166
            cr.execute("""
167
                  SELECT a.id,
168
                         sum(
169
                             CASE WHEN l.amount > 0
170
                             THEN l.amount
171
                             ELSE 0.0
172
                             END
173
                              ) as debit,
174
                         sum(
175
                             CASE WHEN l.amount < 0
176
                             THEN -l.amount
177
                             ELSE 0.0
178
                             END
179
                              ) as credit,
180
                         COALESCE(SUM(l.amount),0) AS balance,
181
                         COALESCE(SUM(l.unit_amount),0) AS quantity
182
                  FROM account_analytic_account a
183
                      LEFT JOIN account_analytic_line l ON (a.id = l.""" + default_field  + """)
184
                  WHERE a.id IN %s
185
                  """ + where_date + """
186
                  GROUP BY a.id""", where_clause_args)
187
            for ac_id, debit, credit, balance, quantity in cr.fetchall():
188
                res[ac_id] = {'debit': debit, 'credit': credit, 'balance': balance, 'quantity': quantity}
1793.2.23 by Olivier DOSSMANN
UF-1718 [FIX] Problem when using a currency in the report that breaks it
189
            tmp_res = self._compute_level_tree(cr, uid, ids, child_ids, res, name, context)
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
190
            res.update(tmp_res)
191
        return res
192
2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
193
    _columns = {
1424.1.4 by jf
UF-1662 translate=1 added
194
        'name': fields.char('Name', size=128, required=True, translate=1),
675.3.2 by duy.vo at msf
[IMP] UF-887: Rename some attributes of Analytic Account
195
        'code': fields.char('Code', size=24),
196
        'type': fields.selection([('view','View'), ('normal','Normal')], 'Type', help='If you select the View Type, it means you won\'t allow to create journal entries using that account.'),
154.4.1 by Matthieu Dietrich
UF-287: [IMP] start date/end date are now active date/inactive date
197
        'date_start': fields.date('Active from', required=True),
198
        'date': fields.date('Inactive from', select=True),
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
199
        'category': fields.selection([('OC','Cost Center'),
200
            ('FUNDING','Funding Pool'),
201
            ('FREE1','Free 1'),
827.8.1 by Olivier DOSSMANN
UF-1106 [ADD] Add new analytic account type : DESTINATION
202
            ('FREE2','Free 2'),
203
            ('DEST', 'Destination')], 'Category', select=1),
827.8.62 by Olivier DOSSMANN
UF-1106 [ADD] Domain on cost_center for analytic account configuration
204
        'cost_center_ids': fields.many2many('account.analytic.account', 'funding_pool_associated_cost_centers', 'funding_pool_id', 'cost_center_id', string='Cost Centers', domain="[('type', '!=', 'view'), ('category', '=', 'OC')]"),
584.14.1 by Olivier DOSSMANN
UF-806 [ADD] Default analytic account attribute for FX gain/loss
205
        'for_fx_gain_loss': fields.boolean(string="For FX gain/loss", help="Is this account for default FX gain/loss?"),
1116.1.1 by jf
UF-1291: on destination (analytic.account), un-lazy m2m destination_ids + check to not delete a default destination
206
        'destination_ids': many2many_notlazy('account.account', 'account_destination_link', 'destination_id', 'account_id', 'Accounts'),
827.10.3 by jf
UF-1106: FP: order tuple by account.code, FIX: summary dest by accounts
207
        'tuple_destination_account_ids': many2many_sorted('account.destination.link', 'funding_pool_associated_destinations', 'funding_pool_id', 'tuple_id', "Account/Destination"),
827.9.10 by jf
FP: Account/destination Summary tab
208
        'tuple_destination_summary': fields.one2many('account.destination.summary', 'funding_pool_id', 'Destination by accounts'),
1367.3.1 by duy.vo at msf
UTP-410: Modified the active search on account analytic tree
209
        'filter_active': fields.function(_get_active, fnct_search=_search_filter_active, type="boolean", method=True, store=False, string="Show only active analytic accounts",),
1390.4.4 by Olivier DOSSMANN
UTP-423 [FIX] Problem with FP display: could not display analytic item that have an FP on a soft/hard closed contract. So change behaviour.
210
        'hide_closed_fp': fields.function(_get_active, fnct_search=_search_closed_by_a_fp, type="boolean", method=True, store=False, string="Linked to a soft/hard closed contract?"),
1937 by jf
UF-1714 [IMP] General Ledger (modifications on existing feature)
211
        'intermission_restricted': fields.function(_get_fake, type="boolean", method=True, store=False, string="Domain to restrict intermission cc"),
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
212
        'balance': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Balance', digits_compute=dp.get_precision('Account'), multi='debit_credit_bal_qtty'),
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
213
    }
601.1.2 by Olivier DOSSMANN
UF-814 [MERGE] lp:~unifield-team/unifield-wm/trunk
214
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
215
    _defaults ={
584.14.1 by Olivier DOSSMANN
UF-806 [ADD] Default analytic account attribute for FX gain/loss
216
        'date_start': lambda *a: (datetime.datetime.today() + relativedelta(months=-3)).strftime('%Y-%m-%d'),
217
        'for_fx_gain_loss': lambda *a: False,
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
218
    }
1390.4.1 by Olivier DOSSMANN
UTP-423 [FIX] Do not permit user to select an analytic FP account if it is used in a soft/hard closed contract.
219
707 by jf
[FIX] Default values
220
    def _check_unicity(self, cr, uid, ids, context=None):
556.5.1 by Matthieu Dietrich
UF-533: [IMP] re-added analytic account constraint
221
        if not context:
707 by jf
[FIX] Default values
222
            context = {}
556.5.1 by Matthieu Dietrich
UF-533: [IMP] re-added analytic account constraint
223
        for account in self.browse(cr, uid, ids, context=context):
1385.10.5 by jf
UF-1662 Import data
224
            bad_ids = self.search(cr, uid, [('category', '=', account.category),('|'),('name', '=ilike', account.name),('code', '=ilike', account.code)])
556.5.1 by Matthieu Dietrich
UF-533: [IMP] re-added analytic account constraint
225
            if len(bad_ids) and len(bad_ids) > 1:
226
                return False
227
        return True
363.10.4 by Matthieu Dietrich
UF-533: case-insensitive unicity constraints
228
707 by jf
[FIX] Default values
229
    def _check_gain_loss_account_unicity(self, cr, uid, ids, context=None):
584.14.3 by Olivier DOSSMANN
UF-806 [ADD] Check account type and account category for fx gain/loss account: Should be 'normal' type and 'OC' category (Cost Center)
230
        """
231
        Check that no more account is "for_fx_gain_loss" available.
232
        """
584.14.2 by Olivier DOSSMANN
UF-806 [ADD] Add constraint for fx gain/loss account
233
        if not context:
234
            context = {}
235
        search_ids = self.search(cr, uid, [('for_fx_gain_loss', '=', True)])
236
        if search_ids and len(search_ids) > 1:
237
            return False
238
        return True
239
707 by jf
[FIX] Default values
240
    def _check_gain_loss_account_type(self, cr, uid, ids, context=None):
584.14.3 by Olivier DOSSMANN
UF-806 [ADD] Check account type and account category for fx gain/loss account: Should be 'normal' type and 'OC' category (Cost Center)
241
        """
242
        Check account type for fx_gain_loss_account: should be Normal type and Cost Center category
243
        """
244
        if not context:
245
            context = {}
246
        for account in self.browse(cr, uid, ids, context=context):
584.14.6 by Olivier DOSSMANN
UF-806 [FIX] Some bug on account type for analytic account
247
            if account.for_fx_gain_loss == True and (account.type != 'normal' or account.category != 'OC'):
584.14.3 by Olivier DOSSMANN
UF-806 [ADD] Check account type and account category for fx gain/loss account: Should be 'normal' type and 'OC' category (Cost Center)
248
                return False
249
        return True
1116.1.1 by jf
UF-1291: on destination (analytic.account), un-lazy m2m destination_ids + check to not delete a default destination
250
    
251
    def _check_default_destination(self, cr, uid, ids, context=None):
252
        if isinstance(ids, (int, long)):
253
            ids = [ids]
254
        if not ids:
255
            return True
256
        cr.execute('''select a.code, a.name, d.name from
257
            '''+self._table+''' d
258
            left join account_account a on a.default_destination_id = d.id
259
            left join account_destination_link l on l.destination_id = d.id and l.account_id = a.id
260
            where a.default_destination_id is not null and l.destination_id is null and d.id in %s ''', (tuple(ids),)
261
        )
262
        error = []
263
        for x in cr.fetchall():
1116.1.2 by jf
UF-1291 raise message
264
            error.append(_('"%s" is the default destination for the G/L account "%s %s", you can\'t remove it.')%(x[2], x[0], x[1]))
1116.1.1 by jf
UF-1291: on destination (analytic.account), un-lazy m2m destination_ids + check to not delete a default destination
265
        if error:
266
            raise osv.except_osv(_('Warning !'), "\n".join(error))
267
        return True
584.14.3 by Olivier DOSSMANN
UF-806 [ADD] Check account type and account category for fx gain/loss account: Should be 'normal' type and 'OC' category (Cost Center)
268
556.5.1 by Matthieu Dietrich
UF-533: [IMP] re-added analytic account constraint
269
    _constraints = [
270
        (_check_unicity, 'You cannot have the same code or name between analytic accounts in the same category!', ['code', 'name', 'category']),
584.14.3 by Olivier DOSSMANN
UF-806 [ADD] Check account type and account category for fx gain/loss account: Should be 'normal' type and 'OC' category (Cost Center)
271
        (_check_gain_loss_account_unicity, 'You can only have one account used for FX gain/loss!', ['for_fx_gain_loss']),
272
        (_check_gain_loss_account_type, 'You have to use a Normal account type and Cost Center category for FX gain/loss!', ['for_fx_gain_loss']),
1116.1.1 by jf
UF-1291: on destination (analytic.account), un-lazy m2m destination_ids + check to not delete a default destination
273
        (_check_default_destination, "You can't delete an account which has this destination as default", []),
556.5.1 by Matthieu Dietrich
UF-533: [IMP] re-added analytic account constraint
274
    ]
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
275
707 by jf
[FIX] Default values
276
    def copy(self, cr, uid, id, default=None, context=None, done_list=[], local=False):
363.10.4 by Matthieu Dietrich
UF-533: case-insensitive unicity constraints
277
        account = self.browse(cr, uid, id, context=context)
278
        if not default:
279
            default = {}
280
        default = default.copy()
281
        default['code'] = (account['code'] or '') + '(copy)'
282
        default['name'] = (account['name'] or '') + '(copy)'
1306.1.2 by jf
UF-1601 UTP-335 : duplicate fp: don't duplicate computed "Destinations by accounts" + set the code
283
        default['tuple_destination_summary'] = []
284
        # code is deleted in copy method in addons
285
        new_id = super(analytic_account, self).copy(cr, uid, id, default, context=context)
286
        self.write(cr, uid, new_id, {'code': '%s(copy)' % (account['code'] or '')})
287
        return new_id
363.10.4 by Matthieu Dietrich
UF-533: case-insensitive unicity constraints
288
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
289
    def set_funding_pool_parent(self, cr, uid, vals):
363.10.3 by Matthieu Dietrich
Fix for installation
290
        if 'category' in vals and \
291
           'code' in vals and \
292
            vals['category'] == 'FUNDING' and \
293
            vals['code'] != 'FUNDING':
294
            # for all accounts except the parent one
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
295
            funding_pool_parent = self.search(cr, uid, [('category', '=', 'FUNDING'), ('parent_id', '=', False)])[0]
296
            vals['parent_id'] = funding_pool_parent
584.14.2 by Olivier DOSSMANN
UF-806 [ADD] Add constraint for fx gain/loss account
297
1748 by jf
UF-2079 [FIX] context={} in method def
298
    def _check_date(self, vals, context=None):
299
        if context is None:
300
            context = {}
154.4.1 by Matthieu Dietrich
UF-287: [IMP] start date/end date are now active date/inactive date
301
        if 'date' in vals and vals['date'] is not False:
1728.4.1 by Matthieu Dietrich
UF-2079: [FIX] removed inactivation date constraint if account created from sync
302
            if vals['date'] <= datetime.date.today().strftime('%Y-%m-%d') and not context.get('sync_update_execution', False):
1316.4.1 by Olivier DOSSMANN
UF-1583 [DEL] Non-used libraries and variables
303
                # validate the date (must be > today)
304
                raise osv.except_osv(_('Warning !'), _('You cannot set an inactivity date lower than tomorrow!'))
154.4.1 by Matthieu Dietrich
UF-287: [IMP] start date/end date are now active date/inactive date
305
            elif 'date_start' in vals and not vals['date_start'] < vals['date']:
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
306
                # validate that activation date 
307
                raise osv.except_osv(_('Warning !'), _('Activation date must be lower than inactivation date!'))
584.14.2 by Olivier DOSSMANN
UF-806 [ADD] Add constraint for fx gain/loss account
308
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
309
    def create(self, cr, uid, vals, context=None):
584.14.2 by Olivier DOSSMANN
UF-806 [ADD] Add constraint for fx gain/loss account
310
        """
311
        Some verifications before analytic account creation
312
        """
1728.4.1 by Matthieu Dietrich
UF-2079: [FIX] removed inactivation date constraint if account created from sync
313
        self._check_date(vals, context=context)
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
314
        self.set_funding_pool_parent(cr, uid, vals)
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
315
        return super(analytic_account, self).create(cr, uid, vals, context=context)
601.1.2 by Olivier DOSSMANN
UF-814 [MERGE] lp:~unifield-team/unifield-wm/trunk
316
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
317
    def write(self, cr, uid, ids, vals, context=None):
584.14.2 by Olivier DOSSMANN
UF-806 [ADD] Add constraint for fx gain/loss account
318
        """
319
        Some verifications before analytic account write
320
        """
1728.4.1 by Matthieu Dietrich
UF-2079: [FIX] removed inactivation date constraint if account created from sync
321
        self._check_date(vals, context=context)
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
322
        self.set_funding_pool_parent(cr, uid, vals)
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
323
        return super(analytic_account, self).write(cr, uid, ids, vals, context=context)
2.6.1 by Matthieu Dietrich
UF-133: [FIX] changed active flag to 2 activity periods
324
827.8.64 by Olivier DOSSMANN
UF-1106 [FIX] FP search compatibility with selected destination in analytic distribution wizard
325
    def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
326
        """
1390.4.1 by Olivier DOSSMANN
UTP-423 [FIX] Do not permit user to select an analytic FP account if it is used in a soft/hard closed contract.
327
        FIXME: this method do others things that not have been documented. Please complete here what method do.
827.8.64 by Olivier DOSSMANN
UF-1106 [FIX] FP search compatibility with selected destination in analytic distribution wizard
328
        """
1390.4.3 by Olivier DOSSMANN
UTP-423 [FIX] context that break YAML tests
329
        if not context:
330
            context = {}
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
331
        if context and 'search_by_ids' in context and context['search_by_ids']:
332
            args2 = args[-1][2]
333
            del args[-1]
334
            ids = []
335
            for arg in args2:
336
                ids.append(arg[1])
337
            args.append(('id', 'in', ids))
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
338
        # UF-1713: Active/inactive functionnality was missing.
339
        if context and 'filter_inactive' in context and context['filter_inactive']:
340
            args.append(('filter_active', '=', context['filter_inactive']))
827.8.64 by Olivier DOSSMANN
UF-1106 [FIX] FP search compatibility with selected destination in analytic distribution wizard
341
        # Tuple Account/Destination search
342
        for i, arg in enumerate(args):
343
            if arg[0] and arg[0] == 'tuple_destination':
344
                fp_ids = []
345
                destination_ids = self.pool.get('account.destination.link').search(cr, uid, [('account_id', '=', arg[2][0]), ('destination_id', '=', arg[2][1])])
346
                for adl in self.pool.get('account.destination.link').read(cr, uid, destination_ids, ['funding_pool_ids']):
347
                    fp_ids.append(adl.get('funding_pool_ids'))
348
                fp_ids = flatten(fp_ids)
349
                args[i] = ('id', 'in', fp_ids)
1390.4.1 by Olivier DOSSMANN
UTP-423 [FIX] Do not permit user to select an analytic FP account if it is used in a soft/hard closed contract.
350
        res = super(analytic_account, self).search(cr, uid, args, offset, limit, order, context=context, count=count)
351
        return res
350.8.2 by Olivier DOSSMANN
UF-359 [ADD] Filter on OC in order to see all child
352
353
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
354
        if not context:
355
            context = {}
356
        view = super(analytic_account, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
350.8.7 by jf
FIX unit test
357
        try:
559.20.1 by Olivier DOSSMANN
[IMP] Disallow some analytic accounts deletion
358
            oc_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_project')[1]
350.8.7 by jf
FIX unit test
359
        except ValueError:
360
            oc_id = 0
350.8.2 by Olivier DOSSMANN
UF-359 [ADD] Filter on OC in order to see all child
361
        if view_type=='form':
350.8.3 by Olivier DOSSMANN
UF-359 [IMP] Give a better method to change xml attribute in fields_view_get
362
            tree = etree.fromstring(view['arch'])
363
            fields = tree.xpath('/form/field[@name="cost_center_ids"]')
364
            for field in fields:
365
                field.set('domain', "[('type', '!=', 'view'), ('id', 'child_of', [%s])]" % oc_id)
366
            view['arch'] = etree.tostring(tree)
350.8.2 by Olivier DOSSMANN
UF-359 [ADD] Filter on OC in order to see all child
367
        return view
368
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
369
    def on_change_category(self, cr, uid, id, category):
370
        if not category:
371
            return {}
372
        res = {'value': {}, 'domain': {}}
373
        parent = self.search(cr, uid, [('category', '=', category), ('parent_id', '=', False)])[0]
374
        res['value']['parent_id'] = parent
581.5.5 by Matthieu Dietrich
UF-683: [FIX] added consolidated budgets + bug fixes on reports and budgets
375
        res['domain']['parent_id'] = [('category', '=', category), ('type', '=', 'view')]
363.10.1 by Matthieu Dietrich
UF-527: Change Active Date for Private Funds
376
        return res
601.1.1 by Olivier DOSSMANN
UF-814 [ADD] Change Analytic Account display
377
601.1.7 by jf
UF-814: name_search on acccount.analytic.account
378
    def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
379
        if not args:
380
            args=[]
381
        if context is None:
382
            context={}
1380.3.9 by Olivier DOSSMANN
UF-1678 [ADD] Filtering inactive analytic account on name_search for analytic distribution wizard
383
        if context.get('hide_inactive', False):
384
            args.append(('filter_active', '=', True))
601.1.7 by jf
UF-814: name_search on acccount.analytic.account
385
        if context.get('current_model') == 'project.project':
386
            cr.execute("select analytic_account_id from project_project")
387
            project_ids = [x[0] for x in cr.fetchall()]
388
            return self.name_get(cr, uid, project_ids, context=context)
389
        account = self.search(cr, uid, ['|', ('code', 'ilike', '%%%s%%' % name), ('name', 'ilike', '%%%s%%' % name)]+args, limit=limit, context=context)
390
        return self.name_get(cr, uid, account, context=context)
391
1748 by jf
UF-2079 [FIX] context={} in method def
392
    def name_get(self, cr, uid, ids, context=None):
601.1.1 by Olivier DOSSMANN
UF-814 [ADD] Change Analytic Account display
393
        """
394
        Get name for analytic account with analytic account code.
395
        Example: For an account OC/Project/Mission, we have something like this:
396
          MIS-001 (OC-015/PROJ-859)
397
        """
398
        # Some verifications
399
        if not context:
400
            context = {}
401
        if isinstance(ids, (int, long)):
402
            ids = [ids]
403
        # Prepare some value
404
        res = []
405
        # Browse all accounts
406
        for account in self.browse(cr, uid, ids, context=context):
601.1.5 by Olivier DOSSMANN
UF-814 [ADD] Adapt name_get regarding last Jira comments
407
#            data = []
408
#            acc = account
409
#            while acc:
410
#                data.insert(0, acc.code)
411
#                acc = acc.parent_id
412
#            data = ' / '.join(data[1:-1])
413
#            display = "%s" % (account.code)
414
#            if len(data) and len(data) > 0:
415
#                display = "%s (%s)" % (account.code, data)
416
#            res.append((account.id, display))
417
            res.append((account.id, account.code))
601.1.1 by Olivier DOSSMANN
UF-814 [ADD] Change Analytic Account display
418
        return res
419
707 by jf
[FIX] Default values
420
    def unlink(self, cr, uid, ids, context=None):
559.20.1 by Olivier DOSSMANN
[IMP] Disallow some analytic accounts deletion
421
        """
1193.12.3 by Olivier DOSSMANN
UF-1469 [DEL] Dummy CC from Unifield
422
        Delete some analytic account is forbidden!
559.20.1 by Olivier DOSSMANN
[IMP] Disallow some analytic accounts deletion
423
        """
424
        # Some verification
425
        if not context:
426
            context = {}
427
        if isinstance(ids, (int, long)):
428
            ids = [ids]
429
        # Prepare some values
430
        analytic_accounts = []
431
        # Search OC CC
432
        try:
433
            oc_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_project')[1]
434
        except ValueError:
435
            oc_id = 0
436
        analytic_accounts.append(oc_id)
437
        # Search Funding Pool
438
        try:
439
            fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_funding_pool')[1]
440
        except ValueError:
441
            fp_id = 0
442
        analytic_accounts.append(fp_id)
443
        # Search Free 1
444
        try:
445
            f1_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_free_1')[1]
446
        except ValueError:
447
            f1_id = 0
448
        analytic_accounts.append(f1_id)
449
        # Search Free 2
450
        try:
451
            f2_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_free_2')[1]
452
        except ValueError:
453
            f2_id = 0
454
        analytic_accounts.append(f2_id)
455
        # Search MSF Private Fund
456
        try:
457
            msf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
458
        except ValueError:
459
            msf_id = 0
460
        analytic_accounts.append(msf_id)
461
        # Accounts verification
462
        for id in ids:
463
            if id in analytic_accounts:
464
                raise osv.except_osv(_('Error'), _('You cannot delete this Analytic Account!'))
465
        return super(analytic_account, self).unlink(cr, uid, ids, context=context)
466
827.8.52 by Olivier DOSSMANN
UF-1106 [ADD] Analytic distribution correction with journal item correction
467
    def is_blocked_by_a_contract(self, cr, uid, ids):
468
        """
469
        Return ids (analytic accounts) that are blocked by a contract (just FP1)
470
        """
471
        # Some verifications
472
        if isinstance(ids, (int, long)):
473
            ids = [ids]
474
        # Prepare some values
475
        res = []
476
        for aa in self.browse(cr, uid, ids):
477
            # Only check funding pool accounts
478
            if aa.category != 'FUNDING':
479
                continue
827.8.56 by Olivier DOSSMANN
UF-1106 [FIX] Error when change FP in analytic distribution correction wizard
480
            link_ids = self.pool.get('financing.contract.funding.pool.line').search(cr, uid, [('funding_pool_id', '=', aa.id)])
827.8.52 by Olivier DOSSMANN
UF-1106 [ADD] Analytic distribution correction with journal item correction
481
            format_ids = []
482
            for link in self.pool.get('financing.contract.funding.pool.line').browse(cr, uid, link_ids):
483
                if link.contract_id:
484
                    format_ids.append(link.contract_id.id)
485
            contract_ids = self.pool.get('financing.contract.contract').search(cr, uid, [('format_id', 'in', format_ids)])
827.8.56 by Olivier DOSSMANN
UF-1106 [FIX] Error when change FP in analytic distribution correction wizard
486
            for contract in self.pool.get('financing.contract.contract').browse(cr, uid, contract_ids):
827.8.52 by Olivier DOSSMANN
UF-1106 [ADD] Analytic distribution correction with journal item correction
487
                if contract.state in ['soft_closed', 'hard_closed']:
488
                    res.append(aa.id)
489
        return res
1873 by jf
UF-530 [IMP] Add a "remove all" button in the CC and accounts tabs from the funding pool form view
490
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
491
    def get_analytic_line(self, cr, uid, ids, context=None):
492
        """
493
        Return analytic lines list linked to the given analytic accounts
494
        """
495
        # Some verifications
496
        if not context:
497
            context = {}
498
        if isinstance(ids, (int, long)):
499
            ids = [ids]
500
        default_field = 'account_id'
501
        for aaa in self.browse(cr, uid, ids):
502
            if aaa.category == 'OC':
503
                default_field = 'cost_center_id'
504
            elif aaa.category == 'DEST':
505
                default_field = 'destination_id'
506
        # Prepare some values
507
        domain = [(default_field, 'child_of', ids)]
508
        context.update({default_field: context.get('active_id')})
509
        return {
510
            'name': _('Analytic Journal Items'),
511
            'type': 'ir.actions.act_window',
512
            'res_model': 'account.analytic.line',
513
            'view_type': 'form',
514
            'view_mode': 'tree,form',
515
            'context': context,
516
            'domain': domain,
517
            'target': 'current',
518
        }
519
1864.3.1 by Sean Carroll
UF-530: [IMP] added delete all buttons
520
    def button_cc_clear(self, cr, uid, ids, context=None):
1873 by jf
UF-530 [IMP] Add a "remove all" button in the CC and accounts tabs from the funding pool form view
521
        self.write(cr, uid, ids, {'cost_center_ids':[(6, 0, [])]}, context=context)
1864.3.1 by Sean Carroll
UF-530: [IMP] added delete all buttons
522
        return True
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
523
1864.3.1 by Sean Carroll
UF-530: [IMP] added delete all buttons
524
    def button_dest_clear(self, cr, uid, ids, context=None):
1873 by jf
UF-530 [IMP] Add a "remove all" button in the CC and accounts tabs from the funding pool form view
525
        self.write(cr, uid, ids, {'tuple_destination_account_ids':[(6, 0, [])]}, context=context)
1864.3.1 by Sean Carroll
UF-530: [IMP] added delete all buttons
526
        return True
1793.2.2 by Olivier DOSSMANN
UF-1713 [ADD] Analytic chart of account rebuild
527
232.5.1 by Matthieu Dietrich
UF-630: [IMP] 1st step of analytic distribution wizard (on registers and move lines)
528
analytic_account()
2.1.1 by Matthieu Dietrich
UF-133: [ADD] Analytical plans
529
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: