| @@ -7,15 +7,18 @@ from pathlib import Path | |||
| whitelist_cards = ["7756"] | |||
| in_header = ['Utført dato', 'Bokført dato', 'Rentedato', 'Beskrivelse', 'Type', 'Undertype', 'Fra konto', 'Avsender', 'Til konto', 'Mottakernavn', 'Beløp inn', 'Beløp ut', 'Valuta', 'Status', 'Melding'] | |||
| out_header = ['Date', 'Payee', 'Memo', 'Outflow', 'Inflow'] | |||
| def usage(): | |||
| print('Usage: ynab.py <filename>') | |||
| def is_reserved(row): | |||
| return '(Reservert)' in row[1] | |||
| return row['Status'] == "Reservert" | |||
| def convert_memo(original): | |||
| original = re.match(r'="[ ]?(.+)"', original).groups()[0] | |||
| original = original.replace(" Kurs: 1.0000", "") | |||
| words = original.split(" ") | |||
| @@ -53,41 +56,45 @@ def convert_memo(original): | |||
| return " ".join(words) | |||
| def convert(reader, writer): | |||
| header = ['Date', 'Payee', 'Memo', 'Outflow', 'Inflow'] | |||
| writer.writerow(header) | |||
| def convert_row(row): | |||
| if is_reserved(row): | |||
| return None | |||
| # Ignore header | |||
| reader.__next__() | |||
| if row['Valuta'] != 'NOK': | |||
| raise ValueError(f"Unknown currency {row['Valuta']}") | |||
| for row in reader: | |||
| if is_reserved(row): | |||
| continue | |||
| return [ | |||
| row['Bokført dato'], | |||
| row['Beskrivelse'], | |||
| convert_memo(row['Melding']), | |||
| -float(row['Beløp ut'] or '0'), | |||
| float(row['Beløp inn'] or '0'), | |||
| ] | |||
| money_out = 0 | |||
| money_in = 0 | |||
| if (isinstance(row[3], str)): | |||
| moneystr = row[3].replace(',', '.') | |||
| def convert(reader, writer): | |||
| writer.writerow(out_header) | |||
| try: | |||
| money = float(moneystr) if moneystr else 0 | |||
| except ValueError as e: | |||
| print(f'Error in row {row}') | |||
| raise e | |||
| else: | |||
| money = float(row[3]) | |||
| # Ignore header | |||
| reader.__next__() | |||
| if money >= 0: | |||
| money_in = money | |||
| for raw_row in reader: | |||
| # Stop when we hit an empty row | |||
| for field in raw_row: | |||
| if field: | |||
| break | |||
| else: | |||
| money_out = -money | |||
| break | |||
| memo = convert_memo(row[2]) | |||
| # Create dictionary with proper field names | |||
| row = {x[0]: x[1] for x in zip(in_header, raw_row)} | |||
| new_row = [*row[:2], memo, money_out, money_in] | |||
| writer.writerow(new_row) | |||
| try: | |||
| if (result := convert_row(row)) is not None: | |||
| writer.writerow(result) | |||
| except Exception as e: | |||
| print(f'Error in row {row}') | |||
| raise e | |||
| def main(): | |||
| @@ -100,7 +107,7 @@ def main(): | |||
| new_basename = f'ynab-{filepath.name}' | |||
| new_filepath = filepath.parent / new_basename | |||
| with filepath.open(mode='r') as old_file: | |||
| with filepath.open(mode='r', encoding='latin1') as old_file: | |||
| reader = csv.reader(old_file, delimiter=';') | |||
| with new_filepath.open(mode='w') as new_file: | |||