fix the dates in Statistics & Analysis page does not be processed for daylight saving time
This commit is contained in:
+2
-2
@@ -150,7 +150,7 @@ func (a *AccountsApi) AccountCreateHandler(c *core.WebContext) (any, *errs.Error
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
_, utcOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[accounts.AccountCreateHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
@@ -315,7 +315,7 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error
|
||||
return nil, errs.ErrAccountIdInvalid
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
_, utcOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[accounts.AccountModifyHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
|
||||
@@ -302,13 +302,11 @@ func (a *DataManagementsApi) getExportedFileContent(c *core.WebContext, fileType
|
||||
return nil, "", errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
timezone := time.Local
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
timezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[data_managements.getExportedFileContent] cannot get client timezone offset, because %s", err.Error())
|
||||
} else {
|
||||
timezone = time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
timezone = time.Local
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
@@ -47,14 +47,13 @@ func (a *LargeLanguageModelsApi) RecognizeReceiptImageHandler(c *core.WebContext
|
||||
return nil, errs.ErrLargeLanguageModelProviderNotEnabled
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, utcOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[large_language_models.RecognizeReceiptImageHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[large_language_models.RecognizeReceiptImageHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
timezone := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
uid := c.GetCurrentUid()
|
||||
user, err := a.users.GetUserById(c, uid)
|
||||
|
||||
@@ -197,7 +196,7 @@ func (a *LargeLanguageModelsApi) RecognizeReceiptImageHandler(c *core.WebContext
|
||||
}
|
||||
|
||||
systemPromptParams := map[string]any{
|
||||
"CurrentDateTime": utils.FormatUnixTimeToLongDateTime(time.Now().Unix(), timezone),
|
||||
"CurrentDateTime": utils.FormatUnixTimeToLongDateTime(time.Now().Unix(), clientTimezone),
|
||||
"AllExpenseCategoryNames": strings.Join(expenseCategoryNames, "\n"),
|
||||
"AllIncomeCategoryNames": strings.Join(incomeCategoryNames, "\n"),
|
||||
"AllTransferCategoryNames": strings.Join(transferCategoryNames, "\n"),
|
||||
|
||||
+59
-37
@@ -7,6 +7,7 @@ import (
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
|
||||
@@ -120,10 +121,10 @@ func (a *TransactionsApi) TransactionListHandler(c *core.WebContext) (any, *errs
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionListHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionListHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -191,7 +192,7 @@ func (a *TransactionsApi) TransactionListHandler(c *core.WebContext) (any, *errs
|
||||
transactions = transactions[:transactionListReq.Count]
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, utcOffset, transactionListReq.WithPictures, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, clientTimezone, 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())
|
||||
@@ -223,10 +224,10 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.WebContext) (any,
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionMonthListHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionMonthListHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -274,7 +275,7 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.WebContext) (any,
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, utcOffset, transactionListReq.WithPictures, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, clientTimezone, 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())
|
||||
@@ -299,10 +300,10 @@ func (a *TransactionsApi) TransactionListAllHandler(c *core.WebContext) (any, *e
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionListAllHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionListAllHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -361,7 +362,7 @@ func (a *TransactionsApi) TransactionListAllHandler(c *core.WebContext) (any, *e
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, allTransactions, utcOffset, transactionAllListReq.WithPictures, transactionAllListReq.TrimAccount, transactionAllListReq.TrimCategory, transactionAllListReq.TrimTag)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, allTransactions, clientTimezone, transactionAllListReq.WithPictures, transactionAllListReq.TrimAccount, transactionAllListReq.TrimCategory, transactionAllListReq.TrimTag)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionListAllHandler] failed to assemble transaction result for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -381,10 +382,10 @@ func (a *TransactionsApi) TransactionReconciliationStatementHandler(c *core.WebC
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionReconciliationStatementHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionReconciliationStatementHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -440,7 +441,7 @@ func (a *TransactionsApi) TransactionReconciliationStatementHandler(c *core.WebC
|
||||
transactionAccountBalanceMap[transactionWithBalance.RelatedId] = transactionWithBalance
|
||||
}
|
||||
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, utcOffset, false, true, true, true)
|
||||
transactionResult, err := a.getTransactionResponseListResult(c, user, transactions, clientTimezone, false, true, true, true)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionReconciliationStatementHandler] failed to assemble transaction result for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -489,10 +490,10 @@ func (a *TransactionsApi) TransactionStatisticsHandler(c *core.WebContext) (any,
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, utfOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -509,7 +510,7 @@ func (a *TransactionsApi) TransactionStatisticsHandler(c *core.WebContext) (any,
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
totalAmounts, err := a.transactions.GetAccountsAndCategoriesTotalInflowAndOutflow(c, uid, statisticReq.StartTime, statisticReq.EndTime, tagFilters, noTags, statisticReq.Keyword, utcOffset, statisticReq.UseTransactionTimezone)
|
||||
totalAmounts, err := a.transactions.GetAccountsAndCategoriesTotalInflowAndOutflow(c, uid, statisticReq.StartTime, statisticReq.EndTime, tagFilters, noTags, statisticReq.Keyword, utfOffset, clientTimezone, statisticReq.UseTransactionTimezone)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionStatisticsHandler] failed to get accounts and categories total income and expense for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -550,10 +551,10 @@ func (a *TransactionsApi) TransactionStatisticsTrendsHandler(c *core.WebContext)
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsTrendsHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsTrendsHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -577,7 +578,7 @@ func (a *TransactionsApi) TransactionStatisticsTrendsHandler(c *core.WebContext)
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
allMonthlyTotalAmounts, err := a.transactions.GetAccountsAndCategoriesMonthlyInflowAndOutflow(c, uid, startYear, startMonth, endYear, endMonth, tagFilters, noTags, statisticTrendsReq.Keyword, utcOffset, statisticTrendsReq.UseTransactionTimezone)
|
||||
allMonthlyTotalAmounts, err := a.transactions.GetAccountsAndCategoriesMonthlyInflowAndOutflow(c, uid, startYear, startMonth, endYear, endMonth, tagFilters, noTags, statisticTrendsReq.Keyword, clientTimezone, statisticTrendsReq.UseTransactionTimezone)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionStatisticsTrendsHandler] failed to get accounts and categories total income and expense for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -625,10 +626,10 @@ func (a *TransactionsApi) TransactionStatisticsAssetTrendsHandler(c *core.WebCon
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -646,7 +647,7 @@ func (a *TransactionsApi) TransactionStatisticsAssetTrendsHandler(c *core.WebCon
|
||||
minTransactionTime = utils.GetMinTransactionTimeFromUnixTime(statisticAssetTrendsReq.StartTime)
|
||||
}
|
||||
|
||||
accountDailyBalances, err := a.transactions.GetAllAccountsDailyOpeningAndClosingBalance(c, uid, maxTransactionTime, minTransactionTime, utcOffset)
|
||||
accountDailyBalances, err := a.transactions.GetAllAccountsDailyOpeningAndClosingBalance(c, uid, maxTransactionTime, minTransactionTime, clientTimezone)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] failed to get transactions from \"%d\" to \"%d\" for user \"uid:%d\", because %s", statisticAssetTrendsReq.StartTime, statisticAssetTrendsReq.EndTime, uid, err.Error())
|
||||
@@ -726,10 +727,10 @@ func (a *TransactionsApi) TransactionAmountsHandler(c *core.WebContext) (any, *e
|
||||
}
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, utfOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionAmountsHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionAmountsHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -748,7 +749,7 @@ func (a *TransactionsApi) TransactionAmountsHandler(c *core.WebContext) (any, *e
|
||||
for i := 0; i < len(requestItems); i++ {
|
||||
requestItem := requestItems[i]
|
||||
|
||||
incomeAmounts, expenseAmounts, err := a.transactions.GetAccountsTotalIncomeAndExpense(c, uid, requestItem.StartTime, requestItem.EndTime, excludeAccountIds, excludeCategoryIds, utcOffset, transactionAmountsReq.UseTransactionTimezone)
|
||||
incomeAmounts, expenseAmounts, err := a.transactions.GetAccountsTotalIncomeAndExpense(c, uid, requestItem.StartTime, requestItem.EndTime, excludeAccountIds, excludeCategoryIds, utfOffset, clientTimezone, transactionAmountsReq.UseTransactionTimezone)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionAmountsHandler] failed to get transaction amounts item for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -829,10 +830,10 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.WebContext) (any, *errs.
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionGetHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionGetHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -918,7 +919,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.WebContext) (any, *errs.
|
||||
}
|
||||
}
|
||||
|
||||
transactionEditable := transaction.IsEditable(user, utcOffset, accountMap[transaction.AccountId], accountMap[transaction.RelatedAccountId])
|
||||
transactionEditable := transaction.IsEditable(user, clientTimezone, accountMap[transaction.AccountId], accountMap[transaction.RelatedAccountId])
|
||||
transactionTagIds := allTransactionTagIds[transaction.TransactionId]
|
||||
transactionResp := transaction.ToTransactionInfoResponse(transactionTagIds, transactionEditable)
|
||||
|
||||
@@ -959,6 +960,13 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionCreateHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
tagIds, err := utils.StringArrayToInt64Array(transactionCreateReq.TagIds)
|
||||
|
||||
if err != nil {
|
||||
@@ -1016,7 +1024,7 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.WebContext) (any, *er
|
||||
}
|
||||
|
||||
transaction := a.createNewTransactionModel(uid, &transactionCreateReq, c.ClientIP())
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transactionCreateReq.UtcOffset)
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone)
|
||||
|
||||
if !transactionEditable {
|
||||
return nil, errs.ErrCannotCreateTransactionWithThisTransactionTime
|
||||
@@ -1089,6 +1097,13 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionModifyHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
tagIds, err := utils.StringArrayToInt64Array(transactionModifyReq.TagIds)
|
||||
|
||||
if err != nil {
|
||||
@@ -1202,8 +1217,8 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transaction.TimezoneUtcOffset)
|
||||
newTransactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, transactionModifyReq.UtcOffset)
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone)
|
||||
newTransactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, clientTimezone)
|
||||
|
||||
if !transactionEditable || !newTransactionEditable {
|
||||
return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime
|
||||
@@ -1339,10 +1354,10 @@ func (a *TransactionsApi) TransactionDeleteHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionDeleteHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
log.Warnf(c, "[transactions.TransactionDeleteHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
@@ -1369,7 +1384,7 @@ func (a *TransactionsApi) TransactionDeleteHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.ErrTransactionTypeInvalid
|
||||
}
|
||||
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, utcOffset)
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone)
|
||||
|
||||
if !transactionEditable {
|
||||
return nil, errs.ErrCannotDeleteTransactionWithThisTransactionTime
|
||||
@@ -1473,7 +1488,7 @@ func (a *TransactionsApi) TransactionParseImportFileHandler(c *core.WebContext)
|
||||
return nil, errs.ErrParameterInvalid
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
_, utcOffset, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionParseImportFileHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
@@ -1704,6 +1719,13 @@ func (a *TransactionsApi) TransactionImportHandler(c *core.WebContext) (any, *er
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
clientTimezone, _, err := c.GetClientTimezone()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionImportHandler] cannot get client timezone, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
if a.CurrentConfig().EnableDuplicateSubmissionsCheck && transactionImportReq.ClientSessionId != "" {
|
||||
@@ -1789,7 +1811,7 @@ func (a *TransactionsApi) TransactionImportHandler(c *core.WebContext) (any, *er
|
||||
for i := 0; i < len(transactionImportReq.Transactions); i++ {
|
||||
transactionCreateReq := transactionImportReq.Transactions[i]
|
||||
transaction := a.createNewTransactionModel(uid, transactionCreateReq, c.ClientIP())
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transactionCreateReq.UtcOffset)
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone)
|
||||
|
||||
if !transactionEditable {
|
||||
return nil, errs.ErrCannotCreateTransactionWithThisTransactionTime
|
||||
@@ -1906,7 +1928,7 @@ func (a *TransactionsApi) getTransactionTagInfoResponses(tagIds []int64, allTran
|
||||
return allTags
|
||||
}
|
||||
|
||||
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) {
|
||||
func (a *TransactionsApi) getTransactionResponseListResult(c *core.WebContext, user *models.User, transactions []*models.Transaction, clientTimezone *time.Location, 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)
|
||||
@@ -1985,7 +2007,7 @@ func (a *TransactionsApi) getTransactionResponseListResult(c *core.WebContext, u
|
||||
transaction = a.transactions.GetRelatedTransferTransaction(transaction)
|
||||
}
|
||||
|
||||
transactionEditable := transaction.IsEditable(user, utcOffset, allAccounts[transaction.AccountId], allAccounts[transaction.RelatedAccountId])
|
||||
transactionEditable := transaction.IsEditable(user, clientTimezone, allAccounts[transaction.AccountId], allAccounts[transaction.RelatedAccountId])
|
||||
transactionTagIds := allTransactionTagIds[transaction.TransactionId]
|
||||
result[i] = transaction.ToTransactionInfoResponse(transactionTagIds, transactionEditable)
|
||||
|
||||
|
||||
+37
-6
@@ -4,6 +4,7 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
@@ -25,6 +26,9 @@ const RemoteClientPortHeader = "X-Real-Port"
|
||||
// ClientTimezoneOffsetHeaderName represents the header name of client timezone offset
|
||||
const ClientTimezoneOffsetHeaderName = "X-Timezone-Offset"
|
||||
|
||||
// ClientTimezoneNameHeaderName represents the header name of client timezone name
|
||||
const ClientTimezoneNameHeaderName = "X-Timezone-Name"
|
||||
|
||||
const tokenHeaderName = "Authorization"
|
||||
const tokenHeaderValuePrefix = "bearer "
|
||||
const tokenQueryStringParam = "token"
|
||||
@@ -183,16 +187,24 @@ func (c *WebContext) GetClientLocale() string {
|
||||
return value
|
||||
}
|
||||
|
||||
// GetClientTimezoneOffset returns the client timezone offset
|
||||
func (c *WebContext) GetClientTimezoneOffset() (int16, error) {
|
||||
value := c.GetHeader(ClientTimezoneOffsetHeaderName)
|
||||
offset, err := strconv.Atoi(value)
|
||||
func (c *WebContext) GetClientTimezone() (*time.Location, int16, error) {
|
||||
utcOffset, err := c.getClientTimezoneOffset()
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return int16(offset), nil
|
||||
timezoneName := c.getClientTimezoneName()
|
||||
|
||||
if timezoneName != "" {
|
||||
location, err := time.LoadLocation(timezoneName)
|
||||
|
||||
if err == nil && location != nil {
|
||||
return location, utcOffset, nil
|
||||
}
|
||||
}
|
||||
|
||||
return time.FixedZone("Client Fixed Timezone", int(utcOffset)*60), utcOffset, nil
|
||||
}
|
||||
|
||||
// SetResponseError sets the response error
|
||||
@@ -211,6 +223,25 @@ func (c *WebContext) GetResponseError() *errs.Error {
|
||||
return err.(*errs.Error)
|
||||
}
|
||||
|
||||
// GetClientTimezoneOffset returns the client timezone offset
|
||||
func (c *WebContext) getClientTimezoneOffset() (int16, error) {
|
||||
value := c.GetHeader(ClientTimezoneOffsetHeaderName)
|
||||
offset, err := strconv.Atoi(value)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int16(offset), nil
|
||||
}
|
||||
|
||||
// GetClientTimezoneName returns the client timezone name
|
||||
func (c *WebContext) getClientTimezoneName() string {
|
||||
value := c.GetHeader(ClientTimezoneNameHeaderName)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// WrapWebContext returns a context wrapped by this file
|
||||
func WrapWebContext(ginCtx *gin.Context) *WebContext {
|
||||
return &WebContext{
|
||||
|
||||
@@ -3,6 +3,7 @@ package mcp
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
@@ -177,7 +178,7 @@ func (h *mcpAddTransactionToolHandler) Handle(c *core.WebContext, callToolReq *M
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transaction.TimezoneUtcOffset)
|
||||
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, time.FixedZone("Transaction Timezone", int(transaction.TimezoneUtcOffset)*60))
|
||||
|
||||
if !transactionEditable {
|
||||
return nil, nil, errs.ErrCannotCreateTransactionWithThisTransactionTime
|
||||
|
||||
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
@@ -511,8 +512,8 @@ func ParseTransactionTagFilter(tagFilterStr string) ([]*TransactionTagFilter, er
|
||||
}
|
||||
|
||||
// IsEditable returns whether this transaction can be edited
|
||||
func (t *Transaction) IsEditable(currentUser *User, utcOffset int16, account *Account, relatedAccount *Account) bool {
|
||||
if currentUser == nil || !currentUser.CanEditTransactionByTransactionTime(t.TransactionTime, utcOffset) {
|
||||
func (t *Transaction) IsEditable(currentUser *User, clientTimezone *time.Location, account *Account, relatedAccount *Account) bool {
|
||||
if currentUser == nil || !currentUser.CanEditTransactionByTransactionTime(t.TransactionTime, clientTimezone) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -230,7 +230,7 @@ type UserProfileResponse struct {
|
||||
}
|
||||
|
||||
// CanEditTransactionByTransactionTime returns whether this user can edit transaction with specified transaction time
|
||||
func (u *User) CanEditTransactionByTransactionTime(transactionTime int64, utcOffset int16) bool {
|
||||
func (u *User) CanEditTransactionByTransactionTime(transactionTime int64, clientTimezone *time.Location) bool {
|
||||
if u.TransactionEditScope == TRANSACTION_EDIT_SCOPE_NONE {
|
||||
return false
|
||||
} else if u.TransactionEditScope == TRANSACTION_EDIT_SCOPE_ALL {
|
||||
@@ -245,8 +245,7 @@ func (u *User) CanEditTransactionByTransactionTime(transactionTime int64, utcOff
|
||||
return transactionUnixTime >= now.Unix()-24*60*60
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
clientNow := now.In(clientLocation)
|
||||
clientNow := now.In(clientTimezone)
|
||||
clientTodayFirstUnixTime := clientNow.Unix() - int64(clientNow.Hour()*60*60+clientNow.Minute()*60+clientNow.Second())
|
||||
|
||||
if u.TransactionEditScope == TRANSACTION_EDIT_SCOPE_TODAY_OR_LATER {
|
||||
|
||||
+23
-16
@@ -15,7 +15,8 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsNone(t *testing.T) {
|
||||
TransactionEditScope: TRANSACTION_EDIT_SCOPE_NONE,
|
||||
}
|
||||
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(time.Now().Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(time.Now().Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsAll(t *testing.T) {
|
||||
@@ -23,7 +24,8 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsAll(t *testing.T) {
|
||||
TransactionEditScope: TRANSACTION_EDIT_SCOPE_ALL,
|
||||
}
|
||||
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(time.Now().Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(time.Now().Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsTodayOrLater(t *testing.T) {
|
||||
@@ -32,13 +34,14 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsTodayOrLater(t *testing.
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
todayFirstDatetime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
|
||||
yesterdayLastDatetime := todayFirstDatetime.Add(-1 * time.Second)
|
||||
todayLastDatetime := yesterdayLastDatetime.Add(24 * time.Hour)
|
||||
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(todayFirstDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(todayLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(yesterdayLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(todayFirstDatetime.Unix()), timezone))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(todayLastDatetime.Unix()), timezone))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(yesterdayLastDatetime.Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsLast24HourOrLater(t *testing.T) {
|
||||
@@ -47,10 +50,11 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsLast24HourOrLater(t *tes
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
twentyfourHourBeforeDatetime := now.Add(-24 * time.Hour).Add(-1 * time.Second)
|
||||
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(twentyfourHourBeforeDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(twentyfourHourBeforeDatetime.Add(1*time.Second).Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(twentyfourHourBeforeDatetime.Unix()), timezone))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(twentyfourHourBeforeDatetime.Add(1*time.Second).Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsThisWeekOrLater(t *testing.T) {
|
||||
@@ -60,6 +64,7 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsThisWeekOrLater(t *testi
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
thisWeekFirstDatetime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
|
||||
|
||||
if thisWeekFirstDatetime.Weekday() == time.Sunday {
|
||||
@@ -71,9 +76,9 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsThisWeekOrLater(t *testi
|
||||
lastWeekLastDatetime := thisWeekFirstDatetime.Add(-1 * time.Second)
|
||||
thisWeekLastDatetime := lastWeekLastDatetime.Add(24 * time.Hour)
|
||||
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisWeekFirstDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisWeekLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastWeekLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisWeekFirstDatetime.Unix()), timezone))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisWeekLastDatetime.Unix()), timezone))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastWeekLastDatetime.Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsThisMonthOrLater(t *testing.T) {
|
||||
@@ -82,13 +87,14 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsThisMonthOrLater(t *test
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
thisMonthFirstDatetime := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
|
||||
lastMonthLastDatetime := thisMonthFirstDatetime.Add(-1 * time.Second)
|
||||
thisMonthLastDatetime := lastMonthLastDatetime.Add(24 * time.Hour)
|
||||
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisMonthFirstDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisMonthLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastMonthLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisMonthFirstDatetime.Unix()), timezone))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisMonthLastDatetime.Unix()), timezone))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastMonthLastDatetime.Unix()), timezone))
|
||||
}
|
||||
|
||||
func TestUserCanEditTransactionByTransactionTime_ScopeIsThisYearOrLater(t *testing.T) {
|
||||
@@ -97,11 +103,12 @@ func TestUserCanEditTransactionByTransactionTime_ScopeIsThisYearOrLater(t *testi
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
timezone := time.FixedZone("Timezone", int(utils.GetServerTimezoneOffsetMinutes())*60)
|
||||
thisYearFirstDatetime := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.Local)
|
||||
lastYearLastDatetime := thisYearFirstDatetime.Add(-1 * time.Second)
|
||||
thisYearLastDatetime := lastYearLastDatetime.Add(24 * time.Hour)
|
||||
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisYearFirstDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisYearLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastYearLastDatetime.Unix()), utils.GetServerTimezoneOffsetMinutes()))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisYearFirstDatetime.Unix()), timezone))
|
||||
assert.Equal(t, true, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(thisYearLastDatetime.Unix()), timezone))
|
||||
assert.Equal(t, false, user.CanEditTransactionByTransactionTime(utils.GetMinTransactionTimeFromUnixTime(lastYearLastDatetime.Unix()), timezone))
|
||||
}
|
||||
|
||||
@@ -198,12 +198,11 @@ func (s *TransactionService) GetAllTransactionsInOneAccountWithAccountBalanceByM
|
||||
}
|
||||
|
||||
// GetAllAccountsDailyOpeningAndClosingBalance returns daily opening and closing balance of all accounts within time range
|
||||
func (s *TransactionService) GetAllAccountsDailyOpeningAndClosingBalance(c core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, utcOffset int16) (map[int32][]*models.TransactionWithAccountBalance, error) {
|
||||
func (s *TransactionService) GetAllAccountsDailyOpeningAndClosingBalance(c core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, clientTimezone *time.Location) (map[int32][]*models.TransactionWithAccountBalance, error) {
|
||||
if maxTransactionTime <= 0 {
|
||||
maxTransactionTime = utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
var allTransactions []*models.Transaction
|
||||
|
||||
for maxTransactionTime > 0 {
|
||||
@@ -260,7 +259,7 @@ func (s *TransactionService) GetAllAccountsDailyOpeningAndClosingBalance(c core.
|
||||
continue
|
||||
}
|
||||
|
||||
yearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime), clientLocation)
|
||||
yearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime), clientTimezone)
|
||||
groupKey := fmt.Sprintf("%d_%d", yearMonthDay, transaction.AccountId)
|
||||
dailyAccountBalance, exists := accountDailyLastBalances[groupKey]
|
||||
|
||||
@@ -284,7 +283,7 @@ func (s *TransactionService) GetAllAccountsDailyOpeningAndClosingBalance(c core.
|
||||
firstTransactionTime = minTransactionTime
|
||||
}
|
||||
|
||||
firstYearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(firstTransactionTime), clientLocation)
|
||||
firstYearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(firstTransactionTime), clientTimezone)
|
||||
|
||||
// fill in the opening balance for accounts that do not have transactions on the first day
|
||||
for accountId, accumulatedBalance := range accumulatedBalancesBeforeStartTime {
|
||||
@@ -1798,14 +1797,13 @@ func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *
|
||||
}
|
||||
|
||||
// GetAccountsTotalIncomeAndExpense returns the every accounts total income and expense amount by specific date range
|
||||
func (s *TransactionService) GetAccountsTotalIncomeAndExpense(c core.Context, uid int64, startUnixTime int64, endUnixTime int64, excludeAccountIds []int64, excludeCategoryIds []int64, utcOffset int16, useTransactionTimezone bool) (map[int64]int64, map[int64]int64, error) {
|
||||
func (s *TransactionService) GetAccountsTotalIncomeAndExpense(c core.Context, uid int64, startUnixTime int64, endUnixTime int64, excludeAccountIds []int64, excludeCategoryIds []int64, utcOffset int16, clientTimezone *time.Location, useTransactionTimezone bool) (map[int64]int64, map[int64]int64, error) {
|
||||
if uid <= 0 {
|
||||
return nil, nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
startLocalDateTime := utils.FormatUnixTimeToNumericLocalDateTime(startUnixTime, clientLocation)
|
||||
endLocalDateTime := utils.FormatUnixTimeToNumericLocalDateTime(endUnixTime, clientLocation)
|
||||
startLocalDateTime := utils.FormatUnixTimeToNumericLocalDateTime(startUnixTime, clientTimezone)
|
||||
endLocalDateTime := utils.FormatUnixTimeToNumericLocalDateTime(endUnixTime, clientTimezone)
|
||||
|
||||
startUnixTime = utils.GetMinUnixTimeWithSameLocalDateTime(startUnixTime, utcOffset)
|
||||
endUnixTime = utils.GetMaxUnixTimeWithSameLocalDateTime(endUnixTime, utcOffset)
|
||||
@@ -1889,7 +1887,7 @@ func (s *TransactionService) GetAccountsTotalIncomeAndExpense(c core.Context, ui
|
||||
|
||||
for i := 0; i < len(allTransactions); i++ {
|
||||
transaction := allTransactions[i]
|
||||
timeZone := clientLocation
|
||||
timeZone := clientTimezone
|
||||
|
||||
if useTransactionTimezone {
|
||||
timeZone = time.FixedZone("Transaction Timezone", int(transaction.TimezoneUtcOffset)*60)
|
||||
@@ -1923,22 +1921,21 @@ func (s *TransactionService) GetAccountsTotalIncomeAndExpense(c core.Context, ui
|
||||
}
|
||||
|
||||
// GetAccountsAndCategoriesTotalInflowAndOutflow returns the every accounts and categories total inflows and outflows amount by specific date range
|
||||
func (s *TransactionService) GetAccountsAndCategoriesTotalInflowAndOutflow(c core.Context, uid int64, startUnixTime int64, endUnixTime int64, tagFilters []*models.TransactionTagFilter, noTags bool, keyword string, utcOffset int16, useTransactionTimezone bool) ([]*models.Transaction, error) {
|
||||
func (s *TransactionService) GetAccountsAndCategoriesTotalInflowAndOutflow(c core.Context, uid int64, startUnixTime int64, endUnixTime int64, tagFilters []*models.TransactionTagFilter, noTags bool, keyword string, utcOffset int16, clientTimezone *time.Location, useTransactionTimezone bool) ([]*models.Transaction, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
var startLocalDateTime, endLocalDateTime, startTransactionTime, endTransactionTime int64
|
||||
|
||||
if startUnixTime > 0 {
|
||||
startLocalDateTime = utils.FormatUnixTimeToNumericLocalDateTime(startUnixTime, clientLocation)
|
||||
startLocalDateTime = utils.FormatUnixTimeToNumericLocalDateTime(startUnixTime, clientTimezone)
|
||||
startUnixTime = utils.GetMinUnixTimeWithSameLocalDateTime(startUnixTime, utcOffset)
|
||||
startTransactionTime = utils.GetMinTransactionTimeFromUnixTime(startUnixTime)
|
||||
}
|
||||
|
||||
if endUnixTime > 0 {
|
||||
endLocalDateTime = utils.FormatUnixTimeToNumericLocalDateTime(endUnixTime, clientLocation)
|
||||
endLocalDateTime = utils.FormatUnixTimeToNumericLocalDateTime(endUnixTime, clientTimezone)
|
||||
endUnixTime = utils.GetMaxUnixTimeWithSameLocalDateTime(endUnixTime, utcOffset)
|
||||
endTransactionTime = utils.GetMaxTransactionTimeFromUnixTime(endUnixTime)
|
||||
}
|
||||
@@ -2001,7 +1998,7 @@ func (s *TransactionService) GetAccountsAndCategoriesTotalInflowAndOutflow(c cor
|
||||
|
||||
for i := 0; i < len(allTransactions); i++ {
|
||||
transaction := allTransactions[i]
|
||||
timeZone := clientLocation
|
||||
timeZone := clientTimezone
|
||||
|
||||
if useTransactionTimezone {
|
||||
timeZone = time.FixedZone("Transaction Timezone", int(transaction.TimezoneUtcOffset)*60)
|
||||
@@ -2046,12 +2043,11 @@ func (s *TransactionService) GetAccountsAndCategoriesTotalInflowAndOutflow(c cor
|
||||
}
|
||||
|
||||
// GetAccountsAndCategoriesMonthlyInflowAndOutflow returns the every accounts monthly inflows and outflows amount by specific date range
|
||||
func (s *TransactionService) GetAccountsAndCategoriesMonthlyInflowAndOutflow(c core.Context, uid int64, startYear int32, startMonth int32, endYear int32, endMonth int32, tagFilters []*models.TransactionTagFilter, noTags bool, keyword string, utcOffset int16, useTransactionTimezone bool) (map[int32][]*models.Transaction, error) {
|
||||
func (s *TransactionService) GetAccountsAndCategoriesMonthlyInflowAndOutflow(c core.Context, uid int64, startYear int32, startMonth int32, endYear int32, endMonth int32, tagFilters []*models.TransactionTagFilter, noTags bool, keyword string, clientTimezone *time.Location, useTransactionTimezone bool) (map[int32][]*models.Transaction, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
var startTransactionTime, endTransactionTime int64
|
||||
var err error
|
||||
|
||||
@@ -2132,7 +2128,7 @@ func (s *TransactionService) GetAccountsAndCategoriesMonthlyInflowAndOutflow(c c
|
||||
|
||||
for i := 0; i < len(allTransactions); i++ {
|
||||
transaction := allTransactions[i]
|
||||
timeZone := clientLocation
|
||||
timeZone := clientTimezone
|
||||
|
||||
if useTransactionTimezone {
|
||||
timeZone = time.FixedZone("Transaction Timezone", int(transaction.TimezoneUtcOffset)*60)
|
||||
|
||||
@@ -521,6 +521,10 @@ export function getBrowserTimezoneOffsetMinutes(): number {
|
||||
return -new Date().getTimezoneOffset();
|
||||
}
|
||||
|
||||
export function guessTimezoneName(): string {
|
||||
return moment.tz.guess(true);
|
||||
}
|
||||
|
||||
export function getLocalDatetimeFromUnixTime(unixTime: number): Date {
|
||||
return new Date(unixTime * 1000);
|
||||
}
|
||||
|
||||
+15
-1
@@ -167,13 +167,19 @@ import {
|
||||
isBoolean,
|
||||
objectFieldWithValueToArrayItem
|
||||
} from './common.ts';
|
||||
import {
|
||||
getTimeZone
|
||||
} from './settings.ts';
|
||||
import {
|
||||
getGoogleMapAPIKey,
|
||||
getBaiduMapAK,
|
||||
getAmapApplicationKey,
|
||||
getExchangeRatesRequestTimeout
|
||||
} from './server_settings.ts';
|
||||
import { getTimezoneOffsetMinutes } from './datetime.ts';
|
||||
import {
|
||||
getTimezoneOffsetMinutes,
|
||||
guessTimezoneName
|
||||
} from './datetime.ts';
|
||||
import { generateRandomUUID } from './misc.ts';
|
||||
import { getBasePath } from './web.ts';
|
||||
import logger from './logger.ts';
|
||||
@@ -204,6 +210,14 @@ axios.interceptors.request.use((config: ApiRequestConfig) => {
|
||||
|
||||
config.headers['X-Timezone-Offset'] = getTimezoneOffsetMinutes();
|
||||
|
||||
let timezoneName = getTimeZone();
|
||||
|
||||
if (!timezoneName || timezoneName.trim().length < 1) {
|
||||
timezoneName = guessTimezoneName();
|
||||
}
|
||||
|
||||
config.headers['X-Timezone-Name'] = timezoneName;
|
||||
|
||||
if (needBlockRequest && !config.ignoreBlocked) {
|
||||
return new Promise(resolve => {
|
||||
blockedRequests.push(newToken => {
|
||||
|
||||
@@ -89,6 +89,10 @@ export function getTheme(): string {
|
||||
return getApplicationSettings().theme;
|
||||
}
|
||||
|
||||
export function getTimeZone(): string {
|
||||
return getApplicationSettings().timeZone;
|
||||
}
|
||||
|
||||
export function isEnableApplicationLock(): boolean {
|
||||
return getApplicationSettings().applicationLock;
|
||||
}
|
||||
|
||||
@@ -202,6 +202,7 @@ import {
|
||||
getTimeDifferenceHoursAndMinutes,
|
||||
getTimezoneOffset,
|
||||
getTimezoneOffsetMinutes,
|
||||
guessTimezoneName,
|
||||
isDateRangeMatchFullMonths,
|
||||
isDateRangeMatchFullYears,
|
||||
isPM
|
||||
@@ -2316,7 +2317,7 @@ export function useI18n() {
|
||||
logger.info(`Current timezone is ${timezone}`);
|
||||
setTimeZone(timezone);
|
||||
} else {
|
||||
logger.info(`No timezone is set, use browser default ${getTimezoneOffset()} (maybe ${moment.tz.guess(true)})`);
|
||||
logger.info(`No timezone is set, use browser default ${getTimezoneOffset()} (maybe ${guessTimezoneName()})`);
|
||||
setTimeZone('');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user