<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
#    All Rights Reserved
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import sys
import datetime
import re
from tools.translate import _
from account_banking.parsers import convert
from account_banking import sepa
from account_banking.struct import struct
import unicodedata

__all__ = [
    'get_period', 
    'get_bank_accounts',
    'get_or_create_partner',
    'get_company_bank_account',
    'create_bank_account',
]

def get_period(pool, cursor, uid, date, company, log):
    '''
    Get a suitable period for the given date range and the given company.
    '''
    fiscalyear_obj = pool.get('account.fiscalyear')
    period_obj = pool.get('account.period')
    if not date:
        date = convert.date2str(datetime.datetime.today())

    search_date = convert.date2str(date)
    fiscalyear_ids = fiscalyear_obj.search(cursor, uid, [
        ('date_start','<=', search_date), ('date_stop','>=', search_date),
        ('state','=','draft'), ('company_id','=',company.id)
    ])
    if not fiscalyear_ids:
        fiscalyear_ids = fiscalyear_obj.search(cursor, uid, [
            ('date_start','<=',search_date), ('date_stop','>=',search_date),
            ('state','=','draft'), ('company_id','=',None)
        ])
    if not fiscalyear_ids:
        log.append(
            _('No suitable fiscal year found for date %(date)s and company %(company_name)s')
            % dict(company_name=company.name, date=date)
        )
        return False
    elif len(fiscalyear_ids) > 1:
        log.append(
            _('Multiple overlapping fiscal years found for date %(date)s and company %(company_name)s')
            % dict(company_name=company.name, date=date)
        )
        return False

    fiscalyear_id = fiscalyear_ids[0]
    period_ids = period_obj.search(cursor, uid, [
        ('date_start','<=',search_date), ('date_stop','>=',search_date),
        ('fiscalyear_id','=',fiscalyear_id), ('state','=','draft'),
        ('special', '=', False),
    ])
    if not period_ids:
        log.append(_('No suitable period found for date %(date)s and company %(company_name)s')
                   % dict(company_name=company.name, date=date)
        )
        return False
    if len(period_ids) != 1:
        log.append(_('Multiple overlapping periods for date %(date)s and company %(company_name)s')
                   % dict(company_name=company.name, date=date)
        )
        return False
    return period_ids[0]

def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False):
    '''
    Get the bank account with account number account_number
    '''
    # No need to search for nothing
    if not account_number:
        return False

    partner_bank_obj = pool.get('res.partner.bank')
    bank_account_ids = partner_bank_obj.search(cursor, uid, [
        ('acc_number', '=', account_number)
    ])
    if not bank_account_ids:
        # SR 2012-02-19 does the search() override in res_partner_bank
        # provides this result on the previous query?
        bank_account_ids = partner_bank_obj.search(cursor, uid, [
            ('acc_number_domestic', '=', account_number)
        ])
    if not bank_account_ids:
        if not fail:
            log.append(
                _('Bank account %(account_no)s was not found in the database')
                % dict(account_no=account_number)
            )
        return False
    return partner_bank_obj.browse(cursor, uid, bank_account_ids)

def _has_attr(obj, attr):
    # Needed for dangling addresses and a weird exception scheme in
    # OpenERP's orm.
    try:
        return bool(getattr(obj, attr))
    except KeyError:
        return False

def get_or_create_partner(pool, cursor, uid, name, address, postal_code, city,
                          country_code, log):
    '''
    Get or create the partner belonging to the account holders name <name>
    '''
    partner_obj = pool.get('res.partner')
    partner_ids = partner_obj.search(cursor, uid, [('name', 'ilike', name)])
    if not partner_ids:
        # Try brute search on address and then match reverse
        address_obj = pool.get('res.partner.address')
        filter = [('partner_id', '<>', None)]
        if country_code:
            country_obj = pool.get('res.country')
            country_ids = country_obj.search(
                cursor, uid, [('code','=',country_code.upper())]
            )
            country_id = country_ids and country_ids[0] or False
            filter.append(('country_id', '=', country_id))
        # disable for now. Apparently, address is an array of lines.
        if address and False:
            if len(address) >= 1:
                filter.append(('street', 'ilike', address[0]))
            if len(address) > 1:
                filter.append(('street2', 'ilike', address[1]))
        if city:
            filter.append(('city', 'ilike', city))
        if postal_code:
            filter.append(('zip', 'ilike', postal_code))
        address_ids = address_obj.search(cursor, uid, filter)
        key = name.lower()

        # Make sure to get a unique list
        partner_ids = list(set([x.partner_id.id
                       for x in address_obj.browse(cursor, uid, address_ids)
                       # Beware for dangling addresses
                       if _has_attr(x.partner_id, 'name') and
                          x.partner_id.name.lower() in key
                      ]))
    if not partner_ids:
        if (not country_code) or not country_id:
            user = pool.get('res.user').browse(cursor, uid, uid)
            country_id = (
                user.company_id.partner_id.country and 
                user.company_id.partner_id.country.id or
                False
            )
        partner_id = partner_obj.create(cursor, uid, dict(
            name=name, active=True, comment='Generated from Bank Statements Import',
            address=[(0,0,{
                'street': address and address[0] or '',
                'street2': len(address) > 1 and address[1] or '',
                'city': city,
                'zip': postal_code or '',
                'country_id': country_id,
            })],
        ))
    elif len(partner_ids) > 1:
        log.append(
            _('More then one possible match found for partner with name %(name)s')
            % {'name': name}
        )
        return False
    else:<commit_msg>[FIX] Import fails if two partners exist with same name as on the statement<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
#    All Rights Reserved
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import sys
import datetime
import re
from tools.translate import _
from account_banking.parsers import convert
from account_banking import sepa
from account_banking.struct import struct
import unicodedata

__all__ = [
    'get_period', 
    'get_bank_accounts',
    'get_or_create_partner',
    'get_company_bank_account',
    'create_bank_account',
]

def get_period(pool, cursor, uid, date, company, log):
    '''
    Get a suitable period for the given date range and the given company.
    '''
    fiscalyear_obj = pool.get('account.fiscalyear')
    period_obj = pool.get('account.period')
    if not date:
        date = convert.date2str(datetime.datetime.today())

    search_date = convert.date2str(date)
    fiscalyear_ids = fiscalyear_obj.search(cursor, uid, [
        ('date_start','<=', search_date), ('date_stop','>=', search_date),
        ('state','=','draft'), ('company_id','=',company.id)
    ])
    if not fiscalyear_ids:
        fiscalyear_ids = fiscalyear_obj.search(cursor, uid, [
            ('date_start','<=',search_date), ('date_stop','>=',search_date),
            ('state','=','draft'), ('company_id','=',None)
        ])
    if not fiscalyear_ids:
        log.append(
            _('No suitable fiscal year found for date %(date)s and company %(company_name)s')
            % dict(company_name=company.name, date=date)
        )
        return False
    elif len(fiscalyear_ids) > 1:
        log.append(
            _('Multiple overlapping fiscal years found for date %(date)s and company %(company_name)s')
            % dict(company_name=company.name, date=date)
        )
        return False

    fiscalyear_id = fiscalyear_ids[0]
    period_ids = period_obj.search(cursor, uid, [
        ('date_start','<=',search_date), ('date_stop','>=',search_date),
        ('fiscalyear_id','=',fiscalyear_id), ('state','=','draft'),
        ('special', '=', False),
    ])
    if not period_ids:
        log.append(_('No suitable period found for date %(date)s and company %(company_name)s')
                   % dict(company_name=company.name, date=date)
        )
        return False
    if len(period_ids) != 1:
        log.append(_('Multiple overlapping periods for date %(date)s and company %(company_name)s')
                   % dict(company_name=company.name, date=date)
        )
        return False
    return period_ids[0]

def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False):
    '''
    Get the bank account with account number account_number
    '''
    # No need to search for nothing
    if not account_number:
        return False

    partner_bank_obj = pool.get('res.partner.bank')
    bank_account_ids = partner_bank_obj.search(cursor, uid, [
        ('acc_number', '=', account_number)
    ])
    if not bank_account_ids:
        # SR 2012-02-19 does the search() override in res_partner_bank
        # provides this result on the previous query?
        bank_account_ids = partner_bank_obj.search(cursor, uid, [
            ('acc_number_domestic', '=', account_number)
        ])
    if not bank_account_ids:
        if not fail:
            log.append(
                _('Bank account %(account_no)s was not found in the database')
                % dict(account_no=account_number)
            )
        return False
    return partner_bank_obj.browse(cursor, uid, bank_account_ids)

def _has_attr(obj, attr):
    # Needed for dangling addresses and a weird exception scheme in
    # OpenERP's orm.
    try:
        return bool(getattr(obj, attr))
    except KeyError:
        return False

def get_or_create_partner(pool, cursor, uid, name, address, postal_code, city,
                          country_code, log):
    '''
    Get or create the partner belonging to the account holders name <name>

    If multiple partners are found with the same name, select the first and
    add a warning to the import log.
    '''
    partner_obj = pool.get('res.partner')
    partner_ids = partner_obj.search(cursor, uid, [('name', 'ilike', name)])
    if not partner_ids:
        # Try brute search on address and then match reverse
        address_obj = pool.get('res.partner.address')
        filter = [('partner_id', '<>', None)]
        if country_code:
            country_obj = pool.get('res.country')
            country_ids = country_obj.search(
                cursor, uid, [('code','=',country_code.upper())]
            )
            country_id = country_ids and country_ids[0] or False
            filter.append(('country_id', '=', country_id))
        # disable for now. Apparently, address is an array of lines.
        if address and False:
            if len(address) >= 1:
                filter.append(('street', 'ilike', address[0]))
            if len(address) > 1:
                filter.append(('street2', 'ilike', address[1]))
        if city:
            filter.append(('city', 'ilike', city))
        if postal_code:
            filter.append(('zip', 'ilike', postal_code))
        address_ids = address_obj.search(cursor, uid, filter)
        key = name.lower()

        # Make sure to get a unique list
        partner_ids = list(set([x.partner_id.id
                       for x in address_obj.browse(cursor, uid, address_ids)
                       # Beware for dangling addresses
                       if _has_attr(x.partner_id, 'name') and
                          x.partner_id.name.lower() in key
                      ]))
    if not partner_ids:
        if (not country_code) or not country_id:
            user = pool.get('res.user').browse(cursor, uid, uid)
            country_id = (
                user.company_id.partner_id.country and 
                user.company_id.partner_id.country.id or
                False
            )
        partner_id = partner_obj.create(cursor, uid, dict(
            name=name, active=True, comment='Generated from Bank Statements Import',
            address=[(0,0,{
                'street': address and address[0] or '',
                'street2': len(address) > 1 and address[1] or '',
                'city': city,
                'zip': postal_code or '',
                'country_id': country_id,
            })],
        ))
    else:
        if len(partner_ids) > 1:
            log.append(
                _('More than one possible match found for partner with name %(name)s')
                % {'name': name}
                )
{'fraction_non_alphanumeric': 0.13191169434761807, 'fraction_numerical': 0.004510969858519582, 'mean_word_length': 2.43796992481203, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7468130', 'n_tokens_mistral': 4268, 'n_tokens_neox': 4152, 'n_words': 1184}