def __init__(self, values): self.__dict__.update(dict(zip(self.attrnames, values))) #self.local_account = self.clean_account(self.local_account) #self.remote_account = self.clean_account(self.remote_account) self.start_balance = float(self.start_balance) self.transferred_amount = float(self.transferred_amount) self.execution_date = str2date(self.execution_date, '%d-%m-%Y') self.effective_date = str2date(self.effective_date, '%d-%m-%Y')
def __init__(self, values): ''' Initialize own dict with attributes and coerce values to right type ''' self.__dict__.update(dict(zip(self.attrnames, values))) #self.local_account = self.clean_account(self.local_account) #self.remote_account = self.clean_account(self.remote_account) self.start_balance = float(self.start_balance) self.transferred_amount = float(self.transferred_amount) self.execution_date = str2date(self.execution_date, '%d-%m-%Y') self.effective_date = str2date(self.effective_date, '%d-%m-%Y')
def __init__(self, values, subno): ''' Initialize own dict with attributes and coerce values to right type ''' if len(self.attrnames) != len(values): raise ValueError( _('Invalid transaction line: expected %d columns, found %d') % (len(self.attrnames), len(values))) self.__dict__.update(dict(zip(self.attrnames, values))) self.start_balance = float(self.start_balance) self.transferred_amount = float(self.transferred_amount) self.execution_date = str2date(self.execution_date, '%d-%m-%Y') self.value_date = str2date(self.value_date, '%d-%m-%Y') self.id = str(subno).zfill(4)
def __init__(self, values, subno): ''' Initialize own dict with attributes and coerce values to right type ''' if len(self.attrnames) != len(values): raise ValueError, \ _('Invalid transaction line: expected %d columns, found %d') \ % (len(self.attrnames), len(values)) self.__dict__.update(dict(zip(self.attrnames, values))) #self.local_account = self.clean_account(self.local_account) #self.remote_account = self.clean_account(self.remote_account) self.start_balance = float(self.start_balance) self.transferred_amount = float(self.transferred_amount) self.execution_date = str2date(self.execution_date, '%d-%m-%Y') self.value_date = str2date(self.value_date, '%d-%m-%Y') self.id = str(subno).zfill(4)
def __init__(self, msg, *args, **kwargs): super(statement, self).__init__(*args, **kwargs) self.id = msg.statement_id self.local_account = msg.local_account self.date = str2date(msg.date, '%d-%m-%Y') self.start_balance = self.end_balance = msg.start_balance self.import_transaction(msg)
def __init__(self, msg, *args, **kwargs): ''' Set decent start values based on first transaction read ''' super(statement, self).__init__(*args, **kwargs) self.id = msg.statement_id self.local_account = msg.local_account self.date = str2date(msg.date, '%d-%m-%Y') self.start_balance = self.end_balance = msg.start_balance self.import_transaction(msg)
def __init__(self, values, subno): ''' Initialize own dict with attributes and coerce values to right type ''' if (len(self.attrnames) != len(values) and len(self.attrnames) != len(values)+1) : raise ValueError, \ _('Invalid transaction line: expected %d columns, found ' '%d') % (len(self.attrnames), len(values)) ''' Strip all values except the blob ''' for (key, val) in zip(self.attrnames, values): self.__dict__[key] = key == 'blob' and val or val.strip() # for lack of a standardized locale function to parse amounts self.local_account = self.local_account.zfill(10) self.balance = float(self.balance.replace(',', '.')) self.transferred_amount = float(self.transferred_amount.replace(',', '.')) self.execution_date = str2date(self.execution_date, '%d/%m/%Y') self.value_date = str2date(self.effective_date, '%d/%m/%Y') self.effective_date = str2date(self.effective_date, '%d/%m/%Y') self.id = str(subno).zfill(4)
def __init__(self, values, subno): ''' Initialize own dict with attributes and coerce values to right type ''' if len(self.attrnames) != len(values): raise ValueError( _('Invalid transaction line: expected %d columns, found %d') % (len(self.attrnames), len(values))) self.__dict__.update(dict(zip(self.attrnames, values))) # for lack of a standardized locale function to parse amounts self.transferred_amount = float( re.sub(',', '.', re.sub('\.', '', self.transferred_amount))) if self.debcred == 'Debet': self.transferred_amount = -self.transferred_amount self.execution_date = str2date(self.date, '%d-%m-%Y') self.value_date = str2date(self.date, '%d-%m-%Y') self.statement_id = '' self.id = str(subno).zfill(4) # Normalize basic account numbers self.remote_account = self.remote_account.replace('.', '').zfill(10) self.local_account = self.local_account.replace('.', '').zfill(10)
def __init__(self, values): """ Initialize own dict with attributes and coerce values to right type """ if len(self.attrnames) != len(values): raise ValueError, _("Invalid transaction line: expected %d columns, found %d") % ( len(self.attrnames), len(values), ) self.__dict__.update(dict(zip(self.attrnames, values))) self.date = str2date(self.date, "%Y%m%d") if self.direction == "A": self.transferred_amount = -float(self.transferred_amount) # payment batch done via clieop if ( self.transfer_type == "VZ" and (not self.remote_account or self.remote_account == "0") and (not self.message or re.match("^\s*$", self.message)) and self.remote_owner.startswith("TOTAAL ") ): self.transfer_type = "PB" self.message = self.remote_owner self.remove_owner = False # payment batch done via sepa if ( self.transfer_type == "VZ" and not self.remote_account and not self.remote_owner and re.match("^Verzamel Eurobetaling .* TOTAAL \d+ POSTEN\s*$", self.message) ): self.transfer_type = "PB" else: self.transferred_amount = float(self.transferred_amount) self.local_account = self.local_account.zfill(10) if self.transfer_type != "DV": self.remote_account = self.remote_account.zfill(10) else: self.remote_account = False self.execution_date = self.value_date = self.date self.remote_owner = self.remote_owner.rstrip() self.message = self.message.rstrip() self.genid()
def __init__(self, values): ''' Initialize own dict with attributes and coerce values to right type ''' if len(self.attrnames) != len(values): raise ValueError, \ _('Invalid transaction line: expected %d columns, found %d') \ % (len(self.attrnames), len(values)) self.__dict__.update(dict(zip(self.attrnames, values))) self.date = str2date(self.date, '%Y%m%d') if self.direction == 'A': self.transferred_amount = -float(self.transferred_amount) #payment batch done via clieop if (self.transfer_type == 'VZ' and (not self.remote_account or self.remote_account == '0') and (not self.message or re.match('^\s*$', self.message)) and self.remote_owner.startswith('TOTAAL ')): self.transfer_type = 'PB' self.message = self.remote_owner self.remove_owner = False #payment batch done via sepa if self.transfer_type == 'VZ'\ and not self.remote_account\ and not self.remote_owner\ and re.match( '^Verzamel Eurobetaling .* TOTAAL \d+ POSTEN\s*$', self.message): self.transfer_type = 'PB' else: self.transferred_amount = float(self.transferred_amount) self.local_account = self.local_account.zfill(10) if self.transfer_type != 'DV': self.remote_account = self.remote_account.zfill(10) else: self.remote_account = False self.execution_date = self.value_date = self.date self.remote_owner = self.remote_owner.rstrip() self.message = self.message.rstrip() self.genid()
def parse_message(self): """ Parse the message as sent by the bank. Most messages are composed of chunks of 32 characters, but there are exceptions. """ if self.transfer_type == "VZ": # Credit bank costs (interest) gets a special treatment. if self.remote_owner.startswith("RC AFREK. REK. "): self.transfer_type = "DV" if self.transfer_type == "DV": # Bank costs. # Title of action is in remote_owner, message contains additional # info self.reference = self.remote_owner.rstrip() parts = [self.message[i : i + 32].rstrip() for i in range(0, len(self.message), 32)] if len(parts) > 3: self.reference = parts[-1] self.message = "\n".join(parts[:-1]) else: self.message = "\n".join(parts) self.remote_owner = "" elif self.transfer_type == "BA": # Payment through bank terminal # Id of terminal and some owner info is part of message if self.execution_date < str2date("20091130", "%Y%m%d"): parts = self.remote_owner.split(">") else: parts = self.remote_owner.split(">\\") self.remote_owner = " ".join(parts[0].split()[1:]) if len(parts) > 1 and len(parts[1]) > 2: self.remote_owner_city = parts[1] self.message = self.refold_message(self.message) self.reference = "%s %s" % (self.remote_owner, " ".join(self.message.split()[2:4])) elif self.transfer_type == "IC": # Direct debit - remote_owner containts reference, while # remote_owner is part of the message, most often as # first part of the message. # Sometimes this misfires, as with the tax office collecting road # taxes, but then a once-only manual correction is sufficient. parts = [self.message[i : i + 32].rstrip() for i in range(0, len(self.message), 32)] self.reference = self.remote_owner if not parts: return if self.reference.startswith("KN: "): self.reference = self.reference[4:] if parts[0] == self.reference: parts = parts[1:] # The tax administration office seems to be the notorious exception # to the rule if parts[-1] == "BELASTINGDIENST": self.remote_owner = parts[-1].capitalize() parts = parts[:-1] else: self.remote_owner = parts[0] parts = parts[1:] # Leave the message, to assist in manual correction of misfires self.message = "\n".join(parts) elif self.transfer_type == "GM": # Cash withdrawal from a bank terminal # Structured remote_owner message containing bank info and location if self.remote_owner.startswith("OPL. CHIPKNIP"): # Transferring cash to debit card self.remote_account = self.local_account self.message = "%s: %s" % (self.remote_owner, self.message) else: if self.execution_date < str2date("20091130", "%Y%m%d"): parts = self.remote_owner.split(">") else: parts = self.remote_owner.split(">\\") if len(parts) > 1: self.reference = " ".join([x.rstrip() for x in parts]) else: self.reference = "ING BANK NV %s" % parts[0].split(" ")[0] self.remote_owner = "" elif self.transfer_type == "GT": # Normal transaction, but remote_owner can contain city, depending # on length of total. As there is no clear pattern, leave it as # is. self.message = self.refold_message(self.message) else: # Final default: reconstruct message from chopped fixed length # message parts. self.message = self.refold_message(self.message)
def parse_message(self): ''' Parse structured message parts into appropriate attributes ''' if self.transfer_type == 'ACC': # Accept Giro - structured message payment # First part of message is redundant information - strip it msg = self.message[self.message.index('navraagnr.'):] self.message = ' '.join(msg.split()) elif self.transfer_type == 'BEA': # Payment through payment terminal # Remote owner is part of message, while remote_owner is set # to the intermediate party, which we don't need. self.remote_owner = self.message[:23].rstrip() self.remote_owner_city = self.message[23:31].rstrip() self.message = self.message[31:] elif self.transfer_type == 'BTL': # International transfers. # Remote party is encoded in message, including bank costs parts = self.message.split(' ') last = False for part in parts: if part.startswith('bedrag. '): # The ordered transferred amount currency, amount = part.split('. ')[1].split() if self.remote_currency != currency.upper(): self.error_message = ( 'Remote currency in message differs from ' 'transaction.') else: self.local_amount = float(amount) elif part.startswith('koers. '): # The currency rate used self.exchange_rate = float(part.split('. ')[1]) elif part.startswith('transfer prov. '): # The provision taken by the bank # Note that the amount must be negated to get the right # direction currency, costs = part.split('. ')[1].split() self.provision_costs = -float(costs) self.provision_costs_currency = currency.upper() self.provision_costs_description = 'Transfer costs' elif part.startswith('aan. '): # The remote owner self.remote_owner = part.replace('aan. ', '').rstrip() last = True elif last: # Last parts are address lines address = part.rstrip() iso, pc, city = postalcode.split(address) if pc and city: self.remote_owner_postalcode = pc self.remote_owner_city = city.strip() self.remote_owner_country_code = iso else: self.remote_owner_address.append(address) elif self.transfer_type == 'DIV': # A diverse transfer. Message can be anything, but has some # structure ptr = self.message.find(self.reference) if ptr > 0: address = self.message[:ptr].rstrip().split(' ') length = len(address) if length >= 1: self.remote_owner = address[0] if length >= 2: self.remote_owner_address.append(address[1]) if length >= 3: self.remote_owner_city = address[2] self.message = self.message[ptr:].rstrip() if self.message.find('transactiedatum') >= 0: rest = self.message.split('transactiedatum') if rest[1].startswith('* '): self.execution_date = str2date(rest[1][2:], '%d-%m-%Y') else: self.execution_date = str2date(rest[1][2:], '%d %m %Y') self.message = rest[0].rstrip() elif self.transfer_type == 'IDB': # Payment by iDeal transaction # Remote owner can be part of message, while remote_owner can be # set to the intermediate party, which we don't need. parts = self.message.split(' ') # Second part: structured id, date & time subparts = parts[1].split() datestr = '-'.join(subparts[1:4]) timestr = ':'.join(subparts[4:]) parts[1] = ' '.join([subparts[0], datestr, timestr]) # Only replace reference when redundant if self.reference == parts[0]: if parts[2]: self.reference = ' '.join([parts[2], datestr, timestr]) else: self.reference += ' '.join([datestr, timestr]) # Optional fourth path contains remote owners name if len(parts) > 3 and parts[-1].find(self.remote_owner) < 0: self.remote_owner = parts[-1].rstrip() parts = parts[:-1] self.message = ' '.join(parts)
def str2date(str): dt = convert.str2date(str, '%Y-%m-%d') return datetime.date(dt.year, dt.month, dt.day)
def parse_message(self): ''' Parse structured message parts into appropriate attributes ''' if self.transfer_type == 'ACC': # Accept Giro - structured message payment # First part of message is redundant information - strip it msg = self.message[self.message.index('navraagnr.'):] self.message = ' '.join(msg.split()) elif self.transfer_type == 'BEA': # Payment through payment terminal # Remote owner is part of message, while remote_owner is set # to the intermediate party, which we don't need. self.remote_owner = self.message[:23].rstrip() self.remote_owner_city = self.message[23:31].rstrip() self.message = self.message[31:] elif self.transfer_type == 'BTL': # International transfers. # Remote party is encoded in message, including bank costs parts = self.message.split(' ') last = False for part in parts: if part.startswith('bedrag. '): # The ordered transferred amount currency, amount = part.split('. ')[1].split() if self.remote_currency != currency.upper(): self.error_message = \ 'Remote currency in message differs from transaction.' else: self.local_amount = float(amount) elif part.startswith('koers. '): # The currency rate used self.exchange_rate = float(part.split('. ')[1]) elif part.startswith('transfer prov. '): # The provision taken by the bank # Note that the amount must be negated to get the right # direction currency, costs = part.split('. ')[1].split() self.provision_costs = -float(costs) self.provision_costs_currency = currency.upper() self.provision_costs_description = 'Transfer costs' elif part.startswith('aan. '): # The remote owner self.remote_owner = part.replace('aan. ', '').rstrip() last = True elif last: # Last parts are address lines address = part.rstrip() iso, pc, city = postalcode.split(address) if pc and city: self.remote_owner_postalcode = pc self.remote_owner_city = city.strip() self.remote_owner_country_code = iso else: self.remote_owner_address.append(address) elif self.transfer_type == 'DIV': # A diverse transfer. Message can be anything, but has some # structure ptr = self.message.find(self.reference) if ptr > 0: address = self.message[:ptr].rstrip().split(' ') length = len(address) if length >= 1: self.remote_owner = address[0] if length >= 2: self.remote_owner_address.append(address[1]) if length >= 3: self.remote_owner_city = address[2] self.message = self.message[ptr:].rstrip() if self.message.find('transactiedatum') >= 0: rest = self.message.split('transactiedatum') if rest[1].startswith('* '): self.execution_date = str2date(rest[1][2:], '%d-%m-%Y') else: self.execution_date = str2date(rest[1][2:], '%d %m %Y') self.message = rest[0].rstrip() elif self.transfer_type == 'IDB': # Payment by iDeal transaction # Remote owner can be part of message, while remote_owner can be # set to the intermediate party, which we don't need. parts = self.message.split(' ') # Second part: structured id, date & time subparts = parts[1].split() datestr = '-'.join(subparts[1:4]) timestr = ':'.join(subparts[4:]) parts[1] = ' '.join([subparts[0], datestr, timestr]) # Only replace reference when redundant if self.reference == parts[0]: if parts[2]: self.reference = ' '.join([parts[2], datestr, timestr]) else: self.reference += ' '.join([datestr, timestr]) # Optional fourth path contains remote owners name if len(parts) > 3 and parts[-1].find(self.remote_owner) < 0: self.remote_owner = parts[-1].rstrip() parts = parts[:-1] self.message = ' '.join(parts)
def parse_message(self): ''' Parse the message as sent by the bank. Most messages are composed of chunks of 32 characters, but there are exceptions. ''' if self.transfer_type == 'VZ': # Credit bank costs (interest) gets a special treatment. if self.remote_owner.startswith('RC AFREK. REK. '): self.transfer_type = 'DV' if self.transfer_type == 'DV': # Bank costs. # Title of action is in remote_owner, message contains additional # info self.reference = self.remote_owner.rstrip() parts = [ self.message[i:i + 32].rstrip() for i in range(0, len(self.message), 32) ] if len(parts) > 3: self.reference = parts[-1] self.message = '\n'.join(parts[:-1]) else: self.message = '\n'.join(parts) self.remote_owner = '' elif self.transfer_type == 'BA': # Payment through bank terminal # Id of terminal and some owner info is part of message if self.execution_date < str2date('20091130', '%Y%m%d'): parts = self.remote_owner.split('>') else: parts = self.remote_owner.split('>\\') self.remote_owner = ' '.join(parts[0].split()[1:]) if len(parts) > 1 and len(parts[1]) > 2: self.remote_owner_city = parts[1] self.message = self.refold_message(self.message) self.reference = '%s %s' % (self.remote_owner, ' '.join( self.message.split()[2:4])) elif self.transfer_type == 'IC': # Direct debit - remote_owner containts reference, while # remote_owner is part of the message, most often as # first part of the message. # Sometimes this misfires, as with the tax office collecting road # taxes, but then a once-only manual correction is sufficient. parts = [ self.message[i:i + 32].rstrip() for i in range(0, len(self.message), 32) ] self.reference = self.remote_owner if not parts: return if self.reference.startswith('KN: '): self.reference = self.reference[4:] if parts[0] == self.reference: parts = parts[1:] # The tax administration office seems to be the notorious exception # to the rule if parts[-1] == 'BELASTINGDIENST': self.remote_owner = parts[-1].capitalize() parts = parts[:-1] else: self.remote_owner = parts[0] parts = parts[1:] # Leave the message, to assist in manual correction of misfires self.message = '\n'.join(parts) elif self.transfer_type == 'GM': # Cash withdrawal from a bank terminal # Structured remote_owner message containing bank info and location if self.remote_owner.startswith('OPL. CHIPKNIP'): # Transferring cash to debit card self.remote_account = self.local_account self.message = '%s: %s' % (self.remote_owner, self.message) else: if self.execution_date < str2date('20091130', '%Y%m%d'): parts = self.remote_owner.split('>') else: parts = self.remote_owner.split('>\\') if len(parts) > 1: self.reference = ' '.join([x.rstrip() for x in parts]) else: self.reference = 'ING BANK NV %s' % parts[0].split(' ')[0] self.remote_owner = '' elif self.transfer_type == 'GT': # Normal transaction, but remote_owner can contain city, depending # on length of total. As there is no clear pattern, leave it as # is. self.message = self.refold_message(self.message) else: # Final default: reconstruct message from chopped fixed length # message parts. self.message = self.refold_message(self.message)