From b3f7fd28a18280a5e00e5bc40f70654c2714d527 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 15:54:59 +0100 Subject: [PATCH 1/6] add transactionLinkId Column to transactions table --- .../0032-add-transaction-link-to-transaction.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 database/migrations/0032-add-transaction-link-to-transaction.ts diff --git a/database/migrations/0032-add-transaction-link-to-transaction.ts b/database/migrations/0032-add-transaction-link-to-transaction.ts new file mode 100644 index 000000000..0de8c5a43 --- /dev/null +++ b/database/migrations/0032-add-transaction-link-to-transaction.ts @@ -0,0 +1,14 @@ +/* MIGRATION TO ADD transactionLinkId FIELDTO TRANSACTION */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'ALTER TABLE `transactions` ADD COLUMN `transactionLinkId` int UNSIGNED DEFAULT NULL;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `transactions` DROP COLUMN `transactionLinkId`;') +} From 6d284c8170e9cc41cc3042de6204d3a1a4880f3f Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 15:58:16 +0100 Subject: [PATCH 2/6] new DB version --- backend/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index b1fb8e397..79101856c 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0031-remove_sendEmail_from_transaction_link', + DB_VERSION: '0032-add-transaction-link-to-transaction', DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0 } From e7554030b8ce1b72e30bed0fb198bac3f9c8e22b Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 16:01:35 +0100 Subject: [PATCH 3/6] add transactionLinkId to transaction entity --- .../Transaction.ts | 94 +++++++++++++++++++ database/entity/Transaction.ts | 2 +- ...032-add-transaction-link-to-transaction.ts | 4 +- 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 database/entity/0032-add-transaction-link-to-transaction/Transaction.ts diff --git a/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts b/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts new file mode 100644 index 000000000..398fa03db --- /dev/null +++ b/database/entity/0032-add-transaction-link-to-transaction/Transaction.ts @@ -0,0 +1,94 @@ +import Decimal from 'decimal.js-light' +import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' +import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' + +@Entity('transactions') +export class Transaction extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ name: 'user_id', unsigned: true, nullable: false }) + userId: number + + @Column({ type: 'int', unsigned: true, nullable: true, default: null }) + previous: number | null + + @Column({ name: 'type_id', unsigned: true, nullable: false }) + typeId: number + + @Column({ + type: 'decimal', + precision: 40, + scale: 20, + nullable: false, + transformer: DecimalTransformer, + }) + amount: Decimal + + @Column({ + type: 'decimal', + precision: 40, + scale: 20, + nullable: false, + transformer: DecimalTransformer, + }) + balance: Decimal + + @Column({ + name: 'balance_date', + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP', + nullable: false, + }) + balanceDate: Date + + @Column({ + type: 'decimal', + precision: 40, + scale: 20, + nullable: false, + transformer: DecimalTransformer, + }) + decay: Decimal + + @Column({ + name: 'decay_start', + type: 'datetime', + nullable: true, + default: null, + }) + decayStart: Date | null + + @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + memo: string + + @Column({ name: 'creation_date', type: 'datetime', nullable: true, default: null }) + creationDate: Date | null + + @Column({ + name: 'linked_user_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + linkedUserId?: number | null + + @Column({ + name: 'linked_transaction_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + linkedTransactionId?: number | null + + @Column({ + name: 'transaction_link_id', + type: 'int', + unsigned: true, + nullable: true, + default: null, + }) + transactionLinkId?: number | null +} diff --git a/database/entity/Transaction.ts b/database/entity/Transaction.ts index 56c77c557..3515202d0 100644 --- a/database/entity/Transaction.ts +++ b/database/entity/Transaction.ts @@ -1 +1 @@ -export { Transaction } from './0029-clean_transaction_table/Transaction' +export { Transaction } from './0032-add-transaction-link-to-transaction/Transaction' diff --git a/database/migrations/0032-add-transaction-link-to-transaction.ts b/database/migrations/0032-add-transaction-link-to-transaction.ts index 0de8c5a43..82c104f04 100644 --- a/database/migrations/0032-add-transaction-link-to-transaction.ts +++ b/database/migrations/0032-add-transaction-link-to-transaction.ts @@ -5,10 +5,10 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn( - 'ALTER TABLE `transactions` ADD COLUMN `transactionLinkId` int UNSIGNED DEFAULT NULL;', + 'ALTER TABLE `transactions` ADD COLUMN `transaction_link_id` int UNSIGNED DEFAULT NULL;', ) } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { - await queryFn('ALTER TABLE `transactions` DROP COLUMN `transactionLinkId`;') + await queryFn('ALTER TABLE `transactions` DROP COLUMN `transaction_link_id`;') } From 06d45c1e517ec5ac101fc8975a6faab96c159e85 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 16:12:13 +0100 Subject: [PATCH 4/6] add transaction link id to transaction model --- backend/src/graphql/model/Transaction.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/graphql/model/Transaction.ts b/backend/src/graphql/model/Transaction.ts index 29a8a4bbd..684224175 100644 --- a/backend/src/graphql/model/Transaction.ts +++ b/backend/src/graphql/model/Transaction.ts @@ -30,6 +30,7 @@ export class Transaction { this.creationDate = transaction.creationDate this.linkedUser = linkedUser this.linkedTransactionId = transaction.linkedTransactionId + this.transactionLinkId = transaction.transactionLinkId } @Field(() => Number) @@ -67,4 +68,8 @@ export class Transaction { @Field(() => Number, { nullable: true }) linkedTransactionId?: number | null + + // Links to the TransactionLink when transaction was created by a link + @Field(() => Number, { nullable: true }) + transactionLinkId?: number | null } From e79a583ee2c109ac6651045c7b885f76b4542ff1 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 16:29:54 +0100 Subject: [PATCH 5/6] insert transactionLinkId in transaction made by redeemed link, update transaction link within commit transaction --- .../graphql/resolver/TransactionLinkResolver.ts | 15 +++++++-------- .../src/graphql/resolver/TransactionResolver.ts | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts index 835b84cbf..9e2af6111 100644 --- a/backend/src/graphql/resolver/TransactionLinkResolver.ts +++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts @@ -156,14 +156,13 @@ export class TransactionLinkResolver { throw new Error('Transaction Link already redeemed.') } - await executeTransaction(transactionLink.amount, transactionLink.memo, linkedUser, user) - - // TODO: Rollback transaction when updating links fails - transactionLink.redeemedAt = now - transactionLink.redeemedBy = user.id - transactionLink.save().catch(() => { - throw new Error('Could not update transaction link.') - }) + await executeTransaction( + transactionLink.amount, + transactionLink.memo, + linkedUser, + user, + transactionLink, + ) return true } diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 20b56af7e..d2bfd7f28 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -23,6 +23,7 @@ import { TransactionLinkRepository } from '@repository/TransactionLink' import { User as dbUser } from '@entity/User' import { Transaction as dbTransaction } from '@entity/Transaction' +import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' import { apiPost } from '@/apis/HttpRequest' import { TransactionTypeId } from '@enum/TransactionTypeId' @@ -39,6 +40,7 @@ export const executeTransaction = async ( memo: string, sender: dbUser, recipient: dbUser, + transactionLink?: dbTransactionLink | null, ): Promise => { if (sender.id === recipient.id) { throw new Error('Sender and Recipient are the same.') @@ -67,6 +69,7 @@ export const executeTransaction = async ( transactionSend.decay = sendBalance.decay.decay transactionSend.decayStart = sendBalance.decay.start transactionSend.previous = sendBalance.lastTransactionId + transactionSend.transactionLinkId = transactionLink ? transactionLink.id : null await queryRunner.manager.insert(dbTransaction, transactionSend) const transactionReceive = new dbTransaction() @@ -82,12 +85,23 @@ export const executeTransaction = async ( transactionReceive.decayStart = receiveBalance ? receiveBalance.decay.start : null transactionReceive.previous = receiveBalance ? receiveBalance.lastTransactionId : null transactionReceive.linkedTransactionId = transactionSend.id + transactionReceive.transactionLinkId = transactionLink ? transactionLink.id : null await queryRunner.manager.insert(dbTransaction, transactionReceive) // Save linked transaction id for send transactionSend.linkedTransactionId = transactionReceive.id await queryRunner.manager.update(dbTransaction, { id: transactionSend.id }, transactionSend) + if (transactionLink) { + transactionLink.redeemedAt = receivedCallDate + transactionLink.redeemedBy = recipient.id + await queryRunner.manager.update( + dbTransactionLink, + { id: transactionLink.id }, + transactionLink, + ) + } + await queryRunner.commitTransaction() } catch (e) { await queryRunner.rollbackTransaction() From 470cb368bfd52bd37570a1c51737af7f909bf837 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Mar 2022 16:50:36 +0100 Subject: [PATCH 6/6] add AFTER statement to sql --- database/migrations/0032-add-transaction-link-to-transaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/0032-add-transaction-link-to-transaction.ts b/database/migrations/0032-add-transaction-link-to-transaction.ts index 82c104f04..79cdf195a 100644 --- a/database/migrations/0032-add-transaction-link-to-transaction.ts +++ b/database/migrations/0032-add-transaction-link-to-transaction.ts @@ -5,7 +5,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn( - 'ALTER TABLE `transactions` ADD COLUMN `transaction_link_id` int UNSIGNED DEFAULT NULL;', + 'ALTER TABLE `transactions` ADD COLUMN `transaction_link_id` int UNSIGNED DEFAULT NULL AFTER `linked_transaction_id`;', ) }