#!/usr/bin/python -O
#
# sampo2ofx - convert Sampo bank CSV to OFX
# Copyright (C) 2007  Timo Lindfors <timo.lindfors@iki.fi>

# 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 2 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/>.

# This program is based on mastercard2ofx which had the following
# copyright info:

##
## mastercard2ofx version 0.1 (30 Jan 2006)
##
## Converts a mastercard csv file like you get it from
## https://umsatzabfrage.mastercard.at/Umsatzabfrage/
## to an ofx file which you can import with gnucash.
##
## This does not output a 'really' correct ofx file, but it's
## allright for this purpose.
##
## Copyright (c) 2005, Martin Klaffenboeck
##   (martin.klaffenboeck@gmx.at)
##
## Published unter GPL (http://www.gnu.org/copyleft/gpl.html)
##
## If you patch this file, choose another name and send me your
## changes (diff -Nur).  Thanks!
##
## Enjoy ;-)


# 1) Go to www.sampopankki.fi and login
# 2) Select tilitapahtumat
# 3) click the floppy icon to save transactions. The system will suggest
#    a name like Tilitapahtumat_YYYYMMDD.csv which should be ok.
# 4) Verify that the csv file has the following format:
#
# Kirjauspaiva;Saaja/Maksaja;Tapahtuma;Oma luokittelu;Maara
# 27.8.2007;ARCTECHO OY;Tulot/Panot;Ei luokiteltu;309,90
# 14.8.2007;KATEISAUTOMAATTI/OTTO.;Kateisnostot;Ei luokiteltu;-90,00
# ...
# (Umlauts removed to reduce python warnings)
# 
# 5) run sampo2ofx <accid> Tilitapahtumat_YYYYMMDD.csv Tilitapahtumat_YYYYMMDD.ofx
# 6) choose file->import->ofx in gnucash and select Tilitapahtumat_YYYYMMDD.ofx


import sys, codecs
import time
import md5

CSVFILE = None
OFXFILE = None
ACCID = None

class csv:
    def __init__(self, csvfile):
        self.fp = codecs.open(csvfile, "r", "iso-8859-1")
        header = self.fp.readline()
        assert header == "Kirjausp\xE4iv\xE4;Saaja/Maksaja;Tapahtuma;Oma luokittelu;M\xE4\xE4r\xE4\n"

    def __del__(self):
        self.fp.close()

    def next(self):
        line = self.fp.readline()
        if not line or line == '\n':
            return False

        rawval = line.split(";")

        t = time.strptime(rawval[0], "%d.%m.%Y")

        self.dtposted = time.strftime("%Y%m%d", t)
        self.trnamt = rawval[4].replace(",",".").replace(" ", "").strip()
        self.name = rawval[1].strip().replace("\"", "")
        self.memo = ""
        assert rawval[3] == "Ei luokiteltu"

        # eindeutige id
        self.fitid = md5.new(line.encode('iso-8859-1')).hexdigest()

    def get(self):
        return self.dtposted, self.trnamt, self.fitid, self.name, self.memo

class ofx:
    tags = []
    intend = 0
    def __init__(self, ofxfile):
        self.fp = codecs.open(ofxfile, "w", "utf-8")
        self.startfile()

    def startfile(self):
        self.fp.write("""OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:UTF-8
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE
""")

    def write(self, str):
        self.fp.write(" " * self.intend + str)

    def open(self, rawtag):
        tag = rawtag.upper()
        self.write("<" + tag + ">\n")
        self.tags.append(tag)
        self.intend += 2

    def close(self, num=1):
        for i in range(num):
            tag = self.tags.pop()
            self.intend -= 2
            self.write("</" + tag + ">\n")

    def put(self, rawtag, value):
        tag = rawtag.upper()
        self.write("<" + tag + ">" + value + "\n")

    def __del__(self):
        self.close(len(self.tags))
        self.fp.close()


def convert():
    x = ofx(OFXFILE)
    c = csv(CSVFILE)

    x.open("OFX")
    x.open("SIGNONMSGSRSV1")
    x.open("SONRS")
    x.open("STATUS")
    x.put("CODE", "0")
    x.put("SERVERITY", "INFO")
    x.close()

    val = time.strftime("%Y%m%d")
    x.put("DTSERVER", val + "000000[+1:CET]") # FIXME
    x.put("LANGUAGE", "ENG")
    x.close(2)

    x.open("BANKMSGSRSV1")
    x.open("STMTTRNRS")
    x.put("TRNUID", "1")
    x.open("STATUS")
    x.put("CODE", "0")
    x.put("SEVERITY", "INFO")
    x.close()

    x.open("STMTRS")
    x.put("CURDEF", "EUR")

    #bankaccount
    x.open("BANKACCTFROM")
    val = "Sampo"
    x.put("BANKID", val)
    x.put("ACCTID", ACCID)
    x.put("ACCTTYPE", "CREDIT")
    x.close()

    #tranlist
    x.open("BANKTRANLIST")
#         val = c.get_value("ACCTSTMT.STMTRS.DTSTART")
#         x.put("DTSTART", val + "000000[+1:CET]")
#         val = c.get_value("ACCTSTMT.STMTRS.DTEND")
#         x.put("DTEND", val + "000000[+1:CET]")

    # transaktions
    while c.next() != False:
        dtposted, trnamt, fitid, name, memo = c.get()
        x.open("STMTTRN")
        x.put("TRNTYPE", "XFER")
        x.put("DTPOSTED", dtposted + "000000[+1:CET]")
        x.put("FITID", fitid)
        x.put("TRNAMT", trnamt)
        x.put("NAME", name)
        if memo != "":
            x.put("MEMO", memo)
        x.close()



def usage():
    print "Usage: csv2ofx <accid> <infile.csv> <outfile.ofx>"

def main():
    global ACCID, OFXFILE, CSVFILE
    if len(sys.argv) < 4:
        usage()
        sys.exit()

    ACCID = sys.argv[1]
    CSVFILE = sys.argv[2]
    OFXFILE = sys.argv[3]

    convert()


if __name__ == "__main__":
    main()

