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

« back to all changes in this revision

Viewing changes to account_reconciliation/wizard/account_reconcile.py

  • Committer: matthieu.choplin at msf
  • Date: 2012-08-30 07:48:00 UTC
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: matthieu.choplin@geneva.msf.org-20120830074800-l442bu42mt0yzutn
[uf-1374]- change the write and create by an _sql_constraint on the financing contract check dates

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
from osv import fields
26
26
from tools.translate import _
27
27
import time
28
 
from collections import defaultdict
29
28
 
30
29
class account_move_line_reconcile(osv.osv_memory):
31
30
    _inherit = 'account.move.line.reconcile'
35
34
        'state': fields.selection([('total', 'Full Reconciliation'), ('partial', 'Partial Reconciliation'), 
36
35
            ('total_change', 'Full Reconciliation with change'), ('partial_change', 'Partial Reconciliation with change')], string="State", 
37
36
            required=True, readonly=True),
38
 
        'different_currencies': fields.boolean('Is this reconciliation in different currencies? (2 at most)'),
39
37
    }
40
38
 
41
39
    _defaults = {
42
40
        'state': lambda *a: 'total',
43
 
        'different_currencies': lambda *a: False,
44
41
    }
45
42
 
46
43
    def default_get(self, cr, uid, fields, context=None):
54
51
        res = super(account_move_line_reconcile, self).default_get(cr, uid, fields, context=context)
55
52
        # Retrieve some value
56
53
        data = self.trans_rec_get(cr, uid, context['active_ids'], context=context)
57
 
        # Get different currencies state
58
 
        if 'different_currencies' in fields and 'different_currencies' in data:
59
 
            res.update({'different_currencies': data['different_currencies']})
60
54
        # Update res with state value
61
55
        if 'state' in fields and 'state' in data:
62
56
            res.update({'state': data['state']})
89
83
        intermission_default_account_id = False
90
84
        if self.pool.get('res.users').browse(cr, uid, uid).company_id.intermission_default_counterpart:
91
85
            intermission_default_account_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.intermission_default_counterpart.id
92
 
        # Browse all lines and check currencies, journals, and transfers state
93
 
        currencies = defaultdict(list)
94
 
        journals = defaultdict(list)
95
 
        transfers = []
96
 
        transfer_with_change = False
97
 
        disregard_third_party = False
98
 
        transfer = False
99
 
        debits = 0
100
 
        credits = 0
101
 
        statements = []
 
86
        # Browse all lines
102
87
        for line in account_move_line_obj.browse(cr, uid, context['active_ids']):
103
88
            if line.move_id and line.move_id.state == 'posted':
104
 
                # Prepare some infos needed for transfers with/without change
105
 
                currencies[(line.currency_id, line.transfer_journal_id and line.transfer_journal_id.currency or None)].append(line.id)
106
 
                journals[(line.journal_id.id, line.transfer_journal_id and line.transfer_journal_id.id or None)].append(line.id)
107
 
                if line.is_transfer_with_change:
108
 
                    transfers.append(line.id)
109
 
                if line.account_id.type_for_register == 'disregard_rec':
110
 
                    disregard_third_party = True
111
 
                debits += line.debit
112
 
                credits += line.credit
113
 
                statements.append(line.statement_id)
114
89
                continue
115
90
            raise osv.except_osv(_('Warning'), _('You can only do reconciliation on Posted Entries!'))
116
 
        # Check lines for transfers cases (this permit to do transfers with more than 2 lines!)
117
 
        if len(journals) == 2:
118
 
            keys = journals.keys()
119
 
            # Cross check on: "third parties" × "journals" (if YES, this is a transfer)
120
 
            if keys[0][1] == keys[1][0] and keys[0][0] == keys[1][1]:
121
 
                transfer = True
122
 
        if len(transfers) == len(context['active_ids']):
123
 
            transfer_with_change = True
124
 
        # Cross check on: "journal currency" × "transfer_journal currency" (should check all error cases to avoid transfer_with_change problems)
125
 
        if transfer_with_change:
126
 
            keys_c = currencies.keys()
127
 
            if len(currencies) != 2 or keys_c[0][1] != keys_c[1][0] or keys_c[0][0] != keys_c[1][1]:
128
 
                transfer_with_change = False
129
 
                # UTP-526: Do not raise next error if line comes from the same register and have same amount
130
 
                previous_st = None
131
 
                same = True
132
 
                for st in statements:
133
 
                    if not previous_st:
134
 
                        previous_st = st
135
 
                        continue
136
 
                    if st != previous_st:
137
 
                        same = False
138
 
                        break
139
 
                if not (same and debits == credits):
140
 
                    raise osv.except_osv(_('Warning'), _("Cannot reconcile entries : Cross check between transfer currencies fails."))
141
91
        prev_acc_id = None
142
92
        prev_third_party = None
 
93
        transfer = False
 
94
        transfer_with_change = False
 
95
        # Transfer verification
 
96
        operator = 'in'
 
97
        if len(context['active_ids']) == 1:
 
98
            operator = '='
 
99
        search_ids = account_move_line_obj.search(cr, uid, [('account_id.type_for_register', 'in', ['transfer_same', 'transfer']), 
 
100
            ('id', operator, context['active_ids'])], context=context)
 
101
        if len(context['active_ids']) == len(search_ids):
 
102
            if len(context['active_ids']) == 2:
 
103
                elements = account_move_line_obj.browse(cr, uid, context['active_ids'], context)
 
104
                first_line = elements[0]
 
105
                second_line = elements[1]
 
106
                if first_line.journal_id and first_line.transfer_journal_id and second_line.journal_id and second_line.transfer_journal_id:
 
107
                    # Cross check on third parties
 
108
                    if first_line.journal_id.id == second_line.transfer_journal_id.id and second_line.journal_id.id == first_line.transfer_journal_id.id:
 
109
                        transfer = True
 
110
                    # Cross check on currencies for transfer_with_change verification
 
111
                    if first_line.is_transfer_with_change and second_line.is_transfer_with_change:
 
112
                        if first_line.journal_id.currency == second_line.transfer_journal_id.currency and first_line.transfer_journal_id.currency == second_line.journal_id.currency:
 
113
                            transfer_with_change = True
 
114
                        else:
 
115
                            raise osv.except_osv(_('Warning'), _("Cannot reconcile entries : Cross check between transfer currencies fails."))
143
116
        if transfer_with_change:
144
117
            # For transfer with change, we need to do a total reconciliation!
145
118
            state = 'total_change'
146
 
        currency_id = False
147
 
        currency2_id = False
148
119
        for line in account_move_line_obj.browse(cr, uid, context['active_ids'], context=context):
149
120
            # prepare some values
150
121
            account_id = line.account_id.id
151
122
            # some verifications
152
123
            if not line.account_id.reconcile:
153
124
                raise osv.except_osv(_('Warning'), _('This account is not reconciliable: %s') % (line.account_id.code,))
154
 
            # Check that currency id is the same unless transfer with change cases
155
 
            if not currency_id:
156
 
                currency_id = line.currency_id and line.currency_id.id or False
157
 
            if line.currency_id and line.currency_id.id != currency_id and not transfer_with_change:
158
 
                currency2_id = line.currency_id.id
159
125
            # verification that there's only one account for each line
160
126
            if not prev_acc_id:
161
127
                prev_acc_id = account_id
163
129
                raise osv.except_osv(_('Error'), _('An account is different from others: %s') % (line.account_id.code,))
164
130
            # verification that there's only one 3rd party
165
131
            # The 3rd party verification is desactivated in case of transfer with change
166
 
            # UTP-1040: 3RD party is also desactivated in case of account that is "Disregard Third Party" as "type_for_register"
167
 
            if not transfer and not disregard_third_party:
 
132
            if not transfer:
168
133
                third_party = {
169
134
                        'partner_id': line.partner_id and line.partner_id.id or False, 
170
135
                        'employee_id': line.employee_id and line.employee_id.id or False, 
 
136
                        'register_id': line.register_id and line.register_id.id or False, 
171
137
                        'transfer_journal_id': line.transfer_journal_id and line.transfer_journal_id.id or False}
172
138
                if not prev_third_party:
173
139
                    prev_third_party = third_party
174
140
                if prev_third_party != third_party:
175
141
                    # Do not raise an exception if salary_default_account is configured and this line account is equal to default salary account
176
 
                    # True + not (False + False) => True [ERROR message]
177
 
                    # True + not (True + False) or True + not (False + True) => True [ERROR message]
178
 
                    # True + not (True + True) => False [NO error]
179
 
                    # False + anything => False [NO error]
180
 
                    if line.account_id.id != salary_account_id and not (line.partner_id.partner_type == 'intermission' and line.account_id.id != intermission_default_account_id):
181
 
                        raise osv.except_osv(_('Error'), _('Third parties do not match or bad company configuration!'))
 
142
                    if line.account_id.id != salary_account_id and (line.partner_id.partner_type == 'intermission' and line.account_id.id != intermission_default_account_id):
 
143
                        raise osv.except_osv(_('Error'), _('A third party is different from others: %s') % line.partner_txt)
182
144
            # process necessary elements
183
145
            if not line.reconcile_id and not line.reconcile_id.id:
184
146
                count += 1
185
147
                credit += line.credit_currency
186
148
                debit += line.debit_currency
187
 
                fcredit += line.credit
188
 
                fdebit += line.debit
 
149
                if transfer_with_change:
 
150
                    fcredit += line.credit
 
151
                    fdebit += line.debit
189
152
        # Adapt state value
190
153
        if (debit - credit) == 0.0:
191
154
            state = 'total'
194
157
            credit = fcredit
195
158
            if (fdebit - fcredit) == 0.0:
196
159
                state = 'total_change'
197
 
        # Currencies state
198
 
        different_currencies = False
199
 
        if currency_id and currency2_id and not transfer_with_change:
200
 
            different_currencies = True
201
 
            debit = fdebit
202
 
            credit = fcredit
203
160
        # For salaries, behaviour is the same as total_change: we use functional debit/credit
204
 
        if account_id == salary_account_id or (currency_id and currency2_id and not transfer_with_change):
 
161
        if account_id == salary_account_id:
205
162
            if (fdebit - fcredit) == 0.0:
206
163
                state = 'total'
207
164
            else:
208
165
                state = 'partial'
209
 
                # UF-2050: Do not allow partial reconciliation of entries in different currencies. We ALWAYS do total reconciliation
210
 
                if different_currencies and not transfer_with_change:
211
 
                    state = 'total'
212
 
        return {'trans_nbr': count, 'account_id': account_id, 'credit': credit, 'debit': debit, 'writeoff': debit - credit, 'state': state, 'different_currencies': different_currencies}
 
166
        return {'trans_nbr': count, 'account_id': account_id, 'credit': credit, 'debit': debit, 'writeoff': debit - credit, 'state': state}
213
167
 
214
168
    def total_reconcile(self, cr, uid, ids, context=None):
215
169
        """