support storing geo location in transaction

This commit is contained in:
MaysWind
2023-04-28 21:22:12 +08:00
parent 1ac968f63c
commit e71ffd1a77
9 changed files with 207 additions and 30 deletions
+20 -4
View File
@@ -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
View File
@@ -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,
}
}
+5
View File
@@ -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,