1
0
mirror of https://github.com/aclindsa/moneygo.git synced 2025-01-30 17:38:55 -05:00

imports: Don't re-import the same transaction from the same place

This is detected using the RemoteId field on Splits

While we're at it, also make gnucash import check numbers
This commit is contained in:
Aaron Lindsay 2017-06-10 15:22:13 -04:00
parent 8cb222a107
commit a4b99381d3
4 changed files with 46 additions and 10 deletions

View File

@ -84,6 +84,7 @@ type GnucashAccount struct {
type GnucashTransaction struct { type GnucashTransaction struct {
TransactionId string `xml:"http://www.gnucash.org/XML/trn id"` TransactionId string `xml:"http://www.gnucash.org/XML/trn id"`
Description string `xml:"http://www.gnucash.org/XML/trn description"` Description string `xml:"http://www.gnucash.org/XML/trn description"`
Number string `xml:"http://www.gnucash.org/XML/trn num"`
DatePosted GnucashDate `xml:"http://www.gnucash.org/XML/trn date-posted"` DatePosted GnucashDate `xml:"http://www.gnucash.org/XML/trn date-posted"`
DateEntered GnucashDate `xml:"http://www.gnucash.org/XML/trn date-entered"` DateEntered GnucashDate `xml:"http://www.gnucash.org/XML/trn date-entered"`
Commodity GnucashXMLCommodity `xml:"http://www.gnucash.org/XML/trn currency"` Commodity GnucashXMLCommodity `xml:"http://www.gnucash.org/XML/trn currency"`
@ -215,7 +216,6 @@ func ImportGnucash(r io.Reader) (*GnucashImport, error) {
for j := range gt.Splits { for j := range gt.Splits {
gs := gt.Splits[j] gs := gt.Splits[j]
s := new(Split) s := new(Split)
s.Memo = gs.Memo
switch gs.Status { switch gs.Status {
default: // 'n', or not present default: // 'n', or not present
@ -238,6 +238,10 @@ func ImportGnucash(r io.Reader) (*GnucashImport, error) {
} }
s.SecurityId = -1 s.SecurityId = -1
s.RemoteId = "gnucash:" + gs.SplitId
s.Number = gt.Number
s.Memo = gs.Memo
var r big.Rat var r big.Rat
_, ok = r.SetString(gs.Amount) _, ok = r.SetString(gs.Amount)
if ok { if ok {
@ -359,6 +363,7 @@ func GnucashImportHandler(w http.ResponseWriter, r *http.Request) {
// Insert transactions, fixing up account IDs to match internal ones from // Insert transactions, fixing up account IDs to match internal ones from
// above // above
for _, transaction := range gnucashImport.Transactions { for _, transaction := range gnucashImport.Transactions {
var already_imported bool
for _, split := range transaction.Splits { for _, split := range transaction.Splits {
acctId, ok := accountMap[split.AccountId] acctId, ok := accountMap[split.AccountId]
if !ok { if !ok {
@ -368,13 +373,25 @@ func GnucashImportHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
split.AccountId = acctId split.AccountId = acctId
exists, err := split.AlreadyImportedTx(sqltransaction)
if err != nil {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
log.Print("Error checking if split was already imported:", err)
return
} else if exists {
already_imported = true
}
} }
err := InsertTransactionTx(sqltransaction, &transaction, user) if !already_imported {
if err != nil { err := InsertTransactionTx(sqltransaction, &transaction, user)
sqltransaction.Rollback() if err != nil {
WriteError(w, 999 /*Internal Error*/) sqltransaction.Rollback()
log.Print(err) WriteError(w, 999 /*Internal Error*/)
return log.Print(err)
return
}
} }
} }

View File

@ -187,7 +187,9 @@ func ofxImportHelper(r io.Reader, w http.ResponseWriter, user *User, accountid i
} }
// Move any splits with SecurityId but not AccountId to Imbalances // Move any splits with SecurityId but not AccountId to Imbalances
// accounts // accounts. In the same loop, check to see if this transaction/split
// has been imported before
var already_imported bool
for _, split := range transaction.Splits { for _, split := range transaction.Splits {
if split.SecurityId != -1 || split.AccountId == -1 { if split.SecurityId != -1 || split.AccountId == -1 {
imbalanced_account, err := GetImbalanceAccount(sqltransaction, user.UserId, split.SecurityId) imbalanced_account, err := GetImbalanceAccount(sqltransaction, user.UserId, split.SecurityId)
@ -201,9 +203,21 @@ func ofxImportHelper(r io.Reader, w http.ResponseWriter, user *User, accountid i
split.AccountId = imbalanced_account.AccountId split.AccountId = imbalanced_account.AccountId
split.SecurityId = -1 split.SecurityId = -1
} }
exists, err := split.AlreadyImportedTx(sqltransaction)
if err != nil {
sqltransaction.Rollback()
WriteError(w, 999 /*Internal Error*/)
log.Print("Error checking if split was already imported:", err)
return
} else if exists {
already_imported = true
}
} }
transactions = append(transactions, transaction) if !already_imported {
transactions = append(transactions, transaction)
}
} }
for _, transaction := range transactions { for _, transaction := range transactions {

2
ofx.go
View File

@ -80,7 +80,7 @@ func (i *OFXImport) AddTransaction(tran *ofxgo.Transaction, account *Account) er
return errors.New("Internal error: security index not found in OFX import\n") return errors.New("Internal error: security index not found in OFX import\n")
} }
s1.RemoteId = tran.FiTID.String() s1.RemoteId = "ofx:" + tran.FiTID.String()
// TODO CorrectFiTID/CorrectAction? // TODO CorrectFiTID/CorrectAction?
security := i.Securities[account.SecurityId-1] security := i.Securities[account.SecurityId-1]

View File

@ -61,6 +61,11 @@ func (s *Split) Valid() bool {
return err == nil return err == nil
} }
func (s *Split) AlreadyImportedTx(transaction *gorp.Transaction) (bool, error) {
count, err := transaction.SelectInt("SELECT COUNT(*) from splits where RemoteId=? and AccountId=?", s.RemoteId, s.AccountId)
return count == 1, err
}
type Transaction struct { type Transaction struct {
TransactionId int64 TransactionId int64
UserId int64 UserId int64