mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-04 02:23:26 -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:
		
							
								
								
									
										31
									
								
								gnucash.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								gnucash.go
									
									
									
									
									
								
							@@ -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
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								imports.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								imports.go
									
									
									
									
									
								
							@@ -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
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								ofx.go
									
									
									
									
									
								
							@@ -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]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user