~therp-nl/banking-addons/ba61-SCT_suitable_bank_types

« back to all changes in this revision

Viewing changes to account_banking/wizard/banking_transaction_wizard.py

[ADD] allow to manually match multiple invoices/move lines causing the
statement line to be split according to the amounts given

Show diffs side-by-side

added added

removed removed

Lines of Context:
94
94
        # The following fields get never written
95
95
        # they are just triggers for manual matching
96
96
        # which populates regular fields on the transaction
97
 
        manual_invoice_id = vals.pop('manual_invoice_id', False)
98
 
        manual_move_line_id = vals.pop('manual_move_line_id', False)
 
97
        manual_invoice_ids = vals.pop('manual_invoice_ids', [])
 
98
        manual_move_line_ids = vals.pop('manual_move_line_ids', [])
99
99
 
100
100
        # Support for writing fields.related is still flakey:
101
101
        # https://bugs.launchpad.net/openobject-server/+bug/915975
167
167
                            _("No entry found for the selected invoice. " +
168
168
                              "Try manual reconciliation."))
169
169
 
170
 
        if manual_move_line_id or manual_invoice_id:
 
170
        if manual_move_line_ids or manual_invoice_ids:
171
171
            move_line_obj = self.pool.get('account.move.line')
172
172
            invoice_obj = self.pool.get('account.invoice')
173
173
            statement_line_obj = self.pool.get('account.bank.statement.line')
174
 
            for wiz in self.browse(
175
 
                cr, uid, ids, context=context):
176
 
                move_line_id = False
177
 
                invoice_id = manual_invoice_id
178
 
                if invoice_id:
179
 
                    invoice = invoice_obj.browse(
180
 
                        cr, uid, manual_invoice_id, context=context)
 
174
            manual_invoice_ids = (
 
175
                    [i[1] for i in manual_invoice_ids if i[0]==4] +
 
176
                    [j for i in manual_invoice_ids if i[0]==6 for j in i[2]])
 
177
            manual_move_line_ids = (
 
178
                    [i[1] for i in manual_move_line_ids if i[0]==4] +
 
179
                    [j for i in manual_move_line_ids if i[0]==6 for j in i[2]])
 
180
            for wiz in self.browse(cr, uid, ids, context=context):
 
181
                #write can be called multiple times for the same values
 
182
                #that doesn't hurt above, but it does here
 
183
                if wiz.match_type and (
 
184
                        len(manual_move_line_ids) > 1 or
 
185
                        len(manual_invoice_ids) > 1):
 
186
                    continue
 
187
 
 
188
                todo = []
 
189
 
 
190
                for invoice in invoice_obj.browse(
 
191
                        cr, uid, manual_invoice_ids, context=context):
 
192
                    found_move_line = False
181
193
                    if invoice.move_id:
182
194
                        for line in invoice.move_id.line_id:
183
195
                            if line.account_id.type in ('receivable', 'payable'):
184
 
                                move_line_id = line.id
 
196
                                todo.append((invoice.id, line.id))
 
197
                                found_move_line = True
185
198
                                break
186
 
                    if not move_line_id:
187
 
                        osv.except_osv(
 
199
                    if not found_move_line:
 
200
                        raise osv.except_osv(
188
201
                            _("Cannot select for reconcilion"),
189
202
                            _("No entry found for the selected invoice. "))
190
 
                else:
191
 
                    move_line_id = manual_move_line_id
192
 
                    move_line = move_line_obj.read(
193
 
                        cr, uid, move_line_id, ['invoice'], context=context)
194
 
                    invoice_id = (move_line['invoice'] and
195
 
                                  move_line['invoice'][0])
196
 
                vals = {
197
 
                    'move_line_id': move_line_id,
198
 
                    'move_line_ids': [(6, 0, [move_line_id])],
199
 
                    'invoice_id': invoice_id,
200
 
                    'invoice_ids': [(6, 0, invoice_id and
201
 
                                     [invoice_id] or [])],
202
 
                    'match_type': 'manual',
203
 
                    }
204
 
                transaction_obj.clear_and_write(
205
 
                    cr, uid, wiz.import_transaction_id.id,
206
 
                    vals, context=context)
207
 
                st_line_vals = {
208
 
                    'account_id': move_line_obj.read(
209
 
                        cr, uid, move_line_id, 
210
 
                        ['account_id'], context=context)['account_id'][0],
211
 
                    }
212
 
                if invoice_id:
213
 
                    st_line_vals['partner_id'] = invoice_obj.read(
214
 
                        cr, uid, invoice_id, 
215
 
                        ['partner_id'], context=context)['partner_id'][0]
216
 
                statement_line_obj.write(
217
 
                    cr, uid, wiz.import_transaction_id.statement_line_id.id,
218
 
                    st_line_vals, context=context)
 
203
                for move_line_id in manual_move_line_ids:
 
204
                    todo_entry = [False, move_line_id]
 
205
                    move_line=move_line_obj.read(
 
206
                            cr,
 
207
                            uid,
 
208
                            move_line_id,
 
209
                            ['invoice'],
 
210
                            context=context)
 
211
                    if move_line['invoice']:
 
212
                        todo_entry[0] = move_line['invoice'][0]
 
213
                    todo.append(todo_entry)
 
214
 
 
215
                while todo:
 
216
                    todo_entry = todo.pop()
 
217
                    move_line = move_line_obj.browse(
 
218
                            cr, uid, todo_entry[1], context)
 
219
                    transaction_id = wiz.import_transaction_id.id
 
220
                    statement_line_id = wiz.statement_line_id.id
 
221
 
 
222
                    if len(todo) > 0:
 
223
                        statement_line_id = wiz.statement_line_id.split_off(
 
224
                                move_line.debit or -move_line.credit)[0]
 
225
                        transaction_id = statement_line_obj.browse(
 
226
                                cr,
 
227
                                uid,
 
228
                                statement_line_id,
 
229
                                context=context).import_transaction_id.id
 
230
 
 
231
                    vals = {
 
232
                        'move_line_id': todo_entry[1],
 
233
                        'move_line_ids': [(6, 0, [todo_entry[1]])],
 
234
                        'invoice_id': todo_entry[0],
 
235
                        'invoice_ids': [(6, 0,
 
236
                            [todo_entry[0]] if todo_entry[0] else [])],
 
237
                        'match_type': 'manual',
 
238
                        }
 
239
 
 
240
                    transaction_obj.clear_and_write(
 
241
                        cr, uid, transaction_id, vals, context=context)
 
242
 
 
243
                    st_line_vals = {
 
244
                        'account_id': move_line_obj.read(
 
245
                            cr, uid, todo_entry[1], 
 
246
                            ['account_id'], context=context)['account_id'][0],
 
247
                        }
 
248
 
 
249
                    if todo_entry[0]:
 
250
                        st_line_vals['partner_id'] = invoice_obj.read(
 
251
                            cr, uid, todo_entry[0], 
 
252
                            ['partner_id'], context=context)['partner_id'][0]
 
253
 
 
254
                    statement_line_obj.write(
 
255
                        cr, uid, statement_line_id, 
 
256
                        st_line_vals, context=context)
219
257
        return res
220
258
 
221
259
    def trigger_write(self, cr, uid, ids, context=None):
247
285
                    account_id = setting.default_debit_account_id and setting.default_debit_account_id.id
248
286
                statement_pool.write(cr, uid, wiz.statement_line_id.id, {'account_id':account_id})
249
287
            
250
 
            self.write(cr, uid, wiz.id, {'partner_id': False}, context=context)
251
 
            
252
 
            wizs = self.read(
253
 
                cr, uid, ids, ['import_transaction_id'], context=context)
254
 
            trans_ids = [x['import_transaction_id'][0] for x in wizs
255
 
                         if x['import_transaction_id']]
256
 
            self.pool.get('banking.import.transaction').clear_and_write(
257
 
                cr, uid, trans_ids, context=context)
 
288
            # Restore partner id from the bank account or else reset
 
289
            partner_id = False
 
290
            if (wiz.statement_line_id.partner_bank_id and
 
291
                    wiz.statement_line_id.partner_bank_id.partner_id):
 
292
                partner_id = wiz.statement_line_id.partner_bank_id.partner_id.id
 
293
            wiz.write({'partner_id': partner_id})
 
294
            
 
295
            if wiz.statement_line_id:
 
296
                #delete splits causing an unsplit if this is a split
 
297
                #transaction
 
298
                statement_pool.unlink(cr, uid,
 
299
                        statement_pool.search(cr, uid,
 
300
                            [('parent_id', '=', wiz.statement_line_id.id)],
 
301
                            context=context),
 
302
                        context=context)
 
303
 
 
304
            if wiz.import_transaction_id:
 
305
                wiz.import_transaction_id.clear_and_write()
 
306
 
 
307
            
258
308
        return True
259
309
 
260
310
    def reverse_duplicate(self, cr, uid, ids, context=None):
281
331
        return res
282
332
 
283
333
    def button_done(self, cr, uid, ids, context=None):
284
 
        return {'nodestroy': False, 'type': 'ir.actions.act_window_close'}        
 
334
        return {'type': 'ir.actions.act_window_close'}        
285
335
 
286
336
    _defaults = {
287
337
#        'match_type': _get_default_match_type,
305
355
            'statement_line_id', 'partner_id',
306
356
            type='many2one', relation='res.partner',
307
357
            string="Partner", readonly=True),
 
358
        'statement_line_parent_id': fields.related(
 
359
            'statement_line_id', 'parent_id', type='many2one',
 
360
            relation='account.bank.statement.line', readonly=True),
308
361
        'import_transaction_id': fields.related(
309
362
            'statement_line_id', 'import_transaction_id', 
310
363
            string="Import transaction",
350
403
        'match_type': fields.related(
351
404
            'import_transaction_id', 'match_type', 
352
405
            type="char", size=16, string='Match type', readonly=True),
353
 
        'manual_invoice_id': fields.many2one(
354
 
            'account.invoice', 'Match this invoice',
 
406
        'manual_invoice_ids': fields.many2many(
 
407
            'account.invoice',
 
408
            'banking_transaction_wizard_account_invoice_rel',
 
409
            'wizard_id', 'invoice_id', string='Match one or more invoices',
355
410
            domain=[('reconciled', '=', False)]),
356
 
        'manual_move_line_id': fields.many2one(
357
 
            'account.move.line', 'Or match this entry',
 
411
        'manual_move_line_ids': fields.many2many(
 
412
            'account.move.line',
 
413
            'banking_transaction_wizard_account_move_line_rel',
 
414
            'wizard_id', 'move_line_id', string='Or match one or more entries',
358
415
            domain=[('account_id.reconcile', '=', True),
359
 
                    ('reconcile_id', '=', False)],
360
 
            ),
 
416
                    ('reconcile_id', '=', False)]),
361
417
        'payment_option': fields.related('import_transaction_id','payment_option', string='Payment Difference', type='selection', required=True,
362
418
                                         selection=[('without_writeoff', 'Keep Open'),('with_writeoff', 'Reconcile Payment Balance')]),
363
419
        'writeoff_analytic_id': fields.related(