1
0
mirror of https://github.com/aclindsa/moneygo.git synced 2025-07-01 12:08:37 -04:00

Move OFX imports from libofx to ofxgo

This makes them native Go code, and will allow for fetching them
directly from financial institutions later.
This commit is contained in:
2017-05-08 06:01:26 -04:00
parent 32fffdf91b
commit a9cf95dba8
7 changed files with 291 additions and 371 deletions

View File

@ -2,11 +2,9 @@ package main
import (
"io"
"io/ioutil"
"log"
"math/big"
"net/http"
"os"
)
/*
@ -15,13 +13,6 @@ import (
func AccountImportHandler(w http.ResponseWriter, r *http.Request, user *User, accountid int64, importtype string) {
//TODO branch off for different importtype's
// Return Account with this Id
account, err := GetAccount(accountid, user.UserId)
if err != nil {
WriteError(w, 3 /*Invalid Request*/)
return
}
multipartReader, err := r.MultipartReader()
if err != nil {
WriteError(w, 3 /*Invalid Request*/)
@ -40,28 +31,18 @@ func AccountImportHandler(w http.ResponseWriter, r *http.Request, user *User, ac
return
}
f, err := ioutil.TempFile(tmpDir, user.Username+"_"+account.Name)
if err != nil {
WriteError(w, 999 /*Internal Error*/)
log.Print(err)
return
}
tmpFilename := f.Name()
defer os.Remove(tmpFilename)
_, err = io.Copy(f, part)
f.Close()
if err != nil {
WriteError(w, 999 /*Internal Error*/)
log.Print(err)
return
}
itl, err := ImportOFX(tmpFilename, account)
itl, err := ImportOFX(part)
if err != nil {
//TODO is this necessarily an invalid request (what if it was an error on our end)?
WriteError(w, 3 /*Invalid Request*/)
log.Print(err)
return
}
if len(itl.Accounts) != 1 {
WriteError(w, 3 /*Invalid Request*/)
log.Printf("Found %d accounts when importing OFX, expected 1", len(itl.Accounts))
return
}
@ -72,17 +53,99 @@ func AccountImportHandler(w http.ResponseWriter, r *http.Request, user *User, ac
return
}
// Return Account with this Id
account, err := GetAccountTx(sqltransaction, accountid, user.UserId)
if err != nil {
sqltransaction.Rollback()
WriteError(w, 3 /*Invalid Request*/)
log.Print(err)
return
}
importedAccount := itl.Accounts[0]
if len(account.ExternalAccountId) > 0 &&
account.ExternalAccountId != importedAccount.ExternalAccountId {
sqltransaction.Rollback()
WriteError(w, 3 /*Invalid Request*/)
log.Printf("OFX import has \"%s\" as ExternalAccountId, but the account being imported to has\"%s\"",
importedAccount.ExternalAccountId,
account.ExternalAccountId)
return
}
if account.Type != importedAccount.Type {
sqltransaction.Rollback()
WriteError(w, 3 /*Invalid Request*/)
log.Printf("Expected %s account, found %s in OFX file", account.Type.String(), importedAccount.Type.String())
return
}
// Find matching existing securities or create new ones for those
// referenced by the OFX import. Also create a map from placeholder import
// SecurityIds to the actual SecurityIDs
var securitymap = make(map[int64]*Security)
for _, ofxsecurity := range itl.Securities {
security, err := ImportGetCreateSecurity(sqltransaction, user, &ofxsecurity)
if err != nil {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
log.Print(err)
return
}
securitymap[ofxsecurity.SecurityId] = security
}
if account.SecurityId != securitymap[importedAccount.SecurityId].SecurityId {
sqltransaction.Rollback()
WriteError(w, 3 /*Invalid Request*/)
log.Printf("OFX import account's SecurityId (%d) does not match this account's (%d)", securitymap[importedAccount.SecurityId].SecurityId, account.SecurityId)
return
}
// TODO Ensure all transactions have at least one split in the account
// we're importing to?
var transactions []Transaction
for _, transaction := range *itl.Transactions {
for _, transaction := range itl.Transactions {
transaction.UserId = user.UserId
transaction.Status = Imported
if !transaction.Valid() {
sqltransaction.Rollback()
WriteError(w, 3 /*Invalid Request*/)
WriteError(w, 999 /*Internal Error*/)
log.Print("Unexpected invalid transaction from OFX import")
return
}
// Ensure that either AccountId or SecurityId is set for this split,
// and fixup the SecurityId to be a valid one for this user's actual
// securities instead of a placeholder from the import
for _, split := range transaction.Splits {
if split.AccountId != -1 {
if split.AccountId != importedAccount.AccountId {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
return
}
split.AccountId = account.AccountId
} else if split.SecurityId != -1 {
if sec, ok := securitymap[split.SecurityId]; ok {
split.SecurityId = sec.SecurityId
} else {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
log.Print("Couldn't find split's SecurityId in map during OFX import")
return
}
} else {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
log.Print("Neither Split.AccountId Split.SecurityId was set during OFX import")
return
}
}
imbalances, err := transaction.GetImbalancesTx(sqltransaction)
if err != nil {
sqltransaction.Rollback()