From 8e90f96562c66d814aaaa175acef64387c15008d Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 14 Mar 2021 02:47:24 +0800 Subject: [PATCH] support modify transaction time zone --- pkg/api/transactions.go | 21 +++++---- pkg/services/transactions.go | 4 ++ src/Mobile.vue | 4 ++ src/filters/moment.js | 18 +++++-- src/lib/utils.js | 10 ++++ src/locales/en.js | 1 + src/locales/zh_Hans.js | 1 + src/mobile-main.js | 2 +- src/store/index.js | 10 ++-- src/store/transaction.js | 5 +- src/views/mobile/transactions/Edit.vue | 65 ++++++++++++++++++++++++-- src/views/mobile/transactions/List.vue | 5 +- 12 files changed, 117 insertions(+), 29 deletions(-) diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index 608ded93..b36c2537 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -454,13 +454,14 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{} transactionTagIds := allTransactionTagIds[transaction.TransactionId] newTransaction := &models.Transaction{ - TransactionId: transaction.TransactionId, - Uid: uid, - CategoryId: transactionModifyReq.CategoryId, - TransactionTime: utils.GetMinTransactionTimeFromUnixTime(transactionModifyReq.Time), - AccountId: transactionModifyReq.SourceAccountId, - Amount: transactionModifyReq.SourceAmount, - Comment: transactionModifyReq.Comment, + TransactionId: transaction.TransactionId, + Uid: uid, + CategoryId: transactionModifyReq.CategoryId, + TransactionTime: utils.GetMinTransactionTimeFromUnixTime(transactionModifyReq.Time), + TimezoneUtcOffset: transactionModifyReq.UtcOffset, + AccountId: transactionModifyReq.SourceAccountId, + Amount: transactionModifyReq.SourceAmount, + Comment: transactionModifyReq.Comment, } if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT { @@ -470,6 +471,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{} if newTransaction.CategoryId == transaction.CategoryId && utils.GetUnixTimeFromTransactionTime(newTransaction.TransactionTime) == utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime) && + newTransaction.TimezoneUtcOffset == transaction.TimezoneUtcOffset && newTransaction.AccountId == transaction.AccountId && newTransaction.Amount == transaction.Amount && (transaction.Type != models.TRANSACTION_DB_TYPE_TRANSFER_OUT || newTransaction.RelatedAccountId == transaction.RelatedAccountId) && @@ -487,9 +489,10 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{} addTransactionTagIds = tagIds } - transactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, transactionModifyReq.UtcOffset) + transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transaction.TimezoneUtcOffset) + newTransactionEditable := user.CanEditTransactionByTransactionTime(newTransaction.TransactionTime, transactionModifyReq.UtcOffset) - if !transactionEditable { + if !transactionEditable || !newTransactionEditable { return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime } diff --git a/pkg/services/transactions.go b/pkg/services/transactions.go index 4c2e66eb..c9a8a273 100644 --- a/pkg/services/transactions.go +++ b/pkg/services/transactions.go @@ -567,6 +567,10 @@ func (s *TransactionService) ModifyTransaction(transaction *models.Transaction, updateCols = append(updateCols, "transaction_time") } + if transaction.TimezoneUtcOffset != oldTransaction.TimezoneUtcOffset { + updateCols = append(updateCols, "timezone_utc_offset") + } + if transaction.AccountId != oldTransaction.AccountId { updateCols = append(updateCols, "account_id") } diff --git a/src/Mobile.vue b/src/Mobile.vue index 051230f3..dd69de85 100644 --- a/src/Mobile.vue +++ b/src/Mobile.vue @@ -234,6 +234,10 @@ i.icon.la, i.icon.las, i.icon.lab { align-self: normal !important; } +.list-item-no-item-after .item-after { + display: none; +} + .list .item-content .input.list-title-input { margin-top: calc(-1 * var(--f7-list-item-padding-vertical)); margin-bottom: calc(-1 * var(--f7-list-item-padding-vertical)); diff --git a/src/filters/moment.js b/src/filters/moment.js index 1acb9339..d61cee2e 100644 --- a/src/filters/moment.js +++ b/src/filters/moment.js @@ -1,9 +1,17 @@ import utils from '../lib/utils.js'; -export default function (value, format) { - if (utils.isNumber(value)) { - return utils.formatUnixTime(value, format); - } else { - return utils.formatTime(value, format); +export default function (value, format, options) { + if (!utils.isNumber(value)) { + value = utils.getUnixTime(value); } + + if (utils.isObject(options) && utils.isNumber(options.utcOffset)) { + if (!utils.isNumber(options.currentUtcOffset)) { + options.currentUtcOffset = utils.getTimezoneOffsetMinutes(); + } + + value = utils.getDummyUnixTimeForLocalDisplay(value, options.utcOffset, options.currentUtcOffset); + } + + return utils.formatUnixTime(value, format); } diff --git a/src/lib/utils.js b/src/lib/utils.js index e4fd2685..473ca977 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -80,6 +80,14 @@ function getTimezoneOffsetMinutes(timezone) { return getUtcOffsetMinutesByUtcOffset(utcOffset); } +function getActualUnixTimeForStore(unixTime, utcOffset, currentUtcOffset) { + return unixTime - (utcOffset - currentUtcOffset) * 60; +} + +function getDummyUnixTimeForLocalDisplay(unixTime, utcOffset, currentUtcOffset) { + return unixTime + (utcOffset - currentUtcOffset) * 60; +} + function getCurrentUnixTime() { return moment().unix(); } @@ -616,6 +624,8 @@ export default { getUtcOffsetByUtcOffsetMinutes, getTimezoneOffset, getTimezoneOffsetMinutes, + getActualUnixTimeForStore, + getDummyUnixTimeForLocalDisplay, getCurrentUnixTime, parseDateFromUnixTime, formatUnixTime, diff --git a/src/locales/en.js b/src/locales/en.js index 397236fc..9df430cb 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -786,6 +786,7 @@ export default { 'Source Account': 'Source Account', 'Destination Account': 'Destination Account', 'Transaction Time': 'Transaction Time', + 'Transaction Time Zone': 'Transaction Time Zone', 'Tags': 'Tags', 'Your transaction description (optional)': 'Your transaction description (optional)', 'Are you sure you want to save this transaction whose amount is 0?': 'Are you sure you want to save this transaction whose amount is 0?', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index bb753d1b..b32a0007 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -786,6 +786,7 @@ export default { 'Source Account': '来源账户', 'Destination Account': '目标账户', 'Transaction Time': '交易时间', + 'Transaction Time Zone': '交易时区', 'Tags': '标签', 'Your transaction description (optional)': '你的交易描述 (可选)', 'Are you sure you want to save this transaction whose amount is 0?': '您确定要保存这个金额为0的交易?', diff --git a/src/mobile-main.js b/src/mobile-main.js index d19b7789..dd0672d7 100644 --- a/src/mobile-main.js +++ b/src/mobile-main.js @@ -150,7 +150,7 @@ Vue.component('NumberPadSheet', NumberPadSheet); Vue.component('TransactionTagSelectionSheet', TransactionTagSelectionSheet); Vue.filter('localized', (value, options) => localizedFilter({ i18n }, value, options)); -Vue.filter('moment', (value, format) => momentFilter(value, format)); +Vue.filter('moment', (value, format, options) => momentFilter(value, format, options)); Vue.filter('percent', (value, precision, lowPrecisionValue) => percentFilter(value, precision, lowPrecisionValue)); Vue.filter('itemFieldContent', (value, fieldName, defaultValue, translate) => itemFieldContentFilter({ i18n }, value, fieldName, defaultValue, translate)); Vue.filter('currency', (value, currencyCode) => currencyFilter({ i18n }, value, currencyCode)); diff --git a/src/store/index.js b/src/store/index.js index 37ed473a..18ca8067 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -417,14 +417,16 @@ const stores = { } if (transactions.items && transactions.items.length) { + const currentUtcOffset = utils.getTimezoneOffsetMinutes(); let currentMonthListIndex = -1; let currentMonthList = null; for (let i = 0; i < transactions.items.length; i++) { const item = transactions.items[i]; - fillTransactionObject(state, item); + fillTransactionObject(state, item, currentUtcOffset); - const transactionTime = utils.parseDateFromUnixTime(item.time); + const transactionUnixTimeForLocalUsage = utils.getDummyUnixTimeForLocalDisplay(item.time, item.utcOffset, currentUtcOffset); + const transactionTime = utils.parseDateFromUnixTime(transactionUnixTimeForLocalUsage); const transactionYear = utils.getYear(transactionTime); const transactionMonth = utils.getMonth(transactionTime); const transactionYearMonth = utils.getYearAndMonth(transactionTime); @@ -547,6 +549,8 @@ const stores = { } }, [SAVE_TRANSACTION_IN_TRANSACTION_LIST] (state, { transaction, defaultCurrency }) { + const currentUtcOffset = utils.getTimezoneOffsetMinutes(); + for (let i = 0; i < state.transactions.length; i++) { const transactionMonthList = state.transactions[i]; @@ -558,7 +562,7 @@ const stores = { for (let j = 0; j < transactionMonthList.items.length; j++) { if (transactionMonthList.items[j].id === transaction.id) { - fillTransactionObject(state, transaction); + fillTransactionObject(state, transaction, currentUtcOffset); if ((state.transactionsFilter.categoryId && state.transactionsFilter.categoryId !== '0' && state.transactionsFilter.categoryId !== transaction.categoryId) || (state.transactionsFilter.accountId && state.transactionsFilter.accountId !== '0' && state.transactionsFilter.accountId !== transaction.sourceAccountId && state.transactionsFilter.accountId !== transaction.destinationAccountId)) { diff --git a/src/store/transaction.js b/src/store/transaction.js index aed132f4..271e3da5 100644 --- a/src/store/transaction.js +++ b/src/store/transaction.js @@ -279,12 +279,13 @@ export function hasMoreTransaction(state) { return state.transactionsNextTimeId > 0; } -export function fillTransactionObject(state, transaction) { +export function fillTransactionObject(state, transaction, currentUtcOffset) { if (!transaction) { return; } - const transactionTime = utils.parseDateFromUnixTime(transaction.time); + const transactionUnixTimeForLocalUsage = utils.getDummyUnixTimeForLocalDisplay(transaction.time, transaction.utcOffset, currentUtcOffset); + const transactionTime = utils.parseDateFromUnixTime(transactionUnixTimeForLocalUsage); transaction.day = utils.getDay(transactionTime); transaction.dayOfWeek = utils.getDayOfWeek(transactionTime); diff --git a/src/views/mobile/transactions/Edit.vue b/src/views/mobile/transactions/Edit.vue index 8cf4521b..4a5c50aa 100644 --- a/src/views/mobile/transactions/Edit.vue +++ b/src/views/mobile/transactions/Edit.vue @@ -27,6 +27,7 @@ + @@ -201,6 +202,21 @@ > + + + + {{ transaction.utcOffset | utcOffset }} + {{ transaction.timeZone | timeZoneName(allTimezones) }} + + + {{ transaction.comment }}