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:
121
imports.go
121
imports.go
@ -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()
|
||||
|
Reference in New Issue
Block a user