<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/>.
#
##############################################################################
# Many thanks to our contributors
#
# <NAME> (KNdati): lenghty discussions, bugreports and bugfixes
# <NAME> (Therp): bugreport and bugfix
# CLEARCORP S.A: Customization and migration to OpenERP 7.0
'''
This module contains the business logic of the wizard account_banking_import.
The parsing is done in the parser modules. Every parser module is required to
use parser.models as a mean of communication with the business logic.
'''
from openerp.osv import osv, fields
import time
import netsvc
import base64
import datetime
from openerp.tools import config
from openerp.tools.translate import _
from account_banking_ccorp.parsers import models
from account_banking_ccorp.parsers.convert import *
from account_banking_ccorp.struct import struct
from account_banking_ccorp import sepa
from banktools import *

import decimal_precision as dp
import re

bt = models.mem_bank_transaction

# This variable is used to match supplier invoices with an invoice date after
# the real payment date. This can occur with online transactions (web shops).
payment_window = datetime.timedelta(days=10)

def parser_types(*args, **kwargs):
    '''Delay evaluation of parser types until start of wizard, to allow
       depending modules to initialize and add their parsers to the list
    '''
    return models.parser_type.get_parser_types()

class bankImportLine(osv.TransientModel):
    _name = 'account.banking.ccorp.bank.import.line'
    
    _description = 'Bank import lines'
    
    _columns = {
        'name': fields.char('Name', size=64),
        'date': fields.date('Date', readonly=True),
        'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
        'statement_line_id': fields.many2one('account.bank.statement.line',
                                             'Resulting statement line',
                                             readonly=True),
        'type': fields.selection([('supplier','Supplier'),
                                  ('customer','Customer'),
                                  ('general','General')],
                                 'Type', required=True),
        'partner_id': fields.many2one('res.partner', 'Partner'),
        'statement_id': fields.many2one('account.bank.statement', 'Statement',
                                        select=True, required=True, ondelete='cascade'),
        'ref': fields.char('Reference', size=32),
        'note': fields.text('Notes'),
        'period_id': fields.many2one('account.period', 'Period'),
        'currency': fields.many2one('res.currency', 'Currency'),
        'banking_import_id': fields.many2one('account.banking.ccorp.bank.import.wizard', 'Bank import',
                                             readonly=True, ondelete='cascade'),
        'reconcile_id': fields.many2one('account.move.reconcile', 'Reconciliaton'),
        'account_id': fields.many2one('account.account', 'Account'),
        'invoice_ids': fields.many2many('account.invoice', 'banking_import_line_invoice_rel',
                                        'line_id', 'invoice_id'),
        'payment_order_id': fields.many2one('payment.order', 'Payment order'),
        'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'),
        'transaction_type': fields.selection([
                                              # TODO: payment terminal etc...
                                              ('invoice', 'Invoice payment'),
                                              ('payment_order_line', 'Payment from a payment order'),
                                              ('payment_order', 'Aggregate payment order'),
                                              ('storno', 'Canceled debit order'),
                                              ('bank_costs', 'Bank costs'),
                                              ('unknown', 'Unknown'),
                                              ], 'Transaction type'),
        'duplicate': fields.boolean('Duplicate'),
        }

class bankImportWizard(osv.TransientModel):
    _name = 'account.banking.ccorp.bank.import.wizard'

    def import_statements_file(self, cr, uid, ids, context):
        '''
        Import bank statements / bank transactions file.
        This method is a wrapper for the business logic on the transaction.
        The parser modules represent the decoding logic.
        '''
        #Get the wizard record and binary file
        bank_import_wizard = self.browse(cr, uid, ids, context)[0]
        #Get the binary file without encoding
        statements_file = bank_import_wizard.file

        user_obj = self.pool.get('res.users')
        company_obj = self.pool.get('res.company')
        statement_obj = self.pool.get('account.bank.statement')
        statement_file_obj = self.pool.get('account.banking.ccorp.imported.file')
        import_transaction_obj = self.pool.get('account.banking.ccorp.bank.import.transaction')
        period_obj = self.pool.get('account.period')
        # Get the parser to parse the file according to
        #the selected account
        parser_code = bank_import_wizard.parser
        parser = models.create_parser(parser_code)
        if not parser:
            raise osv.except_osv(
                _('ERROR!'),
                _('Unable to import parser %(parser)s. Parser class not found.') %
                {'parser': parser_code}
            )
        # Get the user and company
        #Fix the problem with permission of the user
        user = user_obj.browse(cr, uid, uid, context)
        company = bank_import_wizard.company
        '''
            PASS THE PARAMETERS TO PARSER. IT'S MORE EASY AND CLEAR PASS FROM HERE.
            The object bank_import_wizard have all the fields in the wizard.
            For BAC and BCR parsers it's not needed.
        '''
        #account_number used if the file haven't one.
        #Really needed?
        account_number = self.extract_number(bank_import_wizard.account_bank.acc_number)
        #local_currency extracted from account_bank
        if bank_import_wizard.account_bank.currency_id:
            local_currency = bank_import_wizard.account_bank.currency_id.name
        else:
            local_currency = 'CRC'
        #TODO: Fields used only by the davivienda's parser, must be removed and added
        #in the custom parser's module
        date_from_str = bank_import_wizard.date_from
        date_to_str = bank_import_wizard.date_to
        #TODO: Fields used only by the BNCR's parser, must be removed and added
        #in the custom parser's module
        #In BNCR's parser the file does not have the initial balance, <commit_msg>[IMP] - account_banking_ccorp: Currency code from company.<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/>.
