2017-10-04 19:35:59 -04:00
|
|
|
package handlers
|
2015-06-25 22:36:58 -04:00
|
|
|
|
2015-06-27 17:46:06 -04:00
|
|
|
import (
|
|
|
|
"errors"
|
2017-12-03 06:38:22 -05:00
|
|
|
"github.com/aclindsa/moneygo/internal/models"
|
2017-12-07 20:47:55 -05:00
|
|
|
"github.com/aclindsa/moneygo/internal/store"
|
2015-06-27 17:46:06 -04:00
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
// Get (and attempt to create if it doesn't exist). Matches on UserId,
|
|
|
|
// SecurityId, Type, Name, and ParentAccountId
|
2017-12-09 05:56:45 -05:00
|
|
|
func GetCreateAccount(tx store.Tx, a models.Account) (*models.Account, error) {
|
2017-12-04 05:55:25 -05:00
|
|
|
var account models.Account
|
2016-02-10 18:36:11 -05:00
|
|
|
|
2017-12-07 20:47:55 -05:00
|
|
|
accounts, err := tx.FindMatchingAccounts(&a)
|
2016-02-10 18:36:11 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-12-07 20:47:55 -05:00
|
|
|
if len(*accounts) > 0 {
|
|
|
|
account = *(*accounts)[0]
|
2016-02-10 18:36:11 -05:00
|
|
|
} else {
|
2016-02-15 11:28:44 -05:00
|
|
|
account.UserId = a.UserId
|
|
|
|
account.SecurityId = a.SecurityId
|
|
|
|
account.Type = a.Type
|
|
|
|
account.Name = a.Name
|
|
|
|
account.ParentAccountId = a.ParentAccountId
|
2016-02-10 18:36:11 -05:00
|
|
|
|
2017-12-09 05:56:45 -05:00
|
|
|
err = tx.InsertAccount(&account)
|
2016-02-11 05:53:44 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &account, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get (and attempt to create if it doesn't exist) the security/currency
|
2016-02-15 11:28:44 -05:00
|
|
|
// trading account for the supplied security/currency
|
2017-12-09 05:56:45 -05:00
|
|
|
func GetTradingAccount(tx store.Tx, userid int64, securityid int64) (*models.Account, error) {
|
2017-12-04 05:55:25 -05:00
|
|
|
var tradingAccount models.Account
|
|
|
|
var account models.Account
|
2016-02-11 05:53:44 -05:00
|
|
|
|
2017-12-07 20:08:43 -05:00
|
|
|
user, err := tx.GetUser(userid)
|
2017-09-21 21:00:30 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
tradingAccount.UserId = userid
|
2017-12-04 05:55:25 -05:00
|
|
|
tradingAccount.Type = models.Trading
|
2016-02-15 11:28:44 -05:00
|
|
|
tradingAccount.Name = "Trading"
|
2017-09-21 21:00:30 -04:00
|
|
|
tradingAccount.SecurityId = user.DefaultCurrency
|
2016-02-15 11:28:44 -05:00
|
|
|
tradingAccount.ParentAccountId = -1
|
|
|
|
|
|
|
|
// Find/create the top-level trading account
|
2017-10-14 19:41:13 -04:00
|
|
|
ta, err := GetCreateAccount(tx, tradingAccount)
|
2016-02-11 05:53:44 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-12-07 20:08:43 -05:00
|
|
|
security, err := tx.GetSecurity(securityid, userid)
|
2016-10-16 08:19:11 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
account.UserId = userid
|
|
|
|
account.Name = security.Name
|
|
|
|
account.ParentAccountId = ta.AccountId
|
|
|
|
account.SecurityId = securityid
|
2017-12-04 05:55:25 -05:00
|
|
|
account.Type = models.Trading
|
2016-02-15 11:28:44 -05:00
|
|
|
|
2017-10-14 19:41:13 -04:00
|
|
|
a, err := GetCreateAccount(tx, account)
|
2016-02-11 05:53:44 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get (and attempt to create if it doesn't exist) the security/currency
|
|
|
|
// imbalance account for the supplied security/currency
|
2017-12-09 05:56:45 -05:00
|
|
|
func GetImbalanceAccount(tx store.Tx, userid int64, securityid int64) (*models.Account, error) {
|
2017-12-04 05:55:25 -05:00
|
|
|
var imbalanceAccount models.Account
|
|
|
|
var account models.Account
|
2017-12-03 06:38:22 -05:00
|
|
|
xxxtemplate := FindSecurityTemplate("XXX", models.Currency)
|
2017-06-04 16:01:42 -04:00
|
|
|
if xxxtemplate == nil {
|
|
|
|
return nil, errors.New("Couldn't find XXX security template")
|
|
|
|
}
|
2017-10-14 19:41:13 -04:00
|
|
|
xxxsecurity, err := ImportGetCreateSecurity(tx, userid, xxxtemplate)
|
2017-06-04 16:01:42 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("Couldn't create XXX security")
|
|
|
|
}
|
2016-02-11 05:53:44 -05:00
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
imbalanceAccount.UserId = userid
|
|
|
|
imbalanceAccount.Name = "Imbalances"
|
|
|
|
imbalanceAccount.ParentAccountId = -1
|
2017-06-04 16:01:42 -04:00
|
|
|
imbalanceAccount.SecurityId = xxxsecurity.SecurityId
|
2017-12-04 05:55:25 -05:00
|
|
|
imbalanceAccount.Type = models.Bank
|
2016-02-15 11:28:44 -05:00
|
|
|
|
|
|
|
// Find/create the top-level trading account
|
2017-10-14 19:41:13 -04:00
|
|
|
ia, err := GetCreateAccount(tx, imbalanceAccount)
|
2016-02-11 05:53:44 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-12-07 20:08:43 -05:00
|
|
|
security, err := tx.GetSecurity(securityid, userid)
|
2016-10-16 08:19:11 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
account.UserId = userid
|
|
|
|
account.Name = security.Name
|
|
|
|
account.ParentAccountId = ia.AccountId
|
|
|
|
account.SecurityId = securityid
|
2017-12-04 05:55:25 -05:00
|
|
|
account.Type = models.Bank
|
2016-02-10 18:36:11 -05:00
|
|
|
|
2017-10-14 19:41:13 -04:00
|
|
|
a, err := GetCreateAccount(tx, account)
|
2016-02-10 18:36:11 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-02-15 11:28:44 -05:00
|
|
|
return a, nil
|
2016-02-10 18:36:11 -05:00
|
|
|
}
|
|
|
|
|
2017-11-12 20:17:27 -05:00
|
|
|
func AccountHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|
|
|
user, err := GetUserFromSession(context.Tx, r)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(1 /*Not Signed In*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if r.Method == "POST" {
|
2017-11-12 21:12:49 -05:00
|
|
|
if !context.LastLevel() {
|
|
|
|
accountid, err := context.NextID()
|
|
|
|
if err != nil || context.NextLevel() != "imports" {
|
|
|
|
return NewError(3 /*Invalid Request*/)
|
2016-02-02 21:46:27 -05:00
|
|
|
}
|
2017-11-12 21:12:49 -05:00
|
|
|
return AccountImportHandler(context, r, user, accountid)
|
2016-02-02 21:46:27 -05:00
|
|
|
}
|
|
|
|
|
2017-12-04 05:55:25 -05:00
|
|
|
var account models.Account
|
2017-11-13 20:48:19 -05:00
|
|
|
if err := ReadJSON(r, &account); err != nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
account.AccountId = -1
|
|
|
|
account.UserId = user.UserId
|
2015-08-05 21:25:25 -04:00
|
|
|
account.AccountVersion = 0
|
2015-06-27 17:46:06 -04:00
|
|
|
|
2017-12-07 20:08:43 -05:00
|
|
|
security, err := context.Tx.GetSecurity(account.SecurityId, user.UserId)
|
2016-10-16 08:19:11 -04:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2016-10-16 08:19:11 -04:00
|
|
|
}
|
|
|
|
if security == nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
2017-12-07 20:47:55 -05:00
|
|
|
err = context.Tx.InsertAccount(&account)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-12-07 20:47:55 -05:00
|
|
|
if _, ok := err.(store.ParentAccountMissingError); ok {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
} else {
|
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-14 14:20:50 -04:00
|
|
|
return ResponseWrapper{201, &account}
|
2015-06-27 17:46:06 -04:00
|
|
|
} else if r.Method == "GET" {
|
2017-11-12 21:12:49 -05:00
|
|
|
if context.LastLevel() {
|
2015-06-27 17:46:06 -04:00
|
|
|
//Return all Accounts
|
2017-12-04 05:55:25 -05:00
|
|
|
var al models.AccountList
|
2017-12-07 20:47:55 -05:00
|
|
|
accounts, err := context.Tx.GetAccounts(user.UserId)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
al.Accounts = accounts
|
2017-10-14 14:20:50 -04:00
|
|
|
return &al
|
2017-11-12 21:12:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
accountid, err := context.NextID()
|
|
|
|
if err != nil {
|
|
|
|
return NewError(3 /*Invalid Request*/)
|
|
|
|
}
|
2015-07-11 08:58:36 -04:00
|
|
|
|
2017-11-12 21:12:49 -05:00
|
|
|
if context.LastLevel() {
|
2015-06-29 07:25:48 -04:00
|
|
|
// Return Account with this Id
|
2017-12-07 20:47:55 -05:00
|
|
|
account, err := context.Tx.GetAccount(accountid, user.UserId)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
2015-07-11 08:58:36 -04:00
|
|
|
|
2017-10-14 14:20:50 -04:00
|
|
|
return account
|
2017-11-12 21:12:49 -05:00
|
|
|
} else if context.NextLevel() == "transactions" {
|
|
|
|
return AccountTransactionsHandler(context, r, user, accountid)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
} else {
|
2017-11-12 21:12:49 -05:00
|
|
|
accountid, err := context.NextID()
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
if r.Method == "PUT" {
|
2017-12-04 05:55:25 -05:00
|
|
|
var account models.Account
|
2017-11-13 20:48:19 -05:00
|
|
|
if err := ReadJSON(r, &account); err != nil || account.AccountId != accountid {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
account.UserId = user.UserId
|
|
|
|
|
2017-12-07 20:08:43 -05:00
|
|
|
security, err := context.Tx.GetSecurity(account.SecurityId, user.UserId)
|
2016-10-16 08:19:11 -04:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2016-10-16 08:19:11 -04:00
|
|
|
}
|
|
|
|
if security == nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
2017-10-11 21:19:14 -04:00
|
|
|
if account.ParentAccountId == account.AccountId {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2017-10-11 21:19:14 -04:00
|
|
|
}
|
|
|
|
|
2017-12-07 20:47:55 -05:00
|
|
|
err = context.Tx.UpdateAccount(&account)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-12-07 20:47:55 -05:00
|
|
|
if _, ok := err.(store.ParentAccountMissingError); ok {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2017-12-07 20:47:55 -05:00
|
|
|
} else if _, ok := err.(store.CircularAccountsError); ok {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2017-10-11 21:19:14 -04:00
|
|
|
} else {
|
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2017-10-11 21:19:14 -04:00
|
|
|
}
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
2017-10-14 14:20:50 -04:00
|
|
|
return &account
|
2015-06-27 17:46:06 -04:00
|
|
|
} else if r.Method == "DELETE" {
|
2017-12-07 20:47:55 -05:00
|
|
|
account, err := context.Tx.GetAccount(accountid, user.UserId)
|
2015-06-27 17:46:06 -04:00
|
|
|
if err != nil {
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
2017-12-07 20:47:55 -05:00
|
|
|
err = context.Tx.DeleteAccount(account)
|
2015-06-29 07:25:48 -04:00
|
|
|
if err != nil {
|
2015-06-27 17:46:06 -04:00
|
|
|
log.Print(err)
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(999 /*Internal Error*/)
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
|
2017-10-14 14:20:50 -04:00
|
|
|
return SuccessWriter{}
|
2015-06-27 17:46:06 -04:00
|
|
|
}
|
|
|
|
}
|
2017-10-14 14:20:50 -04:00
|
|
|
return NewError(3 /*Invalid Request*/)
|
2015-06-25 22:36:58 -04:00
|
|
|
}
|