mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 16:07:33 +08:00
support storing geo location in transaction
This commit is contained in:
+20
-4
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -572,7 +573,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *
|
||||
|
||||
transactionEditable := transaction.IsEditable(user, utcOffset, accountMap[transaction.AccountId], accountMap[transaction.RelatedAccountId])
|
||||
transactionTagIds := allTransactionTagIds[transaction.TransactionId]
|
||||
transactionResp := transaction.ToTransactionInfoResponse(transactionTagIds, transactionEditable)
|
||||
transactionResp := transaction.ToTransactionInfoResponse(c, transactionTagIds, transactionEditable)
|
||||
|
||||
if !transactionGetReq.TrimAccount {
|
||||
if sourceAccount := accountMap[transaction.AccountId]; sourceAccount != nil {
|
||||
@@ -664,7 +665,7 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.Context) (interface{}
|
||||
|
||||
log.InfofWithRequestId(c, "[transactions.TransactionCreateHandler] user \"uid:%d\" has created a new transaction \"id:%d\" successfully", uid, transaction.TransactionId)
|
||||
|
||||
transactionResp := transaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
transactionResp := transaction.ToTransactionInfoResponse(c, tagIds, transactionEditable)
|
||||
|
||||
return transactionResp, nil
|
||||
}
|
||||
@@ -722,6 +723,12 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{}
|
||||
transactionTagIds = make([]int64, 0, 0)
|
||||
}
|
||||
|
||||
var geoLocation []byte
|
||||
|
||||
if transactionModifyReq.GeoLocation != nil {
|
||||
geoLocation, _ = json.Marshal(transactionModifyReq.GeoLocation)
|
||||
}
|
||||
|
||||
newTransaction := &models.Transaction{
|
||||
TransactionId: transaction.TransactionId,
|
||||
Uid: uid,
|
||||
@@ -732,6 +739,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{}
|
||||
Amount: transactionModifyReq.SourceAmount,
|
||||
HideAmount: transactionModifyReq.HideAmount,
|
||||
Comment: transactionModifyReq.Comment,
|
||||
GeoLocation: string(geoLocation),
|
||||
}
|
||||
|
||||
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT {
|
||||
@@ -748,6 +756,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{}
|
||||
(transaction.Type != models.TRANSACTION_DB_TYPE_TRANSFER_OUT || newTransaction.RelatedAccountAmount == transaction.RelatedAccountAmount) &&
|
||||
newTransaction.HideAmount == transaction.HideAmount &&
|
||||
newTransaction.Comment == transaction.Comment &&
|
||||
newTransaction.GeoLocation == transaction.GeoLocation &&
|
||||
utils.Int64SliceEquals(tagIds, transactionTagIds) {
|
||||
return nil, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
@@ -777,7 +786,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{}
|
||||
log.InfofWithRequestId(c, "[transactions.TransactionModifyHandler] user \"uid:%d\" has updated transaction \"id:%d\" successfully", uid, transactionModifyReq.Id)
|
||||
|
||||
newTransaction.Type = transaction.Type
|
||||
newTransactionResp := newTransaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
newTransactionResp := newTransaction.ToTransactionInfoResponse(c, tagIds, transactionEditable)
|
||||
|
||||
return newTransactionResp, nil
|
||||
}
|
||||
@@ -1004,7 +1013,7 @@ func (a *TransactionsApi) getTransactionListResult(c *core.Context, user *models
|
||||
|
||||
transactionEditable := transaction.IsEditable(user, utcOffset, allAccounts[transaction.AccountId], allAccounts[transaction.RelatedAccountId])
|
||||
transactionTagIds := allTransactionTagIds[transaction.TransactionId]
|
||||
result[i] = transaction.ToTransactionInfoResponse(transactionTagIds, transactionEditable)
|
||||
result[i] = transaction.ToTransactionInfoResponse(c, transactionTagIds, transactionEditable)
|
||||
|
||||
if !trimAccount {
|
||||
if sourceAccount := allAccounts[transaction.AccountId]; sourceAccount != nil {
|
||||
@@ -1045,6 +1054,12 @@ func (a *TransactionsApi) createNewTransactionModel(uid int64, transactionCreate
|
||||
transactionDbType = models.TRANSACTION_DB_TYPE_TRANSFER_OUT
|
||||
}
|
||||
|
||||
var geoLocation []byte
|
||||
|
||||
if transactionCreateReq.GeoLocation != nil {
|
||||
geoLocation, _ = json.Marshal(transactionCreateReq.GeoLocation)
|
||||
}
|
||||
|
||||
transaction := &models.Transaction{
|
||||
Uid: uid,
|
||||
Type: transactionDbType,
|
||||
@@ -1055,6 +1070,7 @@ func (a *TransactionsApi) createNewTransactionModel(uid int64, transactionCreate
|
||||
Amount: transactionCreateReq.SourceAmount,
|
||||
HideAmount: transactionCreateReq.HideAmount,
|
||||
Comment: transactionCreateReq.Comment,
|
||||
GeoLocation: string(geoLocation),
|
||||
CreatedIp: clientIp,
|
||||
}
|
||||
|
||||
|
||||
+54
-23
@@ -1,11 +1,14 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
@@ -48,40 +51,49 @@ type Transaction struct {
|
||||
RelatedAccountAmount int64 `xorm:"NOT NULL"`
|
||||
HideAmount bool `xorm:"NOT NULL"`
|
||||
Comment string `xorm:"VARCHAR(255) NOT NULL"`
|
||||
GeoLocation string `xorm:"VARCHAR(255)"`
|
||||
CreatedIp string `xorm:"VARCHAR(39)"`
|
||||
CreatedUnixTime int64
|
||||
UpdatedUnixTime int64
|
||||
DeletedUnixTime int64
|
||||
}
|
||||
|
||||
// TransactionGeoLocationRequest represents all parameters of transaction geographic location info update request
|
||||
type TransactionGeoLocationRequest struct {
|
||||
Latitude float64 `json:"latitude" binding:"required"`
|
||||
Longitude float64 `json:"longitude" binding:"required"`
|
||||
}
|
||||
|
||||
// TransactionCreateRequest represents all parameters of transaction creation request
|
||||
type TransactionCreateRequest struct {
|
||||
Type TransactionType `json:"type" binding:"required"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Time int64 `json:"time" binding:"required,min=1"`
|
||||
UtcOffset int16 `json:"utcOffset" binding:"min=-720,max=840"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"`
|
||||
SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
Type TransactionType `json:"type" binding:"required"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Time int64 `json:"time" binding:"required,min=1"`
|
||||
UtcOffset int16 `json:"utcOffset" binding:"min=-720,max=840"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"`
|
||||
SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
GeoLocation *TransactionGeoLocationRequest `json:"geoLocation" binding:"omitempty"`
|
||||
}
|
||||
|
||||
// TransactionModifyRequest represents all parameters of transaction modification request
|
||||
type TransactionModifyRequest struct {
|
||||
Id int64 `json:"id,string" binding:"required,min=1"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Time int64 `json:"time" binding:"required,min=1"`
|
||||
UtcOffset int16 `json:"utcOffset" binding:"min=-720,max=840"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"`
|
||||
SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
Id int64 `json:"id,string" binding:"required,min=1"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Time int64 `json:"time" binding:"required,min=1"`
|
||||
UtcOffset int16 `json:"utcOffset" binding:"min=-720,max=840"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string" binding:"required,min=1"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string" binding:"min=0"`
|
||||
SourceAmount int64 `json:"sourceAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
GeoLocation *TransactionGeoLocationRequest `json:"geoLocation" binding:"omitempty"`
|
||||
}
|
||||
|
||||
// TransactionCountRequest represents transaction count request
|
||||
@@ -170,6 +182,12 @@ type TransactionAccountAmount struct {
|
||||
TotalExpenseAmount int64
|
||||
}
|
||||
|
||||
// TransactionGeoLocationResponse represents a view-object of transaction geographic location info
|
||||
type TransactionGeoLocationResponse struct {
|
||||
Latitude float64 `json:"latitude"`
|
||||
Longitude float64 `json:"longitude"`
|
||||
}
|
||||
|
||||
// TransactionInfoResponse represents a view-object of transaction
|
||||
type TransactionInfoResponse struct {
|
||||
Id int64 `json:"id,string"`
|
||||
@@ -189,6 +207,7 @@ type TransactionInfoResponse struct {
|
||||
TagIds []string `json:"tagIds"`
|
||||
Tags []*TransactionTagInfoResponse `json:"tags,omitempty"`
|
||||
Comment string `json:"comment"`
|
||||
GeoLocation *TransactionGeoLocationResponse `json:"geoLocation,omitempty"`
|
||||
Editable bool `json:"editable"`
|
||||
}
|
||||
|
||||
@@ -264,7 +283,7 @@ func (t *Transaction) IsEditable(currentUser *User, utcOffset int16, account *Ac
|
||||
}
|
||||
|
||||
// ToTransactionInfoResponse returns a view-object according to database model
|
||||
func (t *Transaction) ToTransactionInfoResponse(tagIds []int64, editable bool) *TransactionInfoResponse {
|
||||
func (t *Transaction) ToTransactionInfoResponse(c *core.Context, tagIds []int64, editable bool) *TransactionInfoResponse {
|
||||
var transactionType TransactionType
|
||||
|
||||
if t.Type == TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
@@ -298,6 +317,17 @@ func (t *Transaction) ToTransactionInfoResponse(tagIds []int64, editable bool) *
|
||||
destinationAmount = t.Amount
|
||||
}
|
||||
|
||||
geoLocation := &TransactionGeoLocationResponse{}
|
||||
|
||||
if t.GeoLocation != "" {
|
||||
err := json.Unmarshal([]byte(t.GeoLocation), geoLocation)
|
||||
if err != nil {
|
||||
log.WarnfWithRequestId(c, "[transaction.ToTransactionInfoResponse] cannot unmarshal geo location \"%s\", because %s", t.GeoLocation, err.Error())
|
||||
}
|
||||
} else {
|
||||
geoLocation = nil
|
||||
}
|
||||
|
||||
return &TransactionInfoResponse{
|
||||
Id: t.TransactionId,
|
||||
TimeSequenceId: t.TransactionTime,
|
||||
@@ -312,6 +342,7 @@ func (t *Transaction) ToTransactionInfoResponse(tagIds []int64, editable bool) *
|
||||
HideAmount: t.HideAmount,
|
||||
TagIds: utils.Int64ArrayToStringArray(tagIds),
|
||||
Comment: t.Comment,
|
||||
GeoLocation: geoLocation,
|
||||
Editable: editable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,6 +542,10 @@ func (s *TransactionService) ModifyTransaction(transaction *models.Transaction,
|
||||
updateCols = append(updateCols, "comment")
|
||||
}
|
||||
|
||||
if transaction.GeoLocation != oldTransaction.GeoLocation {
|
||||
updateCols = append(updateCols, "geo_location")
|
||||
}
|
||||
|
||||
// Get and verify tags
|
||||
err = s.isTagsValid(sess, transaction, transactionTagIndexs, addTagIds)
|
||||
|
||||
@@ -955,6 +959,7 @@ func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *
|
||||
RelatedAccountId: originalTransaction.AccountId,
|
||||
RelatedAccountAmount: originalTransaction.Amount,
|
||||
Comment: originalTransaction.Comment,
|
||||
GeoLocation: originalTransaction.GeoLocation,
|
||||
CreatedIp: originalTransaction.CreatedIp,
|
||||
CreatedUnixTime: originalTransaction.CreatedUnixTime,
|
||||
UpdatedUnixTime: originalTransaction.UpdatedUnixTime,
|
||||
|
||||
Reference in New Issue
Block a user