Ejemplo n.º 1
0
    def get_from_label_and_partner_field(self, cr, uid, st_line, context=None):
        """Match the partner and the account based on the name field of the
        statement line and the table account.statement.label.
        If more than one statement label matched, raise the ErrorTooManylabel
        error.

        :param int line_id: id of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id': value,

            ...}
            """
        st_obj = self.pool['account.bank.statement']
        statement = st_obj.browse(cr,
                                  uid,
                                  st_line['statement_id'][0],
                                  context=context)
        res = {}
        if not context.get('label_memorizer'):
            context['label_memorizer'] = defaultdict(list)
            for line in statement.line_ids:
                cr.execute(
                    """
                    SELECT l.partner_id,
                           l.account_id
                    FROM account_statement_label as l,
                         account_bank_statement as s
                    LEFT JOIN
                         account_bank_statement_line as st_l
                         ON
                            st_l.statement_id = s.id
                    WHERE
                        (st_l.name ~* l.label OR st_l.ref ~* l.label)
                    AND
                        l.profile_id = s.profile_id
                    AND
                        st_l.id = %s
                        """, (line.id, ))
                for partner, account in cr.fetchall():
                    context['label_memorizer'][line.id].append({
                        'partner_id':
                        partner,
                        'account_id':
                        account
                    })
        if st_line['id'] in context['label_memorizer']:
            label_info = context['label_memorizer'][st_line['id']]
            if len(label_info) > 1:
                raise ErrorTooManyPartner(
                    _('Line named "%s" (Ref:%s) was matched by more than one '
                      'statement label.') % (st_line['name'], st_line['ref']))
            if label_info[0]['partner_id']:
                res['partner_id'] = label_info[0]['partner_id']
            res['account_id'] = label_info[0]['account_id']
        return res
Ejemplo n.º 2
0
    def get_from_santander_rules(self, cr, uid, st_line, context=None):
        """
        Match the partner based on several criteria extracted from reverse
        engineer of Banco Santander C43 files.

        If more than one partner is matched, raise the ErrorTooManyPartner
        error.
        :param dict st_line: read of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id' : value,
            ...}
        """
        partner_obj = self.pool['res.partner']
        st_line_obj = self.pool['account.bank.statement.line']
        conceptos = eval(st_line['name'])
        ids = []
        res = {}
        # Try to match from VAT included in concept complementary record #01
        if conceptos.get('01'):
            if conceptos['01'][1]:
                vat = conceptos['01'][1]
                ids = partner_obj.search(cr,
                                         uid, [('vat', 'ilike', vat)],
                                         context=context)
        if len(ids) > 1:
            from openerp.addons.account_statement_base_completion.statement \
                import ErrorTooManyPartner
            raise ErrorTooManyPartner(
                _('Line named "%s" (Ref: %s) was matched by more than '
                  'one partner for VAT number "%s".') %
                (st_line['name'], st_line['ref'], vat))
        if not ids:
            # Try to match from partner name
            if conceptos.get('01'):
                name = conceptos['01'][0]
                ids = partner_obj.search(cr,
                                         uid, [('name', 'ilike', name)],
                                         context=context)
        if ids:
            res['partner_id'] = ids[0]
        st_vals = st_line_obj.get_values_for_line(
            cr,
            uid,
            profile_id=st_line['profile_id'],
            master_account_id=st_line['master_account_id'],
            partner_id=res.get('partner_id', False),
            line_type=st_line['type'],
            amount=st_line['amount'] or 0.0,
            context=context)
        res.update(st_vals)
        return res
