mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 09:14:27 +08:00
add transaction pictures api
This commit is contained in:
+17
-3
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/avatars"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/duplicatechecker"
|
||||
@@ -22,9 +23,22 @@ func (a *ApiUsingConfig) CurrentConfig() *settings.Config {
|
||||
}
|
||||
|
||||
// GetTransactionPictureInfoResponse returns the view-object of transaction picture basic info according to the transaction picture model
|
||||
func (a *ApiUsingConfig) GetTransactionPictureInfoResponse(picture *models.TransactionPictureInfo) *models.TransactionPictureInfoBasicResponse {
|
||||
originalUrl := fmt.Sprintf(internalTransactionPictureUrlFormat, a.CurrentConfig().RootUrl, picture.PictureId, picture.PictureExtension)
|
||||
return picture.ToTransactionPictureInfoBasicResponse(originalUrl)
|
||||
func (a *ApiUsingConfig) GetTransactionPictureInfoResponse(pictureInfo *models.TransactionPictureInfo) *models.TransactionPictureInfoBasicResponse {
|
||||
originalUrl := fmt.Sprintf(internalTransactionPictureUrlFormat, a.CurrentConfig().RootUrl, pictureInfo.PictureId, pictureInfo.PictureExtension)
|
||||
return pictureInfo.ToTransactionPictureInfoBasicResponse(originalUrl)
|
||||
}
|
||||
|
||||
// GetTransactionPictureInfoResponseList returns the view-object list of transaction picture basic info according to the transaction picture model
|
||||
func (a *ApiUsingConfig) GetTransactionPictureInfoResponseList(pictureInfos []*models.TransactionPictureInfo) models.TransactionPictureInfoBasicResponseSlice {
|
||||
pictureInfoResps := make(models.TransactionPictureInfoBasicResponseSlice, len(pictureInfos))
|
||||
|
||||
for i := 0; i < len(pictureInfos); i++ {
|
||||
pictureInfoResps[i] = a.GetTransactionPictureInfoResponse(pictureInfos[i])
|
||||
}
|
||||
|
||||
sort.Sort(pictureInfoResps)
|
||||
|
||||
return pictureInfoResps
|
||||
}
|
||||
|
||||
// GetAfterRegisterNotificationContent returns the notification content displayed each time users register
|
||||
|
||||
@@ -26,9 +26,9 @@ type DataManagementsApi struct {
|
||||
users *services.UserService
|
||||
accounts *services.AccountService
|
||||
transactions *services.TransactionService
|
||||
pictures *services.TransactionPictureService
|
||||
categories *services.TransactionCategoryService
|
||||
tags *services.TransactionTagService
|
||||
pictures *services.TransactionPictureService
|
||||
templates *services.TransactionTemplateService
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ var (
|
||||
users: services.Users,
|
||||
accounts: services.Accounts,
|
||||
transactions: services.Transactions,
|
||||
pictures: services.TransactionPictures,
|
||||
categories: services.TransactionCategories,
|
||||
tags: services.TransactionTags,
|
||||
pictures: services.TransactionPictures,
|
||||
templates: services.TransactionTemplates,
|
||||
}
|
||||
)
|
||||
@@ -158,13 +158,6 @@ func (a *DataManagementsApi) ClearDataHandler(c *core.WebContext) (any, *errs.Er
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
err = a.pictures.DeleteAllPictures(c, uid)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[data_managements.ClearDataHandler] failed to delete all transaction pictures, because %s", err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
err = a.transactions.DeleteAllTransactions(c, uid)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -147,6 +147,7 @@ func (a *TransactionPicturesApi) TransactionPictureGetHandler(c *core.WebContext
|
||||
func (a *TransactionPicturesApi) createNewPictureInfoModel(uid int64, fileExtension string, clientIp string) *models.TransactionPictureInfo {
|
||||
return &models.TransactionPictureInfo{
|
||||
Uid: uid,
|
||||
TransactionId: models.TransactionPictureNewPictureTransactionId,
|
||||
PictureExtension: fileExtension,
|
||||
CreatedIp: clientIp,
|
||||
}
|
||||
|
||||
+132
-14
@@ -23,6 +23,7 @@ type TransactionsApi struct {
|
||||
transactions *services.TransactionService
|
||||
transactionCategories *services.TransactionCategoryService
|
||||
transactionTags *services.TransactionTagService
|
||||
transactionPictures *services.TransactionPictureService
|
||||
accounts *services.AccountService
|
||||
users *services.UserService
|
||||
}
|
||||
@@ -39,6 +40,7 @@ var (
|
||||
transactions: services.Transactions,
|
||||
transactionCategories: services.TransactionCategories,
|
||||
transactionTags: services.TransactionTags,
|
||||
transactionPictures: services.TransactionPictures,
|
||||
accounts: services.Accounts,
|
||||
users: services.Users,
|
||||
}
|
||||
@@ -177,7 +179,7 @@ func (a *TransactionsApi) TransactionListHandler(c *core.WebContext) (any, *errs
|
||||
transactions = transactions[:transactionListReq.Count]
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionListResult(c, user, transactions, utcOffset, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, utcOffset, transactionListReq.WithPictures, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionListHandler] failed to assemble transaction result for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -260,7 +262,7 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.WebContext) (any,
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionListResult(c, user, transactions, utcOffset, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, utcOffset, transactionListReq.WithPictures, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionMonthListHandler] failed to assemble transaction result for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -567,6 +569,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.WebContext) (any, *errs.
|
||||
|
||||
var category *models.TransactionCategory
|
||||
var tagMap map[int64]*models.TransactionTag
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
|
||||
if !transactionGetReq.TrimCategory {
|
||||
category, err = a.transactionCategories.GetCategoryByCategoryId(c, uid, transaction.CategoryId)
|
||||
@@ -586,6 +589,15 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.WebContext) (any, *errs.
|
||||
}
|
||||
}
|
||||
|
||||
if transactionGetReq.WithPictures {
|
||||
pictureInfos, err = a.transactionPictures.GetPictureInfosByTransactionId(c, uid, transaction.TransactionId)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionGetHandler] failed to get transactions pictures for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
}
|
||||
|
||||
transactionEditable := transaction.IsEditable(user, utcOffset, accountMap[transaction.AccountId], accountMap[transaction.RelatedAccountId])
|
||||
transactionTagIds := allTransactionTagIds[transaction.TransactionId]
|
||||
transactionResp := transaction.ToTransactionInfoResponse(transactionTagIds, transactionEditable)
|
||||
@@ -610,6 +622,10 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.WebContext) (any, *errs.
|
||||
transactionResp.Tags = a.getTransactionTagInfoResponses(transactionTagIds, tagMap)
|
||||
}
|
||||
|
||||
if transactionGetReq.WithPictures {
|
||||
transactionResp.Pictures = a.GetTransactionPictureInfoResponseList(pictureInfos)
|
||||
}
|
||||
|
||||
return transactionResp, nil
|
||||
}
|
||||
|
||||
@@ -630,6 +646,13 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.ErrTransactionTagIdInvalid
|
||||
}
|
||||
|
||||
pictureIds, err := utils.StringArrayToInt64Array(transactionCreateReq.PictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionCreateHandler] parse picture ids failed, because %s", err.Error())
|
||||
return nil, errs.ErrTransactionPictureIdInvalid
|
||||
}
|
||||
|
||||
if transactionCreateReq.Type < models.TRANSACTION_TYPE_MODIFY_BALANCE || transactionCreateReq.Type > models.TRANSACTION_TYPE_TRANSFER {
|
||||
log.Warnf(c, "[transactions.TransactionCreateHandler] transaction type is invalid")
|
||||
return nil, errs.ErrTransactionTypeInvalid
|
||||
@@ -671,6 +694,24 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.ErrCannotCreateTransactionWithThisTransactionTime
|
||||
}
|
||||
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
|
||||
if len(pictureIds) > 0 {
|
||||
pictureInfos, err = a.transactionPictures.GetNewPictureInfosByPictureIds(c, uid, pictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionCreateHandler] failed to get transactions pictures for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
notExistsPictureIds := utils.Int64SliceMinus(pictureIds, a.transactionPictures.GetTransactionPictureIds(pictureInfos))
|
||||
|
||||
if len(notExistsPictureIds) > 0 {
|
||||
log.Errorf(c, "[transactions.TransactionCreateHandler] some pictures \"ids:%s\" does not exists for user \"uid:%d\"", strings.Join(utils.Int64ArrayToStringArray(notExistsPictureIds), ","), uid)
|
||||
return nil, errs.ErrTransactionPictureNotFound
|
||||
}
|
||||
}
|
||||
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && transactionCreateReq.ClientSessionId != "" {
|
||||
found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId)
|
||||
|
||||
@@ -687,13 +728,14 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
}
|
||||
|
||||
transactionResp := transaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
transactionResp.Pictures = a.GetTransactionPictureInfoResponseList(pictureInfos)
|
||||
|
||||
return transactionResp, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = a.transactions.CreateTransaction(c, transaction, tagIds)
|
||||
err = a.transactions.CreateTransaction(c, transaction, tagIds, pictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionCreateHandler] failed to create transaction \"id:%d\" for user \"uid:%d\", because %s", transaction.TransactionId, uid, err.Error())
|
||||
@@ -704,6 +746,7 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
|
||||
a.SetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, transactionCreateReq.ClientSessionId, utils.Int64ToString(transaction.TransactionId))
|
||||
transactionResp := transaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
transactionResp.Pictures = a.GetTransactionPictureInfoResponseList(pictureInfos)
|
||||
|
||||
return transactionResp, nil
|
||||
}
|
||||
@@ -725,6 +768,13 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.ErrTransactionTagIdInvalid
|
||||
}
|
||||
|
||||
pictureIds, err := utils.StringArrayToInt64Array(transactionModifyReq.PictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionModifyHandler] parse picture ids failed, because %s", err.Error())
|
||||
return nil, errs.ErrTransactionPictureIdInvalid
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
user, err := a.users.GetUserById(c, uid)
|
||||
|
||||
@@ -761,6 +811,15 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
transactionTagIds = make([]int64, 0, 0)
|
||||
}
|
||||
|
||||
transactionPictureInfos, err := a.transactionPictures.GetPictureInfosByTransactionId(c, uid, transaction.TransactionId)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionModifyHandler] failed to get transaction picture infos for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
transactionPictureIds := a.transactionPictures.GetTransactionPictureIds(transactionPictureInfos)
|
||||
|
||||
newTransaction := &models.Transaction{
|
||||
TransactionId: transaction.TransactionId,
|
||||
Uid: uid,
|
||||
@@ -794,10 +853,18 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
newTransaction.Comment == transaction.Comment &&
|
||||
newTransaction.GeoLongitude == transaction.GeoLongitude &&
|
||||
newTransaction.GeoLatitude == transaction.GeoLatitude &&
|
||||
utils.Int64SliceEquals(tagIds, transactionTagIds) {
|
||||
utils.Int64SliceEquals(tagIds, transactionTagIds) &&
|
||||
utils.Int64SliceEquals(pictureIds, transactionPictureIds) {
|
||||
return nil, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transaction.TimezoneUtcOffset)
|
||||
newTransactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, transactionModifyReq.UtcOffset)
|
||||
|
||||
if !transactionEditable || !newTransactionEditable {
|
||||
return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime
|
||||
}
|
||||
|
||||
var addTransactionTagIds []int64
|
||||
var removeTransactionTagIds []int64
|
||||
|
||||
@@ -806,14 +873,46 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
addTransactionTagIds = tagIds
|
||||
}
|
||||
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transaction.TimezoneUtcOffset)
|
||||
newTransactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, transactionModifyReq.UtcOffset)
|
||||
addTransactionPictureIds := utils.Int64SliceMinus(pictureIds, transactionPictureIds)
|
||||
removeTransactionPictureIds := utils.Int64SliceMinus(transactionPictureIds, pictureIds)
|
||||
var newPictureInfos []*models.TransactionPictureInfo
|
||||
|
||||
if !transactionEditable || !newTransactionEditable {
|
||||
return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime
|
||||
if !utils.Int64SliceEquals(pictureIds, transactionPictureIds) {
|
||||
oldAndNewPictureIds := transactionPictureIds
|
||||
oldAndNewPictureInfoMap := a.transactionPictures.GetPictureInfoMapByList(transactionPictureInfos)
|
||||
|
||||
if len(addTransactionPictureIds) > 0 {
|
||||
addPictureInfos, err := a.transactionPictures.GetNewPictureInfosByPictureIds(c, uid, addTransactionPictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionModifyHandler] failed to get transactions pictures for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
oldAndNewPictureIds = append(oldAndNewPictureIds, a.transactionPictures.GetTransactionPictureIds(addPictureInfos)...)
|
||||
notExistsPictureIds := utils.Int64SliceMinus(pictureIds, oldAndNewPictureIds)
|
||||
|
||||
if len(notExistsPictureIds) > 0 {
|
||||
log.Errorf(c, "[transactions.TransactionModifyHandler] some pictures \"ids:%s\" does not exists for user \"uid:%d\"", strings.Join(utils.Int64ArrayToStringArray(notExistsPictureIds), ","), uid)
|
||||
return nil, errs.ErrTransactionPictureNotFound
|
||||
}
|
||||
|
||||
for i := 0; i < len(addPictureInfos); i++ {
|
||||
oldAndNewPictureInfoMap[addPictureInfos[i].PictureId] = addPictureInfos[i]
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(pictureIds); i++ {
|
||||
pictureId := pictureIds[i]
|
||||
pictureInfo, exists := oldAndNewPictureInfoMap[pictureId]
|
||||
|
||||
if exists {
|
||||
newPictureInfos = append(newPictureInfos, pictureInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = a.transactions.ModifyTransaction(c, newTransaction, len(transactionTagIds), addTransactionTagIds, removeTransactionTagIds)
|
||||
err = a.transactions.ModifyTransaction(c, newTransaction, len(transactionTagIds), addTransactionTagIds, removeTransactionTagIds, addTransactionPictureIds, removeTransactionPictureIds)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionModifyHandler] failed to update transaction \"id:%d\" for user \"uid:%d\", because %s", transactionModifyReq.Id, uid, err.Error())
|
||||
@@ -824,6 +923,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
|
||||
newTransaction.Type = transaction.Type
|
||||
newTransactionResp := newTransaction.ToTransactionInfoResponse(tagIds, transactionEditable)
|
||||
newTransactionResp.Pictures = a.GetTransactionPictureInfoResponseList(newPictureInfos)
|
||||
|
||||
return newTransactionResp, nil
|
||||
}
|
||||
@@ -1053,7 +1153,7 @@ func (a *TransactionsApi) getTransactionTagInfoResponses(tagIds []int64, allTran
|
||||
return allTags
|
||||
}
|
||||
|
||||
func (a *TransactionsApi) getTransactionListResult(c *core.WebContext, user *models.User, transactions []*models.Transaction, utcOffset int16, trimAccount bool, trimCategory bool, trimTag bool) (models.TransactionInfoResponseSlice, error) {
|
||||
func (a *TransactionsApi) getTransactionResponseListResult(c *core.WebContext, user *models.User, transactions []*models.Transaction, utcOffset int16, withPictures bool, trimAccount bool, trimCategory bool, trimTag bool) (models.TransactionInfoResponseSlice, error) {
|
||||
uid := user.Uid
|
||||
transactionIds := make([]int64, len(transactions))
|
||||
accountIds := make([]int64, 0, len(transactions)*2)
|
||||
@@ -1079,7 +1179,7 @@ func (a *TransactionsApi) getTransactionListResult(c *core.WebContext, user *mod
|
||||
allAccounts, err := a.accounts.GetAccountsByAccountIds(c, uid, utils.ToUniqueInt64Slice(accountIds))
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.getTransactionListResult] failed to get accounts for user \"uid:%d\", because %s", uid, err.Error())
|
||||
log.Errorf(c, "[transactions.getTransactionResponseListResult] failed to get accounts for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1088,18 +1188,19 @@ func (a *TransactionsApi) getTransactionListResult(c *core.WebContext, user *mod
|
||||
allTransactionTagIds, err := a.transactionTags.GetAllTagIdsOfTransactions(c, uid, transactionIds)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.getTransactionListResult] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error())
|
||||
log.Errorf(c, "[transactions.getTransactionResponseListResult] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var categoryMap map[int64]*models.TransactionCategory
|
||||
var tagMap map[int64]*models.TransactionTag
|
||||
var pictureInfoMap map[int64][]*models.TransactionPictureInfo
|
||||
|
||||
if !trimCategory {
|
||||
categoryMap, err = a.transactionCategories.GetCategoriesByCategoryIds(c, uid, utils.ToUniqueInt64Slice(categoryIds))
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.getTransactionListResult] failed to get transactions categories for user \"uid:%d\", because %s", uid, err.Error())
|
||||
log.Errorf(c, "[transactions.getTransactionResponseListResult] failed to get transactions categories for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -1108,7 +1209,16 @@ func (a *TransactionsApi) getTransactionListResult(c *core.WebContext, user *mod
|
||||
tagMap, err = a.transactionTags.GetTagsByTagIds(c, uid, utils.ToUniqueInt64Slice(a.getTransactionTagIds(allTransactionTagIds)))
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.getTransactionListResult] failed to get transactions tags for user \"uid:%d\", because %s", uid, err.Error())
|
||||
log.Errorf(c, "[transactions.getTransactionResponseListResult] failed to get transactions tags for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if withPictures {
|
||||
pictureInfoMap, err = a.transactionPictures.GetPictureInfosByTransactionIds(c, uid, utils.ToUniqueInt64Slice(a.transactions.GetTransactionIds(transactions)))
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.getTransactionResponseListResult] failed to get transactions pictures for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -1145,6 +1255,14 @@ func (a *TransactionsApi) getTransactionListResult(c *core.WebContext, user *mod
|
||||
if !trimTag {
|
||||
result[i].Tags = a.getTransactionTagInfoResponses(transactionTagIds, tagMap)
|
||||
}
|
||||
|
||||
if withPictures {
|
||||
pictureInfos, exists := pictureInfoMap[transaction.TransactionId]
|
||||
|
||||
if exists {
|
||||
result[i].Pictures = a.GetTransactionPictureInfoResponseList(pictureInfos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(result)
|
||||
|
||||
+25
-19
@@ -73,6 +73,7 @@ type TransactionCreateRequest struct {
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
PictureIds []string `json:"pictureIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
GeoLocation *TransactionGeoLocationRequest `json:"geoLocation" binding:"omitempty"`
|
||||
ClientSessionId string `json:"clientSessionId"`
|
||||
@@ -90,6 +91,7 @@ type TransactionModifyRequest struct {
|
||||
DestinationAmount int64 `json:"destinationAmount" binding:"min=-99999999999,max=99999999999"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
PictureIds []string `json:"pictureIds"`
|
||||
Comment string `json:"comment" binding:"max=255"`
|
||||
GeoLocation *TransactionGeoLocationRequest `json:"geoLocation" binding:"omitempty"`
|
||||
}
|
||||
@@ -119,6 +121,7 @@ type TransactionListByMaxTimeRequest struct {
|
||||
Page int32 `form:"page" binding:"min=0"`
|
||||
Count int32 `form:"count" binding:"required,min=1,max=50"`
|
||||
WithCount bool `form:"with_count"`
|
||||
WithPictures bool `form:"with_pictures"`
|
||||
TrimAccount bool `form:"trim_account"`
|
||||
TrimCategory bool `form:"trim_category"`
|
||||
TrimTag bool `form:"trim_tag"`
|
||||
@@ -134,6 +137,7 @@ type TransactionListInMonthByPageRequest struct {
|
||||
TagIds string `form:"tag_ids"`
|
||||
AmountFilter string `form:"amount_filter" binding:"validAmountFilter"`
|
||||
Keyword string `form:"keyword"`
|
||||
WithPictures bool `form:"with_pictures"`
|
||||
TrimAccount bool `form:"trim_account"`
|
||||
TrimCategory bool `form:"trim_category"`
|
||||
TrimTag bool `form:"trim_tag"`
|
||||
@@ -168,6 +172,7 @@ type TransactionAmountsRequestItem struct {
|
||||
// TransactionGetRequest represents all parameters of transaction getting request
|
||||
type TransactionGetRequest struct {
|
||||
Id int64 `form:"id,string" binding:"required,min=1"`
|
||||
WithPictures bool `form:"with_pictures"`
|
||||
TrimAccount bool `form:"trim_account"`
|
||||
TrimCategory bool `form:"trim_category"`
|
||||
TrimTag bool `form:"trim_tag"`
|
||||
@@ -192,25 +197,26 @@ type TransactionGeoLocationResponse struct {
|
||||
|
||||
// TransactionInfoResponse represents a view-object of transaction
|
||||
type TransactionInfoResponse struct {
|
||||
Id int64 `json:"id,string"`
|
||||
TimeSequenceId int64 `json:"timeSequenceId,string"`
|
||||
Type TransactionType `json:"type"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Category *TransactionCategoryInfoResponse `json:"category,omitempty"`
|
||||
Time int64 `json:"time"`
|
||||
UtcOffset int16 `json:"utcOffset"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string"`
|
||||
SourceAccount *AccountInfoResponse `json:"sourceAccount,omitempty"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string,omitempty"`
|
||||
DestinationAccount *AccountInfoResponse `json:"destinationAccount,omitempty"`
|
||||
SourceAmount int64 `json:"sourceAmount"`
|
||||
DestinationAmount int64 `json:"destinationAmount,omitempty"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Tags []*TransactionTagInfoResponse `json:"tags,omitempty"`
|
||||
Comment string `json:"comment"`
|
||||
GeoLocation *TransactionGeoLocationResponse `json:"geoLocation,omitempty"`
|
||||
Editable bool `json:"editable"`
|
||||
Id int64 `json:"id,string"`
|
||||
TimeSequenceId int64 `json:"timeSequenceId,string"`
|
||||
Type TransactionType `json:"type"`
|
||||
CategoryId int64 `json:"categoryId,string"`
|
||||
Category *TransactionCategoryInfoResponse `json:"category,omitempty"`
|
||||
Time int64 `json:"time"`
|
||||
UtcOffset int16 `json:"utcOffset"`
|
||||
SourceAccountId int64 `json:"sourceAccountId,string"`
|
||||
SourceAccount *AccountInfoResponse `json:"sourceAccount,omitempty"`
|
||||
DestinationAccountId int64 `json:"destinationAccountId,string,omitempty"`
|
||||
DestinationAccount *AccountInfoResponse `json:"destinationAccount,omitempty"`
|
||||
SourceAmount int64 `json:"sourceAmount"`
|
||||
DestinationAmount int64 `json:"destinationAmount,omitempty"`
|
||||
HideAmount bool `json:"hideAmount"`
|
||||
TagIds []string `json:"tagIds"`
|
||||
Tags []*TransactionTagInfoResponse `json:"tags,omitempty"`
|
||||
Pictures TransactionPictureInfoBasicResponseSlice `json:"pictures,omitempty"`
|
||||
Comment string `json:"comment"`
|
||||
GeoLocation *TransactionGeoLocationResponse `json:"geoLocation,omitempty"`
|
||||
Editable bool `json:"editable"`
|
||||
}
|
||||
|
||||
// TransactionCountResponse represents transaction count response
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package models
|
||||
|
||||
const TransactionPictureNewPictureTransactionId = int64(0)
|
||||
|
||||
// TransactionPictureInfo represents transaction picture file info stored in database
|
||||
type TransactionPictureInfo struct {
|
||||
Uid int64 `xorm:"INDEX(IDX_transaction_picture_uid_deleted_transaction_id_picture_id) INDEX(IDX_transaction_picture_uid_deleted_picture_id) NOT NULL"`
|
||||
@@ -26,3 +28,21 @@ func (p *TransactionPictureInfo) ToTransactionPictureInfoBasicResponse(originalU
|
||||
OriginalUrl: originalUrl,
|
||||
}
|
||||
}
|
||||
|
||||
// TransactionPictureInfoBasicResponseSlice represents the slice data structure of TransactionPictureInfoBasicResponse
|
||||
type TransactionPictureInfoBasicResponseSlice []*TransactionPictureInfoBasicResponse
|
||||
|
||||
// Len returns the count of items
|
||||
func (s TransactionPictureInfoBasicResponseSlice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Swap swaps two items
|
||||
func (s TransactionPictureInfoBasicResponseSlice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Less reports whether the first item is less than the second one
|
||||
func (s TransactionPictureInfoBasicResponseSlice) Less(i, j int) bool {
|
||||
return s[i].PictureId < s[j].PictureId
|
||||
}
|
||||
|
||||
@@ -71,6 +71,67 @@ func (s *TransactionPictureService) GetPictureInfoByPictureId(c core.Context, ui
|
||||
return pictureInfo, nil
|
||||
}
|
||||
|
||||
// GetNewPictureInfosByPictureIds returns new transaction picture info models according to transaction picture ids
|
||||
func (s *TransactionPictureService) GetNewPictureInfosByPictureIds(c core.Context, uid int64, pictureIds []int64) ([]*models.TransactionPictureInfo, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
if pictureIds == nil {
|
||||
return nil, errs.ErrTransactionPictureIdInvalid
|
||||
}
|
||||
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
err := s.UserDataDB(uid).NewSession(c).Where("uid=? AND deleted=? AND transaction_id=?", uid, false, models.TransactionPictureNewPictureTransactionId).In("picture_id", pictureIds).OrderBy("picture_id asc").Find(&pictureInfos)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pictureInfos, nil
|
||||
}
|
||||
|
||||
// GetPictureInfosByTransactionId returns transaction picture info models according to transaction id
|
||||
func (s *TransactionPictureService) GetPictureInfosByTransactionId(c core.Context, uid int64, transactionId int64) ([]*models.TransactionPictureInfo, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
if transactionId <= 0 {
|
||||
return nil, errs.ErrTransactionIdInvalid
|
||||
}
|
||||
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
err := s.UserDataDB(uid).NewSession(c).Where("uid=? AND deleted=? AND transaction_id=?", uid, false, transactionId).OrderBy("picture_id asc").Find(&pictureInfos)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pictureInfos, nil
|
||||
}
|
||||
|
||||
// GetPictureInfosByTransactionIds returns transaction picture info models according to transaction ids
|
||||
func (s *TransactionPictureService) GetPictureInfosByTransactionIds(c core.Context, uid int64, transactionIds []int64) (map[int64][]*models.TransactionPictureInfo, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
if transactionIds == nil {
|
||||
return nil, errs.ErrTransactionIdInvalid
|
||||
}
|
||||
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
err := s.UserDataDB(uid).NewSession(c).Where("uid=? AND deleted=?", uid, false).In("transaction_id", transactionIds).OrderBy("picture_id asc").Find(&pictureInfos)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pictureInfoMap := s.GetPictureInfoListMapByList(pictureInfos)
|
||||
return pictureInfoMap, err
|
||||
}
|
||||
|
||||
// GetPictureByPictureId returns the transaction picture data according to transaction picture id
|
||||
func (s *TransactionPictureService) GetPictureByPictureId(c core.Context, uid int64, pictureId int64, fileExtension string) ([]byte, error) {
|
||||
if uid <= 0 {
|
||||
@@ -150,26 +211,39 @@ func (s *TransactionPictureService) UploadPicture(c core.Context, pictureInfo *m
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteAllPictures deletes all existed transaction pictures from database
|
||||
func (s *TransactionPictureService) DeleteAllPictures(c core.Context, uid int64) error {
|
||||
if uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
// GetPictureInfoMapByList returns a transaction picture info list map by a list
|
||||
func (s *TransactionPictureService) GetPictureInfoMapByList(pictureInfos []*models.TransactionPictureInfo) map[int64]*models.TransactionPictureInfo {
|
||||
pictureInfoMap := make(map[int64]*models.TransactionPictureInfo)
|
||||
|
||||
for i := 0; i < len(pictureInfos); i++ {
|
||||
pictureInfo := pictureInfos[i]
|
||||
pictureInfoMap[pictureInfo.PictureId] = pictureInfo
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
|
||||
updateModel := &models.TransactionPictureInfo{
|
||||
Deleted: true,
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
|
||||
_, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).Update(updateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return pictureInfoMap
|
||||
}
|
||||
|
||||
// GetPictureInfoListMapByList returns a transaction picture info list map by a list
|
||||
func (s *TransactionPictureService) GetPictureInfoListMapByList(pictureInfos []*models.TransactionPictureInfo) map[int64][]*models.TransactionPictureInfo {
|
||||
pictureInfoMap := make(map[int64][]*models.TransactionPictureInfo)
|
||||
|
||||
for i := 0; i < len(pictureInfos); i++ {
|
||||
pictureInfo := pictureInfos[i]
|
||||
|
||||
pictureInfos, _ := pictureInfoMap[pictureInfo.TransactionId]
|
||||
pictureInfoMap[pictureInfo.TransactionId] = append(pictureInfos, pictureInfo)
|
||||
}
|
||||
|
||||
return pictureInfoMap
|
||||
}
|
||||
|
||||
// GetTransactionPictureIds returns transaction picture ids list
|
||||
func (s *TransactionPictureService) GetTransactionPictureIds(pictureInfos []*models.TransactionPictureInfo) []int64 {
|
||||
pictureIds := make([]int64, len(pictureInfos))
|
||||
|
||||
for i := 0; i < len(pictureInfos); i++ {
|
||||
pictureIds[i] = pictureInfos[i].PictureId
|
||||
}
|
||||
|
||||
return pictureIds
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ func (s *TransactionService) GetTransactionCount(c core.Context, uid int64, maxT
|
||||
}
|
||||
|
||||
// CreateTransaction saves a new transaction to database
|
||||
func (s *TransactionService) CreateTransaction(c core.Context, transaction *models.Transaction, tagIds []int64) error {
|
||||
func (s *TransactionService) CreateTransaction(c core.Context, transaction *models.Transaction, tagIds []int64, pictureIds []int64) error {
|
||||
if transaction.Uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
@@ -261,6 +261,11 @@ func (s *TransactionService) CreateTransaction(c core.Context, transaction *mode
|
||||
}
|
||||
}
|
||||
|
||||
pictureUpdateModel := &models.TransactionPictureInfo{
|
||||
TransactionId: transaction.TransactionId,
|
||||
UpdatedUnixTime: now,
|
||||
}
|
||||
|
||||
return s.UserDataDB(transaction.Uid).DoTransaction(c, func(sess *xorm.Session) error {
|
||||
// Get and verify source and destination account
|
||||
sourceAccount, destinationAccount, err := s.getAccountModels(sess, transaction)
|
||||
@@ -296,6 +301,13 @@ func (s *TransactionService) CreateTransaction(c core.Context, transaction *mode
|
||||
return err
|
||||
}
|
||||
|
||||
// Get and verify pictures
|
||||
err = s.isPicturesValid(sess, transaction, pictureIds)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify balance modification transaction and calculate real amount
|
||||
if transaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
otherTransactionExists, err := sess.Cols("uid", "deleted", "account_id").Where("uid=? AND deleted=? AND account_id=?", transaction.Uid, false, sourceAccount.AccountId).Limit(1).Exist(&models.Transaction{})
|
||||
@@ -376,6 +388,15 @@ func (s *TransactionService) CreateTransaction(c core.Context, transaction *mode
|
||||
}
|
||||
}
|
||||
|
||||
// Update transaction picture
|
||||
if len(pictureIds) > 0 {
|
||||
_, err = sess.Cols("transaction_id", "updated_unix_time").Where("uid=? AND deleted=? AND transaction_id=?", transaction.Uid, false, models.TransactionPictureNewPictureTransactionId).In("picture_id", pictureIds).Update(pictureUpdateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update account table
|
||||
if transaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
sourceAccount.UpdatedUnixTime = time.Now().Unix()
|
||||
@@ -543,7 +564,7 @@ func (s *TransactionService) CreateScheduledTransactions(c core.Context, current
|
||||
}
|
||||
|
||||
tagIds := template.GetTagIds()
|
||||
err = s.CreateTransaction(c, transaction, tagIds)
|
||||
err = s.CreateTransaction(c, transaction, tagIds, nil)
|
||||
|
||||
if err == nil {
|
||||
successCount++
|
||||
@@ -560,7 +581,7 @@ func (s *TransactionService) CreateScheduledTransactions(c core.Context, current
|
||||
}
|
||||
|
||||
// ModifyTransaction saves an existed transaction to database
|
||||
func (s *TransactionService) ModifyTransaction(c core.Context, transaction *models.Transaction, currentTagIdsCount int, addTagIds []int64, removeTagIds []int64) error {
|
||||
func (s *TransactionService) ModifyTransaction(c core.Context, transaction *models.Transaction, currentTagIdsCount int, addTagIds []int64, removeTagIds []int64, addPictureIds []int64, removePictureIds []int64) error {
|
||||
if transaction.Uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
@@ -736,6 +757,13 @@ func (s *TransactionService) ModifyTransaction(c core.Context, transaction *mode
|
||||
return err
|
||||
}
|
||||
|
||||
// Get and verify pictures
|
||||
err = s.isPicturesValid(sess, transaction, addPictureIds)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update transaction row
|
||||
updatedRows, err := sess.ID(transaction.TransactionId).Cols(updateCols...).Where("uid=? AND deleted=?", transaction.Uid, false).Update(transaction)
|
||||
|
||||
@@ -801,6 +829,35 @@ func (s *TransactionService) ModifyTransaction(c core.Context, transaction *mode
|
||||
}
|
||||
}
|
||||
|
||||
// Update transaction picture
|
||||
if len(removePictureIds) > 0 {
|
||||
pictureUpdateModel := &models.TransactionPictureInfo{
|
||||
Deleted: true,
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
deletedRows, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=? AND transaction_id=?", transaction.Uid, false, transaction.TransactionId).In("picture_id", removePictureIds).Update(pictureUpdateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if deletedRows < 1 {
|
||||
return errs.ErrTransactionPictureNotFound
|
||||
}
|
||||
}
|
||||
|
||||
if len(addPictureIds) > 0 {
|
||||
pictureUpdateModel := &models.TransactionPictureInfo{
|
||||
TransactionId: transaction.TransactionId,
|
||||
UpdatedUnixTime: now,
|
||||
}
|
||||
|
||||
_, err = sess.Cols("transaction_id", "updated_unix_time").Where("uid=? AND deleted=? AND transaction_id=?", transaction.Uid, false, models.TransactionPictureNewPictureTransactionId).In("picture_id", addPictureIds).Update(pictureUpdateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update account table
|
||||
if oldTransaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
if transaction.AccountId != oldTransaction.AccountId {
|
||||
@@ -973,6 +1030,11 @@ func (s *TransactionService) DeleteTransaction(c core.Context, uid int64, transa
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
pictureUpdateModel := &models.TransactionPictureInfo{
|
||||
Deleted: true,
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
|
||||
// Get and verify current transaction
|
||||
oldTransaction := &models.Transaction{}
|
||||
@@ -1025,6 +1087,13 @@ func (s *TransactionService) DeleteTransaction(c core.Context, uid int64, transa
|
||||
return err
|
||||
}
|
||||
|
||||
// Update transaction picture
|
||||
_, err = sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=? AND transaction_id=?", uid, false, oldTransaction.TransactionId).Update(pictureUpdateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update account table
|
||||
if oldTransaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
sourceAccount.UpdatedUnixTime = time.Now().Unix()
|
||||
@@ -1097,6 +1166,11 @@ func (s *TransactionService) DeleteAllTransactions(c core.Context, uid int64) er
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
pictureUpdateModel := &models.TransactionPictureInfo{
|
||||
Deleted: true,
|
||||
DeletedUnixTime: now,
|
||||
}
|
||||
|
||||
accountUpdateModel := &models.Account{
|
||||
Balance: 0,
|
||||
Deleted: true,
|
||||
@@ -1118,6 +1192,13 @@ func (s *TransactionService) DeleteAllTransactions(c core.Context, uid int64) er
|
||||
return err
|
||||
}
|
||||
|
||||
// Update all transaction picture to deleted
|
||||
_, err = sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).Update(pictureUpdateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update all account table to deleted
|
||||
_, err = sess.Cols("balance", "deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).Update(accountUpdateModel)
|
||||
|
||||
@@ -1495,6 +1576,17 @@ func (s *TransactionService) GetTransactionMapByList(transactions []*models.Tran
|
||||
return transactionMap
|
||||
}
|
||||
|
||||
// GetTransactionIds returns transaction ids list
|
||||
func (s *TransactionService) GetTransactionIds(transactions []*models.Transaction) []int64 {
|
||||
transactionIds := make([]int64, len(transactions))
|
||||
|
||||
for i := 0; i < len(transactions); i++ {
|
||||
transactionIds[i] = transactions[i].TransactionId
|
||||
}
|
||||
|
||||
return transactionIds
|
||||
}
|
||||
|
||||
func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, tagIds []int64, amountFilter string, keyword string, noDuplicated bool) (string, []any) {
|
||||
condition := "uid=? AND deleted=?"
|
||||
conditionParams := make([]any, 0, 16)
|
||||
@@ -1924,3 +2016,32 @@ func (s *TransactionService) isTagsValid(sess *xorm.Session, transaction *models
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TransactionService) isPicturesValid(sess *xorm.Session, transaction *models.Transaction, pictureIds []int64) error {
|
||||
if len(pictureIds) > 0 {
|
||||
var pictureInfos []*models.TransactionPictureInfo
|
||||
err := sess.Where("uid=? AND deleted=?", transaction.Uid, false).In("picture_id", pictureIds).Find(&pictureInfos)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pictureInfoMap := make(map[int64]*models.TransactionPictureInfo)
|
||||
|
||||
for i := 0; i < len(pictureInfos); i++ {
|
||||
if pictureInfos[i].TransactionId != models.TransactionPictureNewPictureTransactionId && pictureInfos[i].TransactionId != transaction.TransactionId {
|
||||
return errs.ErrTransactionPictureIdInvalid
|
||||
}
|
||||
|
||||
pictureInfoMap[pictureInfos[i].PictureId] = pictureInfos[i]
|
||||
}
|
||||
|
||||
for i := 0; i < len(pictureIds); i++ {
|
||||
if _, exists := pictureInfoMap[pictureIds[i]]; !exists {
|
||||
return errs.ErrTransactionPictureNotFound
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+11
-3
@@ -394,9 +394,9 @@ export default {
|
||||
return axios.get(`v1/transactions/amounts.json?use_transaction_timezone=${useTransactionTimezone}` + (queryParams.length ? '&query=' + queryParams.join('|') : ''));
|
||||
},
|
||||
getTransaction: ({ id }) => {
|
||||
return axios.get(`v1/transactions/get.json?id=${id}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
return axios.get(`v1/transactions/get.json?id=${id}&with_pictures=true&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
},
|
||||
addTransaction: ({ type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, geoLocation, utcOffset, clientSessionId }) => {
|
||||
addTransaction: ({ type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, pictureIds, comment, geoLocation, utcOffset, clientSessionId }) => {
|
||||
return axios.post('v1/transactions/add.json', {
|
||||
type,
|
||||
categoryId,
|
||||
@@ -407,13 +407,14 @@ export default {
|
||||
destinationAmount,
|
||||
hideAmount,
|
||||
tagIds,
|
||||
pictureIds,
|
||||
comment,
|
||||
geoLocation,
|
||||
utcOffset,
|
||||
clientSessionId
|
||||
});
|
||||
},
|
||||
modifyTransaction: ({ id, type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, geoLocation, utcOffset }) => {
|
||||
modifyTransaction: ({ id, type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, pictureIds, comment, geoLocation, utcOffset }) => {
|
||||
return axios.post('v1/transactions/modify.json', {
|
||||
id,
|
||||
type,
|
||||
@@ -425,6 +426,7 @@ export default {
|
||||
destinationAmount,
|
||||
hideAmount,
|
||||
tagIds,
|
||||
pictureIds,
|
||||
comment,
|
||||
geoLocation,
|
||||
utcOffset
|
||||
@@ -435,6 +437,12 @@ export default {
|
||||
id
|
||||
});
|
||||
},
|
||||
uploadTransactionPicture: ({ pictureFile, clientSessionId }) => {
|
||||
return axios.postForm('v1/transaction/pictures/upload.json', {
|
||||
picture: pictureFile,
|
||||
clientSessionId: clientSessionId
|
||||
});
|
||||
},
|
||||
getAllTransactionCategories: () => {
|
||||
return axios.get('v1/transaction/categories/list.json');
|
||||
},
|
||||
|
||||
@@ -1414,6 +1414,7 @@
|
||||
"Transaction": "Transaction",
|
||||
"Transactions": "Transactions",
|
||||
"Transaction Pictures": "Transaction Pictures",
|
||||
"Pictures": "Pictures",
|
||||
"Add Transaction": "Add Transaction",
|
||||
"Edit Transaction": "Edit Transaction",
|
||||
"Add Transaction Template": "Add Transaction Template",
|
||||
@@ -1465,6 +1466,7 @@
|
||||
"Unable to save transaction": "Unable to save transaction",
|
||||
"You have added a new transaction": "You have added a new transaction",
|
||||
"You have saved this transaction": "You have saved this transaction",
|
||||
"Unable to upload transaction picture": "Unable to upload transaction picture",
|
||||
"Search transaction description": "Search transaction description",
|
||||
"Unable to retrieve transaction list": "Unable to retrieve transaction list",
|
||||
"Custom Date Range": "Custom Date Range",
|
||||
|
||||
@@ -1414,6 +1414,7 @@
|
||||
"Transaction": "交易",
|
||||
"Transactions": "交易",
|
||||
"Transaction Pictures": "交易图片",
|
||||
"Pictures": "图片",
|
||||
"Add Transaction": "添加交易",
|
||||
"Edit Transaction": "编辑交易",
|
||||
"Add Transaction Template": "添加交易模板",
|
||||
@@ -1465,6 +1466,7 @@
|
||||
"Unable to save transaction": "无法保存交易",
|
||||
"You have added a new transaction": "您已经添加新交易",
|
||||
"You have saved this transaction": "您已经保存该交易",
|
||||
"Unable to upload transaction picture": "无法上传交易图片",
|
||||
"Search transaction description": "搜索交易描述",
|
||||
"Unable to retrieve transaction list": "无法获取交易列表",
|
||||
"Custom Date Range": "自定义日期范围",
|
||||
|
||||
@@ -864,6 +864,18 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
return Promise.reject('An error occurred');
|
||||
}
|
||||
|
||||
if (transaction.pictures && transaction.pictures.length > 0) {
|
||||
const pictureIds = [];
|
||||
|
||||
for (let i = 0; i < transaction.pictures.length; i++) {
|
||||
if (transaction.pictures[i].pictureId) {
|
||||
pictureIds.push(transaction.pictures[i].pictureId);
|
||||
}
|
||||
}
|
||||
|
||||
transaction.pictureIds = pictureIds;
|
||||
}
|
||||
|
||||
if (isEdit) {
|
||||
submitTransaction.id = transaction.id;
|
||||
}
|
||||
@@ -991,6 +1003,30 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
});
|
||||
});
|
||||
},
|
||||
uploadTransactionPicture({ pictureFile, clientSessionId }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
services.uploadTransactionPicture({ pictureFile, clientSessionId }).then(response => {
|
||||
const data = response.data;
|
||||
|
||||
if (!data || !data.success || !data.result) {
|
||||
reject({ message: 'Unable to upload transaction picture' });
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(data.result);
|
||||
}).catch(error => {
|
||||
logger.error('Unable to upload transaction picture', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
reject({ error: error.response.data });
|
||||
} else if (!error.processed) {
|
||||
reject({ message: 'Unable to upload transaction picture' });
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
collapseMonthInTransactionList({ month, collapse }) {
|
||||
if (month) {
|
||||
month.opened = !collapse;
|
||||
|
||||
Reference in New Issue
Block a user