Created
March 23, 2023 20:51
-
-
Save gbirke/2277173732d13987e618db670125fc2c to your computer and use it in GitHub Desktop.
Convert CSV credit card statements of GLS Bank to look more like bank statements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import csv | |
import os.path | |
import sys | |
import logging | |
import re | |
""" | |
This script converts CSV credit card statements of GLS Bank to look more like | |
bank statements. | |
The difference is that in credit card statements the recipient column is | |
always "GLS Bank" and the real recipient is in the 2nd line of the multiline | |
description column. | |
This script parses the description column and updates the recipient and | |
description column if the description starts with "Basislastschrift" | |
(which indicates a payment). | |
Author: Gabriel Birke <[email protected]> | |
License: MIT | |
Version Changes | |
--------------- | |
2022-03-15 | |
Adapted to new CSV format: | |
* New Primanota column | |
* longer contains line breaks in description. instead, the desciption is a fixed-width table | |
2022-05-14 | |
Adapted to new CSV format | |
* Skip first line (headers) | |
* different columns | |
""" | |
DESCRIPTION_COLUMN = 10 | |
RECIPIENT_COLUMN = 6 | |
def convert_row(row): | |
# Skip non-transaction rows | |
if len(row) < 10: | |
return row | |
description = row[DESCRIPTION_COLUMN] | |
if re.match(r'Abrechnung vom.*Hauptkarte', description): | |
return [] | |
if re.match(r'Jahresbeitrag.*Hauptkarte', description): | |
return row | |
row[RECIPIENT_COLUMN] = description[0:27].strip() | |
row[DESCRIPTION_COLUMN] = description[27:] | |
return row | |
def convert_files(source_file, destination_file): | |
with open(source_file, encoding='utf-8', newline='') as input_file, open(destination_file, 'w', newline='', encoding='utf-8') as output_file: | |
input_reader = csv.reader( | |
input_file, | |
delimiter=";", | |
quoting=csv.QUOTE_NONE | |
) | |
output_writer = csv.writer( | |
output_file, | |
delimiter=";", | |
quoting=csv.QUOTE_NONE | |
) | |
row_index = 0 | |
for row in input_reader: | |
if row_index > 0: | |
converted_row = convert_row(row) | |
else: | |
converted_row = row | |
if converted_row == []: | |
continue | |
output_writer.writerow(converted_row) | |
row_index += 1 | |
def get_filenames(source_file, override): | |
if not os.path.isfile(source_file): | |
print("Can't read '%s' - is it a file?".format(source_file)) | |
if source_file[-4:] != '.csv': | |
logging.warn("Input file name should end in .csv for optimal output file naming") | |
destination_file = source_file[0:-4] + ".converted.csv" | |
if os.path.isfile(destination_file): | |
if override: | |
logging.warning("Overwriting %s", destination_file) | |
else: | |
logging.error("Output file '%s' already exists", destination_file) | |
sys.exit(2) | |
return source_file, destination_file | |
def setup_cli(): | |
parser = argparse.ArgumentParser(description="Convert GLS Bank credit card statements to bank statements") | |
parser.add_argument('statement_file', nargs='+', help="CSV file with credit card statements") | |
parser.add_argument('-f', '--force', dest='override', action="store_true", default=False, help="Overwrite output file if it exists") | |
parser.add_argument('-q', '--quiet', dest='quiet', action="store_true", default=False, help="Suppress output") | |
return parser | |
if __name__ == "__main__": | |
parser = setup_cli() | |
args = parser.parse_args() | |
if args.quiet: | |
logging.basicConfig(level=logging.CRITICAL) | |
else: | |
logging.basicConfig(level=logging.INFO) | |
for statement_file in args.statement_file: | |
source_file, destination_file = get_filenames(statement_file, args.override) | |
convert_files(source_file, destination_file) | |
logging.info("Converted to %s", destination_file) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment