~camptocamp/c2c-financial-addons/trunk

« back to all changes in this revision

Viewing changes to account_statement_ext/statement.py

  • Committer: Joël Grand-Guillaume
  • Date: 2012-06-11 06:13:37 UTC
  • Revision ID: joel.grandguillaume@camptocamp.com-20120611061337-n1yji5we5subxb70
[MRG] From last dev on customer branch: finaly we override the way the bank statement work instead of having another object. You have now profil on bank statement to configure the generated entries once posted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
##############################################################################
3
 
#
4
 
#    Author: Joel Grand-Guillaume
5
 
#    Copyright 2011-2012 Camptocamp SA
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
 
from osv import fields, osv
23
 
from tools.translate import _
24
 
from account_statement_import.file_parser.parser import FileParser
25
 
import datetime
26
 
import netsvc
27
 
logger = netsvc.Logger()
28
 
 
29
 
 
30
 
class AccountSatement(osv.osv):
31
 
    """Override account bank statement to remove the period on it
32
 
    and compute it for each line."""
33
 
 
34
 
    _inherit = "account.bank.statement"
35
 
    
36
 
    _columns = {
37
 
        'period_id': fields.many2one('account.period', 'Period', required=False, readonly=True),
38
 
    }
39
 
 
40
 
    _defaults = {
41
 
        'period_id': lambda *a: False,
42
 
    }
43
 
   
44
 
    def _get_period(self, cursor, uid, date, context=None):
45
 
        '''
46
 
        Find matching period for date, used in thestatement line creation.
47
 
        '''
48
 
        period_obj = self.pool.get('account.period')
49
 
        periods = period_obj.find(cursor, uid, dt=date, context=context)
50
 
        return periods and periods[0] or False
51
 
        
52
 
    def _check_company_id(self, cr, uid, ids, context=None):
53
 
        """
54
 
        Adapt this constraint method from the account module to reflect the
55
 
        move of period_id to the statement line
56
 
        """
57
 
        for statement in self.browse(cr, uid, ids, context=context):
58
 
            if (statement.period_id and
59
 
                statement.company_id.id != statement.period_id.company_id.id):
60
 
                return False
61
 
            for line in statement.line_ids:
62
 
                if (line.period_id and
63
 
                    statement.company_id.id != line.period_id.company_id.id):
64
 
                    return False
65
 
        return True
66
 
 
67
 
    # Redefine the constraint, or it still refer to the original method
68
 
    _constraints = [
69
 
        (_check_company_id, 'The journal and period chosen have to belong to the same company.', ['journal_id','period_id']),
70
 
    ]
71
 
    
72
 
    def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, st_line_number, context=None):
73
 
        """Override a large portion of the code to compute the periode for each line instead of
74
 
        taking the period of the whole statement.
75
 
        Remove the entry posting on generated account moves."""
76
 
        if context is None:
77
 
            context = {}
78
 
        res_currency_obj = self.pool.get('res.currency')
79
 
        account_move_obj = self.pool.get('account.move')
80
 
        account_move_line_obj = self.pool.get('account.move.line')
81
 
        account_bank_statement_line_obj = self.pool.get('account.bank.statement.line')
82
 
        st_line = account_bank_statement_line_obj.browse(cr, uid, st_line_id, context=context)
83
 
        st = st_line.statement_id
84
 
 
85
 
        context.update({'date': st_line.date})
86
 
        ctx = context.copy()                        # Chg
87
 
        ctx['company_id'] = st_line.company_id.id   # Chg
88
 
        period_id = self._get_period(               # Chg
89
 
            cr, uid, st_line.date, context=ctx)  
90
 
            
91
 
        move_id = account_move_obj.create(cr, uid, {
92
 
            'journal_id': st.journal_id.id,
93
 
            'period_id': period_id,                 # Chg
94
 
            'date': st_line.date,
95
 
            'name': st_line_number,
96
 
            'ref': st_line.ref,
97
 
        }, context=context)
98
 
        account_bank_statement_line_obj.write(cr, uid, [st_line.id], {
99
 
            'move_ids': [(4, move_id, False)]
100
 
        })
101
 
 
102
 
        torec = []
103
 
        if st_line.amount >= 0:
104
 
            account_id = st.journal_id.default_credit_account_id.id
105
 
        else:
106
 
            account_id = st.journal_id.default_debit_account_id.id
107
 
 
108
 
        acc_cur = ((st_line.amount<=0) and st.journal_id.default_debit_account_id) or st_line.account_id
109
 
        context.update({
110
 
                'res.currency.compute.account': acc_cur,
111
 
            })
112
 
        amount = res_currency_obj.compute(cr, uid, st.currency.id,
113
 
                company_currency_id, st_line.amount, context=context)
114
 
 
115
 
        val = {
116
 
            'name': st_line.name,
117
 
            'date': st_line.date,
118
 
            'ref': st_line.ref,
119
 
            'move_id': move_id,
120
 
            'partner_id': ((st_line.partner_id) and st_line.partner_id.id) or False,
121
 
            'account_id': (st_line.account_id) and st_line.account_id.id,
122
 
            'credit': ((amount>0) and amount) or 0.0,
123
 
            'debit': ((amount<0) and -amount) or 0.0,
124
 
            'statement_id': st.id,
125
 
            'journal_id': st.journal_id.id,
126
 
            'period_id': period_id,                 #Chg
127
 
            'currency_id': st.currency.id,
128
 
            'analytic_account_id': st_line.analytic_account_id and st_line.analytic_account_id.id or False
129
 
        }
130
 
 
131
 
        if st.currency.id <> company_currency_id:
132
 
            amount_cur = res_currency_obj.compute(cr, uid, company_currency_id,
133
 
                        st.currency.id, amount, context=context)
134
 
            val['amount_currency'] = -amount_cur
135
 
 
136
 
        if st_line.account_id and st_line.account_id.currency_id and st_line.account_id.currency_id.id <> company_currency_id:
137
 
            val['currency_id'] = st_line.account_id.currency_id.id
138
 
            amount_cur = res_currency_obj.compute(cr, uid, company_currency_id,
139
 
                    st_line.account_id.currency_id.id, amount, context=context)
140
 
            val['amount_currency'] = -amount_cur
141
 
 
142
 
        move_line_id = account_move_line_obj.create(cr, uid, val, context=context)
143
 
        torec.append(move_line_id)
144
 
 
145
 
        # Fill the secondary amount/currency
146
 
        # if currency is not the same than the company
147
 
        amount_currency = False
148
 
        currency_id = False
149
 
        if st.currency.id <> company_currency_id:
150
 
            amount_currency = st_line.amount
151
 
            currency_id = st.currency.id
152
 
        account_move_line_obj.create(cr, uid, {
153
 
            'name': st_line.name,
154
 
            'date': st_line.date,
155
 
            'ref': st_line.ref,
156
 
            'move_id': move_id,
157
 
            'partner_id': ((st_line.partner_id) and st_line.partner_id.id) or False,
158
 
            'account_id': account_id,
159
 
            'credit': ((amount < 0) and -amount) or 0.0,
160
 
            'debit': ((amount > 0) and amount) or 0.0,
161
 
            'statement_id': st.id,
162
 
            'journal_id': st.journal_id.id,
163
 
            'period_id': period_id,                 #Chg
164
 
            'amount_currency': amount_currency,
165
 
            'currency_id': currency_id,
166
 
            }, context=context)
167
 
 
168
 
        for line in account_move_line_obj.browse(cr, uid, [x.id for x in
169
 
                account_move_obj.browse(cr, uid, move_id,
170
 
                    context=context).line_id],
171
 
                context=context):
172
 
            if line.state <> 'valid':
173
 
                raise osv.except_osv(_('Error !'),
174
 
                        _('Journal item "%s" is not valid.') % line.name)
175
 
 
176
 
        # Bank statements will not consider boolean on journal entry_posted
177
 
        account_move_obj.post(cr, uid, [move_id], context=context)
178
 
        return move_id
179
 
 
180
 
    def _get_st_number_period(self, cr, uid, date, journal_sequence_id):
181
 
        """Retrieve the name of bank statement from sequence, according to the period 
182
 
        corresponding to the date passed in args"""
183
 
        year = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, date)).fiscalyear_id.id
184
 
        c = {'fiscalyear_id': year}
185
 
        obj_seq = self.pool.get('ir.sequence')
186
 
        if journal_sequence_id:
187
 
            st_number = obj_seq.next_by_id(cr, uid, journal_sequence_id, context=c)
188
 
        else:
189
 
            st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=c)
190
 
        return st_number
191
 
 
192
 
    def button_confirm_bank(self, cr, uid, ids, context=None):
193
 
        """Completely override the method in order to have
194
 
           an error message which displays all the messages
195
 
           instead of having them pop one by one.
196
 
           We have to copy paste a big block of code, changing the error
197
 
           stack + managing period from date."""
198
 
        # obj_seq = self.pool.get('irerrors_stack.sequence')
199
 
        if context is None:
200
 
            context = {}
201
 
        for st in self.browse(cr, uid, ids, context=context):
202
 
            
203
 
            j_type = st.journal_id.type
204
 
            company_currency_id = st.journal_id.company_id.currency_id.id
205
 
            if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):
206
 
                continue
207
 
 
208
 
            self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)
209
 
            if (not st.journal_id.default_credit_account_id) \
210
 
                    or (not st.journal_id.default_debit_account_id):
211
 
                raise osv.except_osv(_('Configuration Error !'),
212
 
                        _('Please verify that an account is defined in the journal.'))
213
 
 
214
 
            if not st.name == '/':
215
 
                st_number = st.name
216
 
            else:
217
 
# Begin Changes                
218
 
                seq_id = st.journal_id.sequence_id and st.journal_id.sequence_id.id or False
219
 
                st_number = self._get_st_number_period(cr, uid, st.date, seq_id)
220
 
                # c = {'fiscalyear_id': st.period_id.fiscalyear_id.id}
221
 
                # if st.journal_id.sequence_id:
222
 
                #     st_number = obj_seq.next_by_id(cr, uid, st.journal_id.sequence_id.id, context=c)
223
 
                # else:
224
 
                #     st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=c)
225
 
# End Changes 
226
 
            for line in st.move_line_ids:
227
 
                if line.state <> 'valid':
228
 
                    raise osv.except_osv(_('Error !'),
229
 
                            _('The account entries lines are not in valid state.'))
230
 
# begin changes
231
 
            errors_stack = []
232
 
            for st_line in st.line_ids:
233
 
                try:
234
 
                    if st_line.analytic_account_id:
235
 
                        if not st.journal_id.analytic_journal_id:
236
 
                            raise osv.except_osv(_('No Analytic Journal !'),
237
 
                                             _("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
238
 
                    if not st_line.amount:
239
 
                        continue
240
 
                    st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context)
241
 
                    self.create_move_from_st_line(cr, uid, st_line.id, company_currency_id, st_line_number, context)
242
 
                except osv.except_osv, exc:
243
 
                    msg = "Line ID %s with ref %s had following error: %s" % (st_line.id, st_line.ref, exc.value)
244
 
                    errors_stack.append(msg)
245
 
                except Exception, exc:
246
 
                    msg = "Line ID %s with ref %s had following error: %s" % (st_line.id, st_line.ref, str(exc))
247
 
                    errors_stack.append(msg)
248
 
            if errors_stack:
249
 
                msg = u"\n".join(errors_stack)
250
 
                raise osv.except_osv(_('Error'), msg)
251
 
#end changes
252
 
            self.write(cr, uid, [st.id], {
253
 
                    'name': st_number,
254
 
                    'balance_end_real': st.balance_end
255
 
            }, context=context)
256
 
            self.log(cr, uid, st.id, _('Statement %s is confirmed, journal items are created.') % (st_number,))
257
 
        return self.write(cr, uid, ids, {'state':'confirm'}, context=context)
258
 
 
259
 
class AccountSatementLine(osv.osv):
260
 
    '''
261
 
    Adds the period on line, matched on the date.
262
 
    '''
263
 
    _inherit = 'account.bank.statement.line'
264
 
 
265
 
    def _get_period(self, cursor, user, context=None):
266
 
        date = context.get('date', None)
267
 
        periods = self.pool.get('account.period').find(cursor, user, dt=date)
268
 
        return periods and periods[0] or False
269
 
 
270
 
    _columns = {
271
 
        'period_id': fields.many2one('account.period', 'Period', required=True),
272
 
    }
273
 
 
274
 
    _defaults = {
275
 
        'period_id': _get_period,
276
 
    }