#
##############################################################################
# Many thanks to our contributors
#
# <NAME> (KNdati): lenghty discussions, bugreports and bugfixes
# <NAME> (Therp): bugreport and bugfix
# CLEARCORP S.A: Customization and migration to OpenERP 7.0
'''
This module contains the business logic of the wizard account_banking_import.
The parsing is done in the parser modules. Every parser module is required to
use parser.models as a mean of communication with the business logic.
'''
from openerp.osv import osv, fields
import time
import netsvc
import base64
import datetime
from openerp.tools import config
from openerp.tools.translate import _
from account_banking_ccorp.parsers import models
from account_banking_ccorp.parsers.convert import *
from account_banking_ccorp.struct import struct
from account_banking_ccorp import sepa
from banktools import *

import decimal_precision as dp
import re

bt = models.mem_bank_transaction

# This variable is used to match supplier invoices with an invoice date after
# the real payment date. This can occur with online transactions (web shops).
payment_window = datetime.timedelta(days=10)

def parser_types(*args, **kwargs):
    '''Delay evaluation of parser types until start of wizard, to allow
       depending modules to initialize and add their parsers to the list
    '''
    return models.parser_type.get_parser_types()

class bankImportLine(osv.TransientModel):
    _name = 'account.banking.ccorp.bank.import.line'
    
    _description = 'Bank import lines'
    
    _columns = {
        'name': fields.char('Name', size=64),
        'date': fields.date('Date', readonly=True),
        'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
        'statement_line_id': fields.many2one('account.bank.statement.line',
                                             'Resulting statement line',
                                             readonly=True),
        'type': fields.selection([('supplier','Supplier'),
                                  ('customer','Customer'),
                                  ('general','General')],
                                 'Type', required=True),
        'partner_id': fields.many2one('res.partner', 'Partner'),
        'statement_id': fields.many2one('account.bank.statement', 'Statement',
                                        select=True, required=True, ondelete='cascade'),
        'ref': fields.char('Reference', size=32),
        'note': fields.text('Notes'),
        'period_id': fields.many2one('account.period', 'Period'),
        'currency': fields.many2one('res.currency', 'Currency'),
        'banking_import_id': fields.many2one('account.banking.ccorp.bank.import.wizard', 'Bank import',
                                             readonly=True, ondelete='cascade'),
        'reconcile_id': fields.many2one('account.move.reconcile', 'Reconciliaton'),
        'account_id': fields.many2one('account.account', 'Account'),
        'invoice_ids': fields.many2many('account.invoice', 'banking_import_line_invoice_rel',
                                        'line_id', 'invoice_id'),
        'payment_order_id': fields.many2one('payment.order', 'Payment order'),
        'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account'),
        'transaction_type': fields.selection([
                                              # TODO: payment terminal etc...
                                              ('invoice', 'Invoice payment'),
                                              ('payment_order_line', 'Payment from a payment order'),
                                              ('payment_order', 'Aggregate payment order'),
                                              ('storno', 'Canceled debit order'),
                                              ('bank_costs', 'Bank costs'),
                                              ('unknown', 'Unknown'),
                                              ], 'Transaction type'),
        'duplicate': fields.boolean('Duplicate'),
        }

class bankImportWizard(osv.TransientModel):
    _name = 'account.banking.ccorp.bank.import.wizard'

    def import_statements_file(self, cr, uid, ids, context):
        '''
        Import bank statements / bank transactions file.
        This method is a wrapper for the business logic on the transaction.
        The parser modules represent the decoding logic.
        '''
        #Get the wizard record and binary file
        bank_import_wizard = self.browse(cr, uid, ids, context)[0]
        #Get the binary file without encoding
        statements_file = bank_import_wizard.file

        user_obj = self.pool.get('res.users')
        company_obj = self.pool.get('res.company')
        statement_obj = self.pool.get('account.bank.statement')
        statement_file_obj = self.pool.get('account.banking.ccorp.imported.file')
        import_transaction_obj = self.pool.get('account.banking.ccorp.bank.import.transaction')
        period_obj = self.pool.get('account.period')
        # Get the parser to parse the file according to
        #the selected account
        parser_code = bank_import_wizard.parser
        parser = models.create_parser(parser_code)
        if not parser:
            raise osv.except_osv(
                _('ERROR!'),
                _('Unable to import parser %(parser)s. Parser class not found.') %
                {'parser': parser_code}
            )
        # Get the user and company
        #Fix the problem with permission of the user
        user = user_obj.browse(cr, uid, uid, context)
        company = bank_import_wizard.company
        '''
            PASS THE PARAMETERS TO PARSER. IT'S MORE EASY AND CLEAR PASS FROM HERE.
            The object bank_import_wizard have all the fields in the wizard.
            For BAC and BCR parsers it's not needed.
        '''
        #account_number used if the file haven't one.
        #Really needed?
        account_number = self.extract_number(bank_import_wizard.account_bank.acc_number)
        #local_currency extracted from account_bank
        if bank_import_wizard.account_bank.currency_id:
            local_currency = bank_import_wizard.account_bank.currency_id.name
        else:
            local_currency = company.currency_id.name
        #TODO: Fields used only by the davivienda's parser, must be removed and added
        #in the custom parser's module
        date_from_str = bank_import_wizard.date_from
        date_to_str = bank_import_wizard.date_to
        #TODO: Fields used only by the BNCR's parser, must be removed and added
        #in the custom parser's module
        #In BNCR's parser the file does not have the initial balance, 
{'fraction_non_alphanumeric': 0.11177552897884084, 'fraction_numerical': 0.0036798528058877645, 'mean_word_length': 2.4408772326475243, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 54, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1085776', 'n_tokens_mistral': 3955, 'n_tokens_neox': 3830, 'n_words': 1209}