Ejemplo n.º 3
0
    def get_from_generic_c43_rules(self, cr, uid, st_line, context=None):
        """
        Match the partner based on invoice amount..

        If more than one partner is matched, raise the ErrorTooManyPartner
        error.
        :param dict st_line: read of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id' : value,
            ...}
        """
        st_line_obj = self.pool['account.bank.statement.line']
        invoice_obj = self.pool['account.invoice']
        ids = []
        res = {}
        # Finally, try to match from invoice amount
        if st_line['amount'] > 0.0:
            domain = [('type', 'in', ['out_invoice', 'in_refund'])]
        else:
            domain = [('type', 'in', ['in_invoice', 'out_refund'])]
        domain.append(('amount_total', '=', abs(st_line['amount'])))
        domain.append(('state', '=', 'open'))
        invoice_ids = invoice_obj.search(cr, uid, domain, context=context)
        if invoice_ids:
            invoices = invoice_obj.read(cr,
                                        uid,
                                        invoice_ids, ['partner_id'],
                                        context=context)
            ids = [x['partner_id'][0] for x in invoices]
            ids = list(set(ids))
        if len(ids) > 1:
            from openerp.addons.account_statement_base_completion.statement \
                import ErrorTooManyPartner
            raise ErrorTooManyPartner(
                _('Line named "%s" (Ref: %s) was matched by more than '
                  'one partner for invoice amount "%s".') %
                (st_line['name'], st_line['ref'], st_line['amount']))
        if ids:
            res['partner_id'] = ids[0]
        st_vals = st_line_obj.get_values_for_line(
            cr,
            uid,
            profile_id=st_line['profile_id'],
            master_account_id=st_line['master_account_id'],
            partner_id=res.get('partner_id', False),
            line_type=st_line['type'],
            amount=st_line['amount'] or 0.0,
            context=context)
        res.update(st_vals)
        return res
Ejemplo n.º 4
0
    def get_from_transaction_id_and_invoice(self,
                                            cr,
                                            uid,
                                            st_line,
                                            context=None):
        """
        Match the partner based on the transaction ID field of the invoice.
        Then, call the generic st_line method to complete other values.

        In that case, we always fullfill the reference of the line with the invoice name.

        :param dict st_line: read of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id' : value,
            ...}
            """
        st_obj = self.pool.get('account.bank.statement.line')
        res = {}
        invoice_obj = self.pool.get('account.invoice')
        invoice_id = invoice_obj.search(
            cr,
            uid, [('transaction_id', '=', st_line['transaction_id'])],
            context=context)
        if len(invoice_id) > 1:
            raise ErrorTooManyPartner(
                _('Line named "%s" (Ref:%s) was matched by more than '
                  'one partner.') % (st_line['name'], st_line['ref']))
        elif len(invoice_id) == 1:
            invoice = invoice_obj.browse(cr,
                                         uid,
                                         invoice_id[0],
                                         context=context)
            res['partner_id'] = invoice.partner_id.id
            # we want the move to have the same ref than the found
            # invoice's move, thus it will be easier to link them for the
            # accountants
            if invoice.move_id:
                res['ref'] = invoice.move_id.ref
            st_vals = st_obj.get_values_for_line(
                cr,
                uid,
                profile_id=st_line['profile_id'],
                master_account_id=st_line['master_account_id'],
                partner_id=res.get('partner_id', False),
                line_type=st_line['type'],
                amount=st_line['amount'] if st_line['amount'] else 0.0,
                context=context)
            res.update(st_vals)
        return res
Ejemplo n.º 5
0
    def get_from_partner_ref(self, cr, uid, id, st_line, context=None):
        """
        If line ref match a partner reference, update partner and account
        Then, call the generic st_line method to complete other values.
        :param dict st_line: read of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id' : value,
            ...}
        """
        ref = st_line['ref'].strip()
        res = {}
        partner_obj = self.pool.get('res.partner')
        partner_ids = partner_obj.search(cr,
                                         uid,
                                         [('ref', '=', str(int(ref[9:16]))),
                                          ('is_company', '=', False)],
                                         context=context)

        # Test that only one partner matches.
        partner = None
        if partner_ids:
            if len(partner_ids) == 1:
                partner = partner_obj.browse(cr,
                                             uid,
                                             partner_ids[0],
                                             context=context)
                partner = partner_obj._find_accounting_partner(partner)
                res['partner_id'] = partner.id
                res['account_id'] = partner.property_account_receivable.id
                # If we fall under this rule of completion, it means there is
                # no open invoice corresponding to the payment. We may need to
                # generate one depending on the payment type.
                res.update(
                    self._generate_invoice(cr,
                                           uid,
                                           st_line,
                                           partner,
                                           context=context))
            else:
                raise ErrorTooManyPartner(
                    ('Line named "%s" (Ref:%s) was matched by more '
                     'than one partner while looking on partners') %
                    (st_line['name'], st_line['ref']))
        return res
Ejemplo n.º 6
0
    def get_from_ref_and_so(self, cr, uid, st_line, context=None):
        """
        Match the partner based on the SO number and the reference of the
        statement line. Then, call the generic get_values_for_line method to
        complete other values. If more than one partner matched, raise the
        ErrorTooManyPartner error.

        :param int/long st_line: read of the concerned
        account.bank.statement.line

        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id': value,

            ...}
        """
        st_obj = self.pool.get('account.bank.statement.line')
        res = {}
        if st_line:
            so_obj = self.pool.get('sale.order')
            so_id = so_obj.search(cr,
                                  uid,
                                  [('name', '=', st_line['ref'])],
                                  context=context)
            if so_id:
                if so_id and len(so_id) == 1:
                    so = so_obj.browse(cr, uid, so_id[0], context=context)
                    res['partner_id'] = so.partner_id.id
                elif so_id and len(so_id) > 1:
                    raise ErrorTooManyPartner(
                        _('Line named "%s" (Ref:%s) was matched by more '
                          'than one partner while looking on SO by ref.') %
                        (st_line['name'], st_line['ref']))
                st_vals = st_obj.get_values_for_line(
                    cr,
                    uid,
                    profile_id=st_line['profile_id'],
                    master_account_id=st_line['master_account_id'],
                    partner_id=res.get('partner_id', False),
                    line_type='customer',
                    amount=st_line['amount'] if st_line['amount'] else 0.0,
                    context=context)
                res.update(st_vals)
        return res
Ejemplo n.º 7
0
 def get_from_bank_account(self, cr, uid, st_line, context=None):
     """
     Match the partner based on the partner account number field
     Then, call the generic st_line method to complete other values.
     :param dict st_line: read of the concerned account.bank.statement.line
     :return:
         A dict of value that can be passed directly to the write method of
         the statement line or {}
        {'partner_id': value,
         'account_id' : value,
         ...}
     """
     partner_acc_number = st_line['partner_acc_number']
     if not partner_acc_number:
         return {}
     st_obj = self.pool['account.bank.statement.line']
     res = {}
     res_bank_obj = self.pool['res.partner.bank']
     ids = res_bank_obj.search_by_acc_number(cr,
                                             uid,
                                             partner_acc_number,
                                             context=context)
     if len(ids) > 1:
         raise ErrorTooManyPartner(_('Line named "%s" (Ref:%s) was matched '
                                     'by more than one partner for account '
                                     'number "%s".') %
                                   (st_line['name'],
                                    st_line['ref'],
                                    partner_acc_number))
     if len(ids) == 1:
         partner = res_bank_obj.browse(cr,
                                       uid,
                                       ids[0],
                                       context=context).partner_id
         res['partner_id'] = partner.id
         st_vals = st_obj.get_values_for_line(
             cr, uid, profile_id=st_line['profile_id'],
             master_account_id=st_line['master_account_id'],
             partner_id=res.get('partner_id', False),
             line_type=st_line['type'],
             amount=st_line['amount'] if st_line['amount'] else 0.0,
             context=context)
         res.update(st_vals)
     return res
 def get_from_transaction_id_and_so(self, cr, uid, st_line, context=None):
     """
     Match the partner based on the transaction ID field of the SO.
     Then, call the generic st_line method to complete other values.
     In that case, we always fullfill the reference of the line with the SO
     name.
     :param dict st_line: read of the concerned account.bank.statement.line
     :return:
         A dict of value that can be passed directly to the write method of
         the statement line or {}
        {'partner_id': value,
         'account_id' : value,
         ...}
         """
     st_obj = self.pool['account.bank.statement.line']
     res = {}
     so_obj = self.pool['sale.order']
     so_id = so_obj.search(
         cr,
         uid, [('transaction_id', '=', st_line['transaction_id'])],
         context=context)
     if len(so_id) > 1:
         raise ErrorTooManyPartner(
             _('Line named "%s" (Ref:%s) was matched by more than '
               'one partner.') % (st_line['name'], st_line['ref']))
     if len(so_id) == 1:
         so = so_obj.browse(cr, uid, so_id[0], context=context)
         res['partner_id'] = so.partner_id.id
         res['ref'] = so.name
         st_vals = st_obj.get_values_for_line(
             cr,
             uid,
             profile_id=st_line['profile_id'],
             master_account_id=st_line['master_account_id'],
             partner_id=res.get('partner_id', False),
             line_type=st_line['type'],
             amount=st_line['amount'] if st_line['amount'] else 0.0,
             context=context)
         res.update(st_vals)
     return res
Ejemplo n.º 9
0
    def get_from_amount(self, cr, uid, id, st_line, context=None):
        """ If line amount match an open supplier invoice,
            update partner and account. """
        amount = float(st_line['amount'])
        res = {}
        # We check only for debit entries
        if amount < 0:
            invoice_obj = self.pool.get('account.invoice')
            invoice_ids = invoice_obj.search(
                cr,
                uid, [('type', '=', 'in_invoice'), ('state', '=', 'open'),
                      ('amount_total', '=', abs(amount))],
                context=context)
            res = {}
            if invoice_ids:
                if len(invoice_ids) == 1:
                    invoice = invoice_obj.browse(cr,
                                                 uid,
                                                 invoice_ids[0],
                                                 context=context)
                    res['partner_id'] = invoice.partner_id.id
                    res['account_id'] = invoice.account_id.id
                else:
                    invoices = invoice_obj.browse(cr,
                                                  uid,
                                                  invoice_ids,
                                                  context=context)
                    partner_id = invoices[0].partner_id.id
                    for invoice in invoices:
                        if invoice.partner_id.id != partner_id:
                            raise ErrorTooManyPartner(
                                ('Line named "%s" (Ref:%s) was matched by '
                                 'more than one invoice while looking on open'
                                 ' supplier invoices') %
                                (st_line['name'], st_line['ref']))
                    res['partner_id'] = partner_id
                    res['account_id'] = invoices[0].account_id.id

        return res
Ejemplo n.º 10
0
    def get_from_bvr_reference_and_invoice(self,
                                           cr,
                                           uid,
                                           st_line,
                                           context=None):
        """
        Match the partner based on the BVR reference field of the invoice.
        Then, call the generic st_line method to complete other values.

        In that case, we always fulfill the reference of the line with
        the invoice name.

        :param dict st_line: read of the concerned account.bank.statement.line
        :return:
            A dict of value that can be passed directly to the write method of
            the statement line or {}
           {'partner_id': value,
            'account_id' : value,
            ...}
            """
        st_obj = self.pool.get('account.bank.statement.line')
        res = {}
        invoice_obj = self.pool.get('account.invoice')
        # For customer invoices, search in bvr_reference that is as list
        # of references separated by semicolons and formatted with
        # spaces inside them.
        # For supplier invoices, search in 'reference'
        query = ("SELECT id FROM account_invoice "
                 "WHERE company_id = %s "
                 "AND (%s = ANY (string_to_array( "
                 "                 replace(bvr_reference, ' ', ''), "
                 "               ';')) "
                 "     AND type IN ('out_invoice', 'out_refund') "
                 "     OR type IN ('in_invoice', 'in_refund') "
                 "     AND reference_type = 'bvr' AND reference = %s "
                 ")")
        cr.execute(query, (st_line['company_id'][0], st_line['transaction_id'],
                           st_line['transaction_id']))
        rows = cr.fetchall()
        invoice_ids = [row[0] for row in rows]
        if len(invoice_ids) > 1:
            raise ErrorTooManyPartner(
                _('Line named "%s" (Ref:%s) was matched by more than '
                  'one partner.') % (st_line['name'], st_line['ref']))
        elif len(invoice_ids) == 1:
            invoice = invoice_obj.browse(cr,
                                         uid,
                                         invoice_ids[0],
                                         context=context)
            res['partner_id'] = invoice.partner_id.id
            # we want the move to have the same ref than the found
            # invoice's move, thus it will be easier to link them for the
            # accountants
            if invoice.move_id:
                res['ref'] = invoice.move_id.ref
            st_vals = st_obj.get_values_for_line(
                cr,
                uid,
                profile_id=st_line['profile_id'],
                master_account_id=st_line['master_account_id'],
                partner_id=res.get('partner_id', False),
                line_type=st_line['type'],
                amount=st_line['amount'] if st_line['amount'] else 0.0,
                context=context)
            res.update(st_vals)
        return res