~therp-nl/banking-addons/ba70-payment_move_line

« back to all changes in this revision

Viewing changes to account_banking/banking_import_transaction.py

  • Committer: Holger Brunn
  • Author(s): stefan at therp
  • Date: 2013-06-03 09:37:27 UTC
  • mfrom: (162.3.7 banking-addons)
  • Revision ID: hbrunn@therp.nl-20130603093727-t8dap2sz68ev4tky
[MIG] Forward ported fixes of 6.1 branch
[MIG] Forward port of lp:~therp-nl/banking-addons/6.1-link_partner_wizard
[FIX] conflict resulting from http://bazaar.launchpad.net/~therp-nl/banking-addons/ba7.0-MIG-import/revision/202

Show diffs side-by-side

added added

removed removed

Lines of Context:
181
181
            Match on ID of invoice (reference, name or number, whatever
182
182
            available and sensible)
183
183
            '''
184
 
            if invoice.reference:
 
184
            if invoice.reference and len(invoice.reference) > 2:
185
185
                # Reference always comes first, as it is manually set for a
186
186
                # reason.
187
187
                iref = invoice.reference.upper()
189
189
                    return True
190
190
            if invoice.type.startswith('in_'):
191
191
                # Internal numbering, no likely match on number
192
 
                if invoice.name:
 
192
                if invoice.name and len(invoice.name) > 2:
193
193
                    iname = invoice.name.upper()
194
194
                    if iname in ref or iname in msg:
195
195
                        return True
334
334
                move_line = False
335
335
                partial = False
336
336
 
337
 
            elif len(candidates) == 1:
 
337
            elif len(candidates) == 1 and candidates[0].invoice:
338
338
                # Mismatch in amounts
339
339
                move_line = candidates[0]
340
340
                invoice = move_line.invoice
382
382
                    if x.partner_id.id == move_line.partner_id.id
383
383
                    ]
384
384
                
385
 
            return (trans, self._get_move_info(
386
 
                    cr, uid, [move_line.id],
387
 
                    account_ids and account_ids[0] or False),
388
 
                    trans2)
 
385
                return (trans, self._get_move_info(
 
386
                        cr, uid, [move_line.id],
 
387
                        account_ids and account_ids[0] or False),
 
388
                        trans2)
389
389
 
390
390
        return trans, False, False
391
391
 
791
791
        if move_lines and len(move_lines) == 1:
792
792
            retval['reference'] = move_lines[0].ref
793
793
        if retval['match_type'] == 'invoice':
794
 
            retval['invoice_ids'] = [x.invoice.id for x in move_lines]
 
794
            retval['invoice_ids'] = list(set([x.invoice.id for x in move_lines]))
795
795
            retval['type'] = type_map[move_lines[0].invoice.type]
796
796
        return retval
797
797
 
885
885
                    i += 1
886
886
                continue
887
887
            
 
888
            partner_banks = []
 
889
            partner_ids = []
 
890
 
888
891
            # TODO: optimize by ordering transactions per company, 
889
892
            # and perform the stanza below only once per company.
890
893
            # In that case, take newest transaction date into account
1027
1030
            if transaction.type == bt.STORNO and has_payment:
1028
1031
                move_info = self._match_storno(
1029
1032
                    cr, uid, transaction, results['log'], context)
 
1033
 
1030
1034
            # Allow inclusion of generated bank invoices
1031
1035
            if transaction.type == bt.BANK_COSTS:
1032
1036
                lines = self._match_costs(
1038
1042
                    if not [x for x in move_lines if x.id == line.id]:
1039
1043
                        move_lines.append(line)
1040
1044
                partner_ids = [account_info.bank_partner_id.id]
1041
 
                partner_banks = []
1042
1045
            else:
1043
1046
                # Link remote partner, import account when needed
1044
1047
                partner_banks = banktools.get_bank_accounts(
1048
1051
                if partner_banks:
1049
1052
                    partner_ids = [x.partner_id.id for x in partner_banks]
1050
1053
                elif transaction.remote_owner:
1051
 
                    iban = sepa.IBAN(transaction.remote_account)
1052
 
                    if iban.valid:
1053
 
                        country_code = iban.countrycode
1054
 
                    elif transaction.remote_owner_country_code:
1055
 
                        country_code = transaction.remote_owner_country_code
1056
 
                    # fallback on the import parsers country code
1057
 
                    elif transaction.bank_country_code:
1058
 
                        country_code = transaction.bank_country_code
1059
 
                    elif company.partner_id and company.partner_id.country:
1060
 
                        country_code = company.partner_id.country.code
1061
 
                    else:
1062
 
                        country_code = None
1063
 
                    partner_id = banktools.get_or_create_partner(
 
1054
                    country_id = banktools.get_country_id(
 
1055
                        self.pool, cr, uid, transaction, context=context)
 
1056
                    partner_id = banktools.get_partner(
1064
1057
                        self.pool, cr, uid, transaction.remote_owner,
1065
1058
                        transaction.remote_owner_address,
1066
1059
                        transaction.remote_owner_postalcode,
1067
1060
                        transaction.remote_owner_city,
1068
 
                        country_code, results['log'],
1069
 
                        customer=transaction.transferred_amount > 0,
1070
 
                        supplier=transaction.transferred_amount < 0,
 
1061
                        country_id, results['log'],
1071
1062
                        context=context)
1072
 
                    if transaction.remote_account:
1073
 
                        partner_bank_id = banktools.create_bank_account(
1074
 
                            self.pool, cr, uid, partner_id,
1075
 
                            transaction.remote_account,
1076
 
                            transaction.remote_owner, 
1077
 
                            transaction.remote_owner_address,
1078
 
                            transaction.remote_owner_city,
1079
 
                            country_code, results['log'],
1080
 
                            bic=transaction.remote_bank_bic
1081
 
                            )
1082
 
                        partner_banks = partner_bank_obj.browse(
1083
 
                            cr, uid, [partner_bank_id]
1084
 
                            )
1085
 
                    else:
1086
 
                        partner_bank_id = None
1087
 
                        partner_banks = []
1088
 
                    partner_ids = [partner_id]
1089
 
                else:
1090
 
                    partner_ids = []
1091
 
                    partner_banks = []
 
1063
                    if partner_id:
 
1064
                        partner_ids = [partner_id]
 
1065
                        if transaction.remote_account:
 
1066
                            partner_bank_id = banktools.create_bank_account(
 
1067
                                self.pool, cr, uid, partner_id,
 
1068
                                transaction.remote_account,
 
1069
                                transaction.remote_owner, 
 
1070
                                transaction.remote_owner_address,
 
1071
                                transaction.remote_owner_city,
 
1072
                                country_id, bic=transaction.remote_bank_bic,
 
1073
                                context=context)
 
1074
                            partner_banks = partner_bank_obj.browse(
 
1075
                                cr, uid, [partner_bank_id], context=context)
1092
1076
 
1093
1077
            # Credit means payment... isn't it?
1094
1078
            if (not move_info
1294
1278
 
1295
1279
        return res
1296
1280
 
 
1281
    def unlink(self, cr, uid, ids, context=None):
 
1282
        """
 
1283
        Unsplit if this if a split transaction
 
1284
        """
 
1285
        for this in self.browse(cr, uid, ids, context):
 
1286
            if this.parent_id:
 
1287
                this.parent_id.write(
 
1288
                        {'transferred_amount':
 
1289
                            this.parent_id.transferred_amount + \
 
1290
                                    this.transferred_amount,
 
1291
                        })
 
1292
                this.parent_id.refresh()
 
1293
        return super(banking_import_transaction, self).unlink(
 
1294
                cr, uid, ids, context=context)
 
1295
 
1297
1296
    column_map = {
1298
1297
        # used in bank_import.py, converting non-osv transactions
1299
1298
        'statement_id': 'statement',
1345
1344
        'duplicate': fields.boolean('duplicate'),
1346
1345
        'statement_line_id': fields.many2one(
1347
1346
            'account.bank.statement.line', 'Statement line',
1348
 
            ondelete='CASCADE'),
 
1347
            ondelete='cascade'),
1349
1348
        'statement_id': fields.many2one(
1350
1349
            'account.bank.statement', 'Statement',
1351
1350
            ondelete='CASCADE'),
1407
1406
 
1408
1407
class account_bank_statement_line(orm.Model):
1409
1408
    _inherit = 'account.bank.statement.line'
 
1409
 
 
1410
    def _get_link_partner_ok(
 
1411
            self, cr, uid, ids, name, args, context=None):
 
1412
        """
 
1413
        Deliver the values of the function field that
 
1414
        determines if the 'link partner' wizard is show on the 
 
1415
        bank statement line
 
1416
        """
 
1417
        res = {}
 
1418
        for line in self.browse(cr, uid, ids, context):
 
1419
            res[line.id] = bool(
 
1420
                line.state == 'draft'
 
1421
                and not line.partner_id
 
1422
                and line.import_transaction_id
 
1423
                and line.import_transaction_id.remote_owner
 
1424
                and line.import_transaction_id.remote_account)
 
1425
        return res
 
1426
 
1410
1427
    _columns = {
1411
1428
        'import_transaction_id': fields.many2one(
1412
1429
            'banking.import.transaction', 
1413
 
            'Import transaction', readonly=True, delete='cascade'),
 
1430
            'Import transaction', readonly=True, ondelete='cascade'),
1414
1431
        'match_multi': fields.related(
1415
1432
            'import_transaction_id', 'match_multi', type='boolean',
1416
1433
            string='Multi match', readonly=True),
1430
1447
        'state': fields.selection(
1431
1448
            [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State',
1432
1449
            readonly=True, required=True),
 
1450
        'parent_id': fields.many2one('account.bank.statement.line',
 
1451
            'Parent'),
 
1452
        'link_partner_ok': fields.function(
 
1453
            _get_link_partner_ok, type='boolean',
 
1454
            string='Can link partner'),
1433
1455
        }
1434
1456
 
1435
1457
    _defaults = {
1450
1472
            res = wizard_obj.create_act_window(cr, uid, res_id, context=context)
1451
1473
        return res
1452
1474
 
 
1475
    def link_partner(self, cr, uid, ids, context=None):
 
1476
        """
 
1477
        Get the appropriate partner or fire a wizard to create
 
1478
        or link one
 
1479
        """
 
1480
        if not ids:
 
1481
            return False
 
1482
 
 
1483
        if isinstance(ids, (int, long)):
 
1484
            ids = [ids]
 
1485
                
 
1486
        # Check if the partner is already known but not shown
 
1487
        # because the screen was not refreshed yet
 
1488
        statement_line = self.browse(
 
1489
            cr, uid, ids[0], context=context)
 
1490
        if statement_line.partner_id:
 
1491
            return True
 
1492
 
 
1493
        # Reuse the bank's partner if any
 
1494
        if (statement_line.partner_bank_id and
 
1495
                statement_line.partner_bank_id.partner_id):
 
1496
            statement_line.write(
 
1497
                {'partner_id': statement_line.partner_bank_id.partner_id.id})
 
1498
            return True
 
1499
 
 
1500
        if (not statement_line.import_transaction_id or
 
1501
            not statement_line.import_transaction_id.remote_account):
 
1502
            raise osv.except_osv(
 
1503
                _("Error"),
 
1504
                _("No bank account available to link partner to"))
 
1505
            
 
1506
        # Check if the bank account was already been linked
 
1507
        # manually to another transaction
 
1508
        remote_account = statement_line.import_transaction_id.remote_account
 
1509
        source_line_ids = self.search(
 
1510
            cr, uid,
 
1511
            [('import_transaction_id.remote_account', '=', remote_account),
 
1512
             ('partner_bank_id.partner_id', '!=', False),
 
1513
             ], limit=1, context=context)
 
1514
        if source_line_ids:
 
1515
            source_line = self.browse(
 
1516
                cr, uid, source_line_ids[0], context=context)
 
1517
            target_line_ids = self.search(
 
1518
                cr, uid,
 
1519
                [('import_transaction_id.remote_account', '=', remote_account),
 
1520
                 ('partner_bank_id', '=', False),
 
1521
                 ('state', '=', 'draft')], context=context)
 
1522
            self.write(
 
1523
                cr, uid, target_line_ids,
 
1524
                {'partner_bank_id': source_line.partner_bank_id.id,
 
1525
                 'partner_id': source_line.partner_bank_id.partner_id.id,
 
1526
                 }, context=context)
 
1527
            return True
 
1528
                
 
1529
        # Or fire the wizard to link partner and account
 
1530
        wizard_obj = self.pool.get('banking.link_partner')
 
1531
        res_id = wizard_obj.create(
 
1532
            cr, uid, {'statement_line_id': ids[0]}, context=context)
 
1533
        return wizard_obj.create_act_window(cr, uid, res_id, context=context)
 
1534
 
1453
1535
    def _convert_currency(
1454
1536
        self, cr, uid, from_curr_id, to_curr_id, from_amount,
1455
1537
        round=False, date=None, context=None):
1570
1652
    def unlink(self, cr, uid, ids, context=None):
1571
1653
        """
1572
1654
        Don't allow deletion of a confirmed statement line
 
1655
        If this statement line comes from a split transaction, give the
 
1656
        amount back
1573
1657
        """
1574
1658
        if type(ids) is int:
1575
1659
            ids = [ids]
1579
1663
                    _('Confirmed Statement Line'),
1580
1664
                    _("You cannot delete a confirmed Statement Line"
1581
1665
                      ": '%s'") % line.name)
 
1666
            if line.parent_id:
 
1667
                line.parent_id.write(
 
1668
                        {
 
1669
                            'amount': line.parent_id.amount + line.amount,
 
1670
                        })
 
1671
                line.parent_id.refresh()
1582
1672
        return super(account_bank_statement_line, self).unlink(
1583
1673
            cr, uid, ids, context=context)
1584
1674
 
1618
1708
                        'import_transaction_id': res},
1619
1709
                    context=context)
1620
1710
 
1621
 
account_bank_statement_line()
 
1711
    def split_off(self, cr, uid, ids, amount, context=None):
 
1712
        """
 
1713
        Create a child statement line with amount, deduce that from this line,
 
1714
        change transactions accordingly
 
1715
        """
 
1716
        if context is None:
 
1717
            context = {}
 
1718
 
 
1719
        transaction_pool = self.pool.get('banking.import.transaction')
 
1720
    
 
1721
        child_statement_ids = []
 
1722
        for this in self.browse(cr, uid, ids, context):
 
1723
            transaction_data = transaction_pool.copy_data(
 
1724
                    cr, uid, this.import_transaction_id.id)
 
1725
            transaction_data['transferred_amount'] = amount
 
1726
            transaction_data['message'] = (
 
1727
                    (transaction_data['message'] or '') + _(' (split)'))
 
1728
            transaction_data['parent_id'] = this.import_transaction_id.id
 
1729
            transaction_id = transaction_pool.create(
 
1730
                    cr,
 
1731
                    uid,
 
1732
                    transaction_data,
 
1733
                    context=dict(
 
1734
                        context, transaction_no_duplicate_search=True))
 
1735
 
 
1736
            statement_line_data = self.copy_data(
 
1737
                    cr, uid, this.id)
 
1738
            statement_line_data['amount'] = amount
 
1739
            statement_line_data['name'] = (
 
1740
                    (statement_line_data['name'] or '') + _(' (split)'))
 
1741
            statement_line_data['import_transaction_id'] = transaction_id
 
1742
            statement_line_data['parent_id'] = this.id
 
1743
 
 
1744
            child_statement_ids.append(
 
1745
                    self.create(cr, uid, statement_line_data,
 
1746
                        context=context))
 
1747
            this.write({'amount': this.amount - amount})
 
1748
 
 
1749
        return child_statement_ids
1622
1750
 
1623
1751
 
1624
1752
class account_bank_statement(orm.Model):