mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-10-29 17:13:26 -04:00 
			
		
		
		
	| @@ -14,7 +14,7 @@ services: | |||||||
| env: | env: | ||||||
|   - MONEYGO_TEST_DB=sqlite |   - MONEYGO_TEST_DB=sqlite | ||||||
|   - MONEYGO_TEST_DB=mysql    MONEYGO_TEST_DSN="root@tcp(127.0.0.1)/moneygo_test?parseTime=true" |   - MONEYGO_TEST_DB=mysql    MONEYGO_TEST_DSN="root@tcp(127.0.0.1)/moneygo_test?parseTime=true" | ||||||
| # - MONEYGO_TEST_DB=postgres MONEYGO_TEST_DSN="postgres://postgres@localhost/moneygo_test" |   - MONEYGO_TEST_DB=postgres MONEYGO_TEST_DSN="postgres://postgres@localhost/moneygo_test" | ||||||
|  |  | ||||||
| before_script: | before_script: | ||||||
|   - sh -c "if [ $MONEYGO_TEST_DB = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS moneygo_test;' -U postgres; fi" |   - sh -c "if [ $MONEYGO_TEST_DB = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS moneygo_test;' -U postgres; fi" | ||||||
|   | |||||||
| @@ -14,8 +14,6 @@ type ResponseWriterWriter interface { | |||||||
| 	Write(http.ResponseWriter) error | 	Write(http.ResponseWriter) error | ||||||
| } | } | ||||||
|  |  | ||||||
| type Tx = gorp.Transaction |  | ||||||
|  |  | ||||||
| type Context struct { | type Context struct { | ||||||
| 	Tx           *Tx | 	Tx           *Tx | ||||||
| 	User         *User | 	User         *User | ||||||
| @@ -51,7 +49,7 @@ type APIHandler struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (ah *APIHandler) txWrapper(h Handler, r *http.Request, context *Context) (writer ResponseWriterWriter) { | func (ah *APIHandler) txWrapper(h Handler, r *http.Request, context *Context) (writer ResponseWriterWriter) { | ||||||
| 	tx, err := ah.DB.Begin() | 	tx, err := GetTx(ah.DB) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Print(err) | 		log.Print(err) | ||||||
| 		return NewError(999 /*Internal Error*/) | 		return NewError(999 /*Internal Error*/) | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ func TestCreatePrice(t *testing.T) { | |||||||
| 			if p.CurrencyId != d.securities[orig.CurrencyId].SecurityId { | 			if p.CurrencyId != d.securities[orig.CurrencyId].SecurityId { | ||||||
| 				t.Errorf("CurrencyId doesn't match") | 				t.Errorf("CurrencyId doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Date != orig.Date { | 			if !p.Date.Equal(orig.Date) { | ||||||
| 				t.Errorf("Date doesn't match") | 				t.Errorf("Date doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Value != orig.Value { | 			if p.Value != orig.Value { | ||||||
| @@ -94,7 +94,7 @@ func TestGetPrice(t *testing.T) { | |||||||
| 			if p.CurrencyId != d.securities[orig.CurrencyId].SecurityId { | 			if p.CurrencyId != d.securities[orig.CurrencyId].SecurityId { | ||||||
| 				t.Errorf("CurrencyId doesn't match") | 				t.Errorf("CurrencyId doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Date != orig.Date { | 			if !p.Date.Equal(orig.Date) { | ||||||
| 				t.Errorf("Date doesn't match") | 				t.Errorf("Date doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Value != orig.Value { | 			if p.Value != orig.Value { | ||||||
| @@ -131,7 +131,7 @@ func TestGetPrices(t *testing.T) { | |||||||
|  |  | ||||||
| 				found := false | 				found := false | ||||||
| 				for _, p := range *pl.Prices { | 				for _, p := range *pl.Prices { | ||||||
| 					if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date == orig.Date && p.Value == orig.Value && p.RemoteId == orig.RemoteId { | 					if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date.Equal(orig.Date) && p.Value == orig.Value && p.RemoteId == orig.RemoteId { | ||||||
| 						if _, ok := foundIds[p.PriceId]; ok { | 						if _, ok := foundIds[p.PriceId]; ok { | ||||||
| 							continue | 							continue | ||||||
| 						} | 						} | ||||||
| @@ -177,7 +177,7 @@ func TestUpdatePrice(t *testing.T) { | |||||||
| 			if p.CurrencyId != curr.CurrencyId { | 			if p.CurrencyId != curr.CurrencyId { | ||||||
| 				t.Errorf("CurrencyId doesn't match") | 				t.Errorf("CurrencyId doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Date != curr.Date { | 			if !p.Date.Equal(curr.Date) { | ||||||
| 				t.Errorf("Date doesn't match") | 				t.Errorf("Date doesn't match") | ||||||
| 			} | 			} | ||||||
| 			if p.Value != curr.Value { | 			if p.Value != curr.Value { | ||||||
|   | |||||||
| @@ -623,7 +623,7 @@ func GetAccountTransactions(tx *Tx, user *User, accountid int64, sort string, pa | |||||||
| 	var sqlsort, balanceLimitOffset string | 	var sqlsort, balanceLimitOffset string | ||||||
| 	var balanceLimitOffsetArg uint64 | 	var balanceLimitOffsetArg uint64 | ||||||
| 	if sort == "date-asc" { | 	if sort == "date-asc" { | ||||||
| 		sqlsort = " ORDER BY transactions.Date ASC" | 		sqlsort = " ORDER BY transactions.Date ASC, transactions.TransactionId ASC" | ||||||
| 		balanceLimitOffset = " LIMIT ?" | 		balanceLimitOffset = " LIMIT ?" | ||||||
| 		balanceLimitOffsetArg = page * limit | 		balanceLimitOffsetArg = page * limit | ||||||
| 	} else if sort == "date-desc" { | 	} else if sort == "date-desc" { | ||||||
| @@ -631,7 +631,7 @@ func GetAccountTransactions(tx *Tx, user *User, accountid int64, sort string, pa | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		sqlsort = " ORDER BY transactions.Date DESC" | 		sqlsort = " ORDER BY transactions.Date DESC, transactions.TransactionId DESC" | ||||||
| 		balanceLimitOffset = fmt.Sprintf(" LIMIT %d OFFSET ?", numSplits) | 		balanceLimitOffset = fmt.Sprintf(" LIMIT %d OFFSET ?", numSplits) | ||||||
| 		balanceLimitOffsetArg = (page + 1) * limit | 		balanceLimitOffsetArg = (page + 1) * limit | ||||||
| 	} | 	} | ||||||
| @@ -676,7 +676,7 @@ func GetAccountTransactions(tx *Tx, user *User, accountid int64, sort string, pa | |||||||
| 	// Sum all the splits for all transaction splits for this account that | 	// Sum all the splits for all transaction splits for this account that | ||||||
| 	// occurred before the page we're returning | 	// occurred before the page we're returning | ||||||
| 	var amounts []string | 	var amounts []string | ||||||
| 	sql = "SELECT s.Amount FROM splits AS s INNER JOIN (SELECT DISTINCT transactions.TransactionId FROM transactions INNER JOIN splits ON transactions.TransactionId = splits.TransactionId WHERE transactions.UserId=? AND splits.AccountId=?" + sqlsort + balanceLimitOffset + ") as t ON s.TransactionId = t.TransactionId WHERE s.AccountId=?" | 	sql = "SELECT s.Amount FROM splits AS s INNER JOIN (SELECT DISTINCT transactions.Date, transactions.TransactionId FROM transactions INNER JOIN splits ON transactions.TransactionId = splits.TransactionId WHERE transactions.UserId=? AND splits.AccountId=?" + sqlsort + balanceLimitOffset + ") as t ON s.TransactionId = t.TransactionId WHERE s.AccountId=?" | ||||||
| 	_, err = tx.Select(&amounts, sql, user.UserId, accountid, balanceLimitOffsetArg, accountid) | 	_, err = tx.Select(&amounts, sql, user.UserId, accountid, balanceLimitOffsetArg, accountid) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
|   | |||||||
| @@ -87,8 +87,8 @@ func ensureTransactionsMatch(t *testing.T, expected, tran *handlers.Transaction, | |||||||
| 	if tran.Description != expected.Description { | 	if tran.Description != expected.Description { | ||||||
| 		t.Errorf("Description doesn't match") | 		t.Errorf("Description doesn't match") | ||||||
| 	} | 	} | ||||||
| 	if tran.Date != expected.Date { | 	if !tran.Date.Equal(expected.Date) { | ||||||
| 		t.Errorf("Date doesn't match") | 		t.Errorf("Date (%+v) differs from expected (%+v)", tran.Date, expected.Date) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(tran.Splits) != len(expected.Splits) { | 	if len(tran.Splits) != len(expected.Splits) { | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								internal/handlers/tx.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								internal/handlers/tx.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | package handlers | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"database/sql" | ||||||
|  | 	"gopkg.in/gorp.v1" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Tx struct { | ||||||
|  | 	Dialect gorp.Dialect | ||||||
|  | 	Tx      *gorp.Transaction | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Rebind(query string) string { | ||||||
|  | 	chunks := strings.Split(query, "?") | ||||||
|  | 	str := chunks[0] | ||||||
|  | 	for i := 1; i < len(chunks); i++ { | ||||||
|  | 		str += tx.Dialect.BindVar(i-1) + chunks[i] | ||||||
|  | 	} | ||||||
|  | 	return str | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Select(i interface{}, query string, args ...interface{}) ([]interface{}, error) { | ||||||
|  | 	return tx.Tx.Select(i, tx.Rebind(query), args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) { | ||||||
|  | 	return tx.Tx.Exec(tx.Rebind(query), args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) SelectInt(query string, args ...interface{}) (int64, error) { | ||||||
|  | 	return tx.Tx.SelectInt(tx.Rebind(query), args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) SelectOne(holder interface{}, query string, args ...interface{}) error { | ||||||
|  | 	return tx.Tx.SelectOne(holder, tx.Rebind(query), args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Insert(list ...interface{}) error { | ||||||
|  | 	return tx.Tx.Insert(list...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Update(list ...interface{}) (int64, error) { | ||||||
|  | 	return tx.Tx.Update(list...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Delete(list ...interface{}) (int64, error) { | ||||||
|  | 	return tx.Tx.Delete(list...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Commit() error { | ||||||
|  | 	return tx.Tx.Commit() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tx *Tx) Rollback() error { | ||||||
|  | 	return tx.Tx.Rollback() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetTx(db *gorp.DbMap) (*Tx, error) { | ||||||
|  | 	tx, err := db.Begin() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &Tx{db.Dialect, tx}, nil | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user