diff --git a/CHANGELOG.md b/CHANGELOG.md index 40685fd4a..53376946c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,27 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.7.1](https://github.com/gradido/gradido/compare/1.7.0...1.7.1) + +- fix: Localize Dates on Redeem Transaction Link Page [`#1720`](https://github.com/gradido/gradido/pull/1720) +- fix: Round Virtual Transaction Link Transaction [`#1718`](https://github.com/gradido/gradido/pull/1718) +- larger icon and deacy information if center [`#1719`](https://github.com/gradido/gradido/pull/1719) +- Fix: restore script load correct .env [`#1717`](https://github.com/gradido/gradido/pull/1717) +- fix-disbled-button-if-totalBalance [`#1716`](https://github.com/gradido/gradido/pull/1716) +- icon droplet-halflarger and correctly positioned [`#1713`](https://github.com/gradido/gradido/pull/1713) +- fix: Clean up Registration Flow [`#1709`](https://github.com/gradido/gradido/pull/1709) +- 1703 submit button disabled when total amount to submit is minus [`#1705`](https://github.com/gradido/gradido/pull/1705) +- add extra disabled variable for send emit, disabled send by emit [`#1704`](https://github.com/gradido/gradido/pull/1704) +- Fix: Correct calculation of decay [`#1699`](https://github.com/gradido/gradido/pull/1699) +- Fix: Allow sending of more then half of my wealth via link [`#1700`](https://github.com/gradido/gradido/pull/1700) +- feat: Seed Creations Months Ago From Now [`#1702`](https://github.com/gradido/gradido/pull/1702) +- Fix: Frontend show proper error message on failed send [`#1701`](https://github.com/gradido/gradido/pull/1701) + #### [1.7.0](https://github.com/gradido/gradido/compare/1.6.6...1.7.0) +> 30 March 2022 + +- v1.7.0 [`#1698`](https://github.com/gradido/gradido/pull/1698) - folder for new style images [`#1694`](https://github.com/gradido/gradido/pull/1694) - fix: No Email Exposed on Forgot Password [`#1696`](https://github.com/gradido/gradido/pull/1696) - fix: No Decay Calculation in Frontend [`#1692`](https://github.com/gradido/gradido/pull/1692) diff --git a/admin/package.json b/admin/package.json index cc4702b4c..ae1f1c305 100644 --- a/admin/package.json +++ b/admin/package.json @@ -3,7 +3,7 @@ "description": "Administraion Interface for Gradido", "main": "index.js", "author": "Moriz Wahl", - "version": "1.7.0", + "version": "1.7.1", "license": "MIT", "private": false, "scripts": { diff --git a/backend/package.json b/backend/package.json index b2086c8d7..3c4066d6b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "gradido-backend", - "version": "1.7.0", + "version": "1.7.1", "description": "Gradido unified backend providing an API-Service for Gradido Transactions", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/backend", diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index 684224175..3c3a684ef 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -12,15 +12,22 @@ export class Transaction { this.user = user this.previous = transaction.previous this.typeId = transaction.typeId - this.amount = transaction.amount - this.balance = transaction.balance + this.amount = transaction.amount.toDecimalPlaces(2, Decimal.ROUND_DOWN) + this.balance = transaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN) this.balanceDate = transaction.balanceDate if (!transaction.decayStart) { - this.decay = new Decay(transaction.balance, new Decimal(0), null, null, null) + // TODO: hot fix, we should separate decay calculation from decay graphql model + this.decay = new Decay( + transaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), + new Decimal(0), + null, + null, + null, + ) } else { this.decay = new Decay( - transaction.balance, - transaction.decay, + transaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), + transaction.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), transaction.decayStart, transaction.balanceDate, Math.round((transaction.balanceDate.getTime() - transaction.decayStart.getTime()) / 1000), diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 672e07b12..f30e779e5 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -54,19 +54,23 @@ export class BalanceResolver { }, }) + // The decay is always calculated on the last booked transaction + const calculatedDecay = calculateDecay( + lastTransaction.balance, + lastTransaction.balanceDate, + now, + ) + + // The final balance is reduced by the link amount withheld const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkRepository.summary(user.id, now) - const calculatedDecay = calculateDecay( - lastTransaction.balance.minus(sumHoldAvailableAmount.toString()), - lastTransaction.balanceDate, - now, - ) - return new Balance({ - balance: calculatedDecay.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), // round towards zero + balance: calculatedDecay.balance + .minus(sumHoldAvailableAmount.toString()) + .toDecimalPlaces(2, Decimal.ROUND_DOWN), // round towards zero decay: calculatedDecay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), // round towards - infinity lastBookedBalance: lastTransaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), balanceGDT, diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 461a70a00..aa1bba639 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -57,7 +57,12 @@ export const executeTransaction = async ( // validate amount const receivedCallDate = new Date() - const sendBalance = await calculateBalance(sender.id, amount.mul(-1), receivedCallDate) + const sendBalance = await calculateBalance( + sender.id, + amount.mul(-1), + receivedCallDate, + transactionLink, + ) if (!sendBalance) { throw new Error("user hasn't enough GDD or amount is < 0") } @@ -198,12 +203,15 @@ export class TransactionResolver { // decay & link transactions if (currentPage === 1 && order === Order.DESC) { + // The virtual decay is always on the booked amount, not including the generated, not yet booked links, + // since the decay is substantially different when the amount is less transactions.push( virtualDecayTransaction( - lastTransaction.balance.minus(sumHoldAvailableAmount.toString()), + lastTransaction.balance, lastTransaction.balanceDate, now, self, + sumHoldAvailableAmount, ), ) // virtual transaction for pending transaction-links sum diff --git a/backend/src/seeds/creation/CreationInterface.ts b/backend/src/seeds/creation/CreationInterface.ts index 8723f441d..3e0f3cf6c 100644 --- a/backend/src/seeds/creation/CreationInterface.ts +++ b/backend/src/seeds/creation/CreationInterface.ts @@ -4,4 +4,6 @@ export interface CreationInterface { memo: string creationDate: string confirmed?: boolean + // number of months to move the confirmed creation to the past + moveCreationDate?: number } diff --git a/backend/src/seeds/creation/index.ts b/backend/src/seeds/creation/index.ts index 7396a7ec8..20d30d94c 100644 --- a/backend/src/seeds/creation/index.ts +++ b/backend/src/seeds/creation/index.ts @@ -1,29 +1,28 @@ import { CreationInterface } from './CreationInterface' - -const lastMonth = (date: Date): string => { - return new Date(date.getFullYear(), date.getMonth() - 1, 1).toISOString() -} +import { nMonthsBefore } from '../factory/creation' export const creations: CreationInterface[] = [ { email: 'bibi@bloxberg.de', amount: 1000, memo: 'Herzlich Willkommen bei Gradido!', - creationDate: lastMonth(new Date()), + creationDate: nMonthsBefore(new Date()), confirmed: true, + moveCreationDate: 12, }, { email: 'bob@baumeister.de', amount: 1000, memo: 'Herzlich Willkommen bei Gradido!', - creationDate: lastMonth(new Date()), + creationDate: nMonthsBefore(new Date()), confirmed: true, + moveCreationDate: 8, }, { email: 'raeuber@hotzenplotz.de', amount: 1000, memo: 'Herzlich Willkommen bei Gradido!', - creationDate: lastMonth(new Date()), + creationDate: nMonthsBefore(new Date()), confirmed: true, }, ] diff --git a/backend/src/seeds/factory/creation.ts b/backend/src/seeds/factory/creation.ts index d4d4c8101..64f693360 100644 --- a/backend/src/seeds/factory/creation.ts +++ b/backend/src/seeds/factory/creation.ts @@ -6,9 +6,14 @@ import { login } from '@/seeds/graphql/queries' import { CreationInterface } from '@/seeds/creation/CreationInterface' import { ApolloServerTestClient } from 'apollo-server-testing' import { User } from '@entity/User' +import { Transaction } from '@entity/Transaction' import { AdminPendingCreation } from '@entity/AdminPendingCreation' // import CONFIG from '@/config/index' +export const nMonthsBefore = (date: Date, months = 1): string => { + return new Date(date.getFullYear(), date.getMonth() - months, 1).toISOString() +} + export const creationFactory = async ( client: ApolloServerTestClient, creation: CreationInterface, @@ -34,5 +39,21 @@ export const creationFactory = async ( }) await mutate({ mutation: confirmPendingCreation, variables: { id: pendingCreation.id } }) + + if (creation.moveCreationDate) { + const transaction = await Transaction.findOneOrFail({ + where: { userId: user.id, creationDate: new Date(creation.creationDate) }, + order: { balanceDate: 'DESC' }, + }) + if (transaction.decay.equals(0) && transaction.creationDate) { + transaction.creationDate = new Date( + nMonthsBefore(transaction.creationDate, creation.moveCreationDate), + ) + transaction.balanceDate = new Date( + nMonthsBefore(transaction.balanceDate, creation.moveCreationDate), + ) + await transaction.save() + } + } } } diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 95e1bf699..8d1c90ca4 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -4,6 +4,7 @@ import { Transaction } from '@entity/Transaction' import { Decay } from '@model/Decay' import { getCustomRepository } from '@dbTools/typeorm' import { TransactionLinkRepository } from '@repository/TransactionLink' +import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' function isStringBoolean(value: string): boolean { const lowerValue = value.toLowerCase() @@ -21,6 +22,7 @@ async function calculateBalance( userId: number, amount: Decimal, time: Date, + transactionLink?: dbTransactionLink | null, ): Promise<{ balance: Decimal; decay: Decay; lastTransactionId: number } | null> { const lastTransaction = await Transaction.findOne({ userId }, { order: { balanceDate: 'DESC' } }) if (!lastTransaction) return null @@ -32,7 +34,13 @@ async function calculateBalance( const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time) - if (balance.minus(sumHoldAvailableAmount.toString()).lessThan(0)) { + // If we want to redeem a link we need to make sure that the link amount is not considered as blocked + // else we cannot redeem links which are more or equal to half of what an account actually owns + const releasedLinkAmount = transactionLink ? transactionLink.holdAvailableAmount : new Decimal(0) + + if ( + balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0) + ) { return null } return { balance, lastTransactionId: lastTransaction.id, decay } diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index e4b9eec1f..920fc4201 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -42,11 +42,11 @@ const virtualLinkTransaction = ( userId: -1, previous: -1, typeId: TransactionTypeId.LINK_SUMMARY, - amount: amount, - balance: balance, + amount: amount.toDecimalPlaces(2, Decimal.ROUND_FLOOR), + balance: balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), balanceDate: validUntil, decayStart: createdAt, - decay: decay, + decay: decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), memo: '', creationDate: null, ...defaultModelFunctions, @@ -59,6 +59,7 @@ const virtualDecayTransaction = ( balanceDate: Date, time: Date = new Date(), user: User, + holdAvailabeAmount: Decimal, ): Transaction => { const decay = calculateDecay(balance, balanceDate, time) // const balance = decay.balance.minus(lastTransaction.balance) @@ -67,10 +68,12 @@ const virtualDecayTransaction = ( userId: -1, previous: -1, typeId: TransactionTypeId.DECAY, - amount: decay.decay ? decay.decay : new Decimal(0), // new Decimal(0), // this kinda is wrong, but helps with the frontend query - balance: decay.balance, + amount: decay.decay ? decay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR) : new Decimal(0), // new Decimal(0), // this kinda is wrong, but helps with the frontend query + balance: decay.balance + .minus(holdAvailabeAmount.toString()) + .toDecimalPlaces(2, Decimal.ROUND_DOWN), balanceDate: time, - decay: decay.decay ? decay.decay : new Decimal(0), + decay: decay.decay ? decay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR) : new Decimal(0), decayStart: decay.start, memo: '', creationDate: null, diff --git a/database/package.json b/database/package.json index 0ee937774..a1aed2558 100644 --- a/database/package.json +++ b/database/package.json @@ -1,6 +1,6 @@ { "name": "gradido-database", - "version": "1.7.0", + "version": "1.7.1", "description": "Gradido Database Tool to execute database migrations", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/database", diff --git a/deployment/bare_metal/restore.sh b/deployment/bare_metal/restore.sh index 2a1ccd0ac..3d6793dd3 100755 --- a/deployment/bare_metal/restore.sh +++ b/deployment/bare_metal/restore.sh @@ -15,13 +15,13 @@ if [ ! -f "$BACKUP_FILE" ]; then return "File '$BACKUP_FILE' does not exist" 2>/dev/null || exit 1 fi -# Load backend .env for DB_USERNAME, DB_PASSWORD & DB_DATABASE +# Load database .env for DB_USERNAME, DB_PASSWORD & DB_DATABASE # NOTE: all config values will be in process.env when starting # the services and will therefore take precedence over the .env -if [ -f "$PROJECT_ROOT/backend/.env" ]; then - export $(cat $PROJECT_ROOT/backend/.env | sed 's/#.*//g' | xargs) +if [ -f "$PROJECT_ROOT/database/.env" ]; then + export $(cat $PROJECT_ROOT/database/.env | sed 's/#.*//g' | xargs) else - export $(cat $PROJECT_ROOT/backend/.env.dist | sed 's/#.*//g' | xargs) + export $(cat $PROJECT_ROOT/database/.env.dist | sed 's/#.*//g' | xargs) fi # Stop gradido-backend service @@ -30,6 +30,11 @@ pm2 stop gradido-backend # Backup data mysqldump --databases --single-transaction --quick --hex-blob --lock-tables=false > ${SCRIPT_DIR}/backup/mariadb-restore-backup-$(date +%d-%m-%Y_%H-%M-%S).sql -u ${DB_USER} -p${DB_PASSWORD} ${DB_DATABASE} +# Drop Database +mysql -u ${DB_USER} -p${DB_PASSWORD} <
-
-
- - {{ $t('decay.calculation_decay') }} -
-
- - -
{{ $t('decay.decay') }}
-
- -
- {{ previousBookedBalance | GDD }} - {{ decay | GDD }} {{ $t('math.equal') }} - {{ balance | GDD }} + + +
+
+ + {{ $t('decay.calculation_decay') }} +
+ + + +
{{ $t('decay.decay') }}
+
+ +
+ {{ previousBookedBalance | GDD }} + {{ decay | GDD }} {{ $t('math.equal') }} + {{ balance | GDD }} +
+
+
diff --git a/frontend/src/components/DecayInformations/DecayInformation-Long.vue b/frontend/src/components/DecayInformations/DecayInformation-Long.vue index 50e3d6697..9059ab62e 100644 --- a/frontend/src/components/DecayInformations/DecayInformation-Long.vue +++ b/frontend/src/components/DecayInformations/DecayInformation-Long.vue @@ -1,64 +1,69 @@