From bf086e7866d5d4cc3d26a6375c6497f9314de6b8 Mon Sep 17 00:00:00 2001 From: Einhornimmond Date: Tue, 28 Jun 2022 16:41:43 +0200 Subject: [PATCH 01/75] add migration script begin --- ...0041-update_transactions_for_blockchain.ts | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 database/migrations/0041-update_transactions_for_blockchain.ts diff --git a/database/migrations/0041-update_transactions_for_blockchain.ts b/database/migrations/0041-update_transactions_for_blockchain.ts new file mode 100644 index 000000000..9662d84cf --- /dev/null +++ b/database/migrations/0041-update_transactions_for_blockchain.ts @@ -0,0 +1,81 @@ +/* MIGRATION for updating transactions from the past to follow the blockchain rules*/ +/* 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>) { + // split creation transaction with 3000 GDD created in one transaction what isn't allowed + const transactionDivData = [ + {date: new Date('2019-12-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Dez'}, + {date: new Date('2019-01-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Jan'}, + {date: new Date('2019-02-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Feb'} + ] + /* + | id | int(10) unsigned | NO | PRI | NULL | auto_increment | + | user_id | int(10) | YES | | NULL | | + | previous | int(10) unsigned | YES | UNI | NULL | | + | type_id | int(10) | YES | | NULL | | + | amount | decimal(40,20) | YES | | NULL | | + | balance | decimal(40,20) | YES | | NULL | | + | balance_date | datetime | NO | | current_timestamp() | | + | decay | decimal(40,20) | YES | | NULL | | + | decay_start | datetime | YES | | NULL | | + | memo | varchar(255) | NO | | NULL | | + | creation_date | datetime | YES | | NULL | | + | linked_user_id | int(10) unsigned | YES | | NULL | | + | linked_transaction_id | int(10) | YES | | NULL | | + | transaction_link_id | int(10) unsigned | YES | | NULL | | + + */ + + transactionDivData.forEach(({date:Date, memo:string}, index)=> { + if(!index) { + queryFn(` + INSERT INTO transactions( + user_id, type_id, amount, balance, + balance_date, decay, decay_start, + memo, creation_date, linked_user_id + ) VALUES( + 275, 1, 1000, ?, + ? + )`, [1000 * (index + 1), date]) + + } else { + //queryFn('INSERT INTO transactions(user_id, previous, type_id, amount, balance, balance_date, decay, decay_start, memo, creation_date, linked_user_id)') + } + + }) + /* + Profiler splitTransactionTime; + Poco::Data::Statement insertTransactions(dbSession); + std::string memo; + Poco::DateTime received(2020, 3, 30, 8, 59, 55); + insertTransactions << "INSERT INTO " << mTempTransactionsTableName + << "(transaction_type_id, memo, received) VALUES(1, ?, ?)", + use(memo), use(received); + + Poco::Data::Statement insertCreationTransactions(dbSession); + int amount = 10000000; + Poco::DateTime targetDate(2019, 12, 1, 1, 0, 0); + insertCreationTransactions << "INSERT INTO " << mTempCreationTableName + << "(transaction_id, state_user_id, amount, target_date) VALUES(LAST_INSERT_ID(), 275, ?, ?)", + use(amount), use(targetDate); + + for (auto it = transactionDivData.begin(); it != transactionDivData.end(); it++) { + targetDate = it->first; + memo = it->second; + insertTransactions.execute(); + insertCreationTransactions.execute(); + } + Poco::Data::Statement removeInvalidTransaction(dbSession); + removeInvalidTransaction << "delete from " << mTempCreationTableName << " where id = 150", now; + removeInvalidTransaction.reset(dbSession); + removeInvalidTransaction << "delete from " << mTempTransactionsTableName << " where id = 224", now; + speedLog.information("time for split transaction: %s", splitTransactionTime.string()); + */ + //await queryFn('DROP TABLE `user_setting`;') + } + + export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + + } + \ No newline at end of file From dbe2ec4845390e116dd210cb1f04ae4356a1c4df Mon Sep 17 00:00:00 2001 From: Dario bb Date: Tue, 28 Jun 2022 18:29:00 +0200 Subject: [PATCH 02/75] implement code translated in js from c++ from gradido blockchain connector --- ...0041-update_transactions_for_blockchain.ts | 170 ++++++++++++------ 1 file changed, 112 insertions(+), 58 deletions(-) diff --git a/database/migrations/0041-update_transactions_for_blockchain.ts b/database/migrations/0041-update_transactions_for_blockchain.ts index 9662d84cf..3f4e47abb 100644 --- a/database/migrations/0041-update_transactions_for_blockchain.ts +++ b/database/migrations/0041-update_transactions_for_blockchain.ts @@ -1,15 +1,19 @@ -/* MIGRATION for updating transactions from the past to follow the blockchain rules*/ +/* MIGRATION for updating transactions from the past to follow the blockchain rules */ /* 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>) { - // split creation transaction with 3000 GDD created in one transaction what isn't allowed - const transactionDivData = [ - {date: new Date('2019-12-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Dez'}, - {date: new Date('2019-01-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Jan'}, - {date: new Date('2019-02-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Feb'} - ] - /* + interface TransactionDivData { + date: Date + memo: string + } + // split creation transaction with 3000 GDD created in one transaction what isn't allowed + const transactionDivData: TransactionDivData[] = [ + { date: new Date('2019-12-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Dez' }, + { date: new Date('2019-01-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Jan' }, + { date: new Date('2019-02-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Feb' }, + ] + /* | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | user_id | int(10) | YES | | NULL | | | previous | int(10) unsigned | YES | UNI | NULL | | @@ -26,56 +30,106 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis | transaction_link_id | int(10) unsigned | YES | | NULL | | */ - - transactionDivData.forEach(({date:Date, memo:string}, index)=> { - if(!index) { - queryFn(` - INSERT INTO transactions( - user_id, type_id, amount, balance, - balance_date, decay, decay_start, - memo, creation_date, linked_user_id - ) VALUES( - 275, 1, 1000, ?, - ? - )`, [1000 * (index + 1), date]) - - } else { - //queryFn('INSERT INTO transactions(user_id, previous, type_id, amount, balance, balance_date, decay, decay_start, memo, creation_date, linked_user_id)') - } - - }) - /* - Profiler splitTransactionTime; - Poco::Data::Statement insertTransactions(dbSession); - std::string memo; - Poco::DateTime received(2020, 3, 30, 8, 59, 55); - insertTransactions << "INSERT INTO " << mTempTransactionsTableName - << "(transaction_type_id, memo, received) VALUES(1, ?, ?)", - use(memo), use(received); - Poco::Data::Statement insertCreationTransactions(dbSession); - int amount = 10000000; - Poco::DateTime targetDate(2019, 12, 1, 1, 0, 0); - insertCreationTransactions << "INSERT INTO " << mTempCreationTableName - << "(transaction_id, state_user_id, amount, target_date) VALUES(LAST_INSERT_ID(), 275, ?, ?)", - use(amount), use(targetDate); - - for (auto it = transactionDivData.begin(); it != transactionDivData.end(); it++) { - targetDate = it->first; - memo = it->second; - insertTransactions.execute(); - insertCreationTransactions.execute(); + transactionDivData.forEach((transactionDivData, index) => { + let sqlQuery = "INSERT INTO 'transactions'(user_id," + let sqlValues = 'VALUES(275,' + if (index) { + sqlQuery += 'previous,' + sqlValues += 'LAST_INSERT_ID()' } - Poco::Data::Statement removeInvalidTransaction(dbSession); - removeInvalidTransaction << "delete from " << mTempCreationTableName << " where id = 150", now; - removeInvalidTransaction.reset(dbSession); - removeInvalidTransaction << "delete from " << mTempTransactionsTableName << " where id = 224", now; - speedLog.information("time for split transaction: %s", splitTransactionTime.string()); - */ - //await queryFn('DROP TABLE `user_setting`;') + sqlQuery += `type_id, amount, balance, + balance_date, + memo, creation_date` + sqlValues += '1, 1000, ?, ?, ?, ?' + + sqlQuery += ')' + sqlValues += ')' + queryFn(sqlQuery + sqlValues, [ + 1000 * (index + 1), + transactionDivData.date, + transactionDivData.memo, + transactionDivData.date, + ]) + }) + // remove original transaction + queryFn("DELETE FROM 'transactions' where id = 150") + + // update previous field of first transaction after splitted transaction + queryFn("UPDATE 'transactions' SET 'previous' = LAST_INSERT_ID() WHERE 'previous' = 150") + + // ---------------------------------------------------------------------------------------------- + // update creation_date for transactions with creation_date == balance_date + // !cannot made be undone easily! + + // update entries from which memo contain month name (most cases) + interface ReplaceSet { + monthName: string + monthValue: number + yearValue: number } - - export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { - - } - \ No newline at end of file + const replaceSets: ReplaceSet[] = [ + { monthName: 'Dez', monthValue: 12, yearValue: 2019 }, + { monthName: 'Jan', monthValue: 1, yearValue: 2020 }, + { monthName: 'Feb', monthValue: 2, yearValue: 2020 }, + { monthName: 'M_rz', monthValue: 3, yearValue: 2020 }, + { monthName: 'April', monthValue: 4, yearValue: 2020 }, + ] + replaceSets.forEach((replaceSet) => { + let sqlQuery = `update 'transactions' + SET 'creation_date' = DATE_FORMAT('creation_date', CONCAT(?, '-', ?, '-', ` + if (replaceSet.monthName === 'Feb') { + sqlQuery += "IF(DATE_FORMAT(creation_date, '%d') <= 28, '%d', 28)" + } else { + sqlQuery += "'%d'" + } + sqlQuery += `, ' %H:%i:%s')) + WHERE balance_date = creation_date + AND type_id = 1 + AND memo LIKE '%?%'` + + queryFn(sqlQuery, [replaceSet.yearValue, replaceSet.monthValue, replaceSet.monthName]) + }) + + // update entries without month name in memo, simply move creation_date 1 month before balance_date + queryFn(`UPDATE 'transactions' + set creation_date = CAST(DATE_FORMAT(creation_date, CONCAT( + IF(DATE_FORMAT(creation_date, '%m') = 1, DATE_FORMAT(creation_date, '%Y') - 1, '%Y'), + '-', + IF(DATE_FORMAT(creation_date, '%m') = 1, 12, DATE_FORMAT(creation_date, '%m') - 1), + '-', + IF(DATE_FORMAT(creation_date, '%m') = 3, IF(DATE_FORMAT(creation_date, '%d') <= 28, '%d', 28), '%d'), + ' %H:%i:%s')) AS DATETIME) + WHERE balance_date = creation_date + `) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // remove in upgrade added transactions + const creationDates: Date[] = [ + new Date('2019-12-01T01:00:00'), + new Date('2019-01-01T01:00:00'), + new Date('2019-02-01T01:00:00'), + ] + queryFn( + "DELETE FROM 'transactions' WHERE 'user_id' = 275 AND 'creation_date' IN(?,?,?)", + creationDates, + ) + // put back removed transaction + queryFn( + `INSERT INTO 'transactions'( + id, user_id, + type_id, amount, + balance, balance_date, + memo, creation_date + ) VALUES( + 150, 275, + 1, 3000, + 3000, '2020-03-30 06:59:55', + 'Aktives Grundeinkommen für GL. Dez, Jan, Feb', '2020-03-30 06:59:55' + )`, + ) + + // restore previous field of first transaction after splitted transaction + queryFn("UPDATE 'transactions' SET 'previous' = 150 WHERE 'id' = 278") +} From ac18a11256dce888091de1307d9a19dc799d0d50 Mon Sep 17 00:00:00 2001 From: Einhornimmond Date: Wed, 29 Jun 2022 12:38:20 +0200 Subject: [PATCH 03/75] simplify code --- ...0041-update_transactions_for_blockchain.ts | 100 +++++------------- 1 file changed, 26 insertions(+), 74 deletions(-) diff --git a/database/migrations/0041-update_transactions_for_blockchain.ts b/database/migrations/0041-update_transactions_for_blockchain.ts index 3f4e47abb..98f794693 100644 --- a/database/migrations/0041-update_transactions_for_blockchain.ts +++ b/database/migrations/0041-update_transactions_for_blockchain.ts @@ -3,60 +3,31 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { - interface TransactionDivData { - date: Date - memo: string - } // split creation transaction with 3000 GDD created in one transaction what isn't allowed - const transactionDivData: TransactionDivData[] = [ - { date: new Date('2019-12-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Dez' }, - { date: new Date('2019-01-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Jan' }, - { date: new Date('2019-02-01T01:00:00'), memo: 'Aktives Grundeinkommen für GL. Feb' }, + const transactionMemos: string[] = [ + 'Aktives Grundeinkommen für GL. Dez', + 'Aktives Grundeinkommen für GL. Jan', + 'Aktives Grundeinkommen für GL. Feb', ] - /* - | id | int(10) unsigned | NO | PRI | NULL | auto_increment | - | user_id | int(10) | YES | | NULL | | - | previous | int(10) unsigned | YES | UNI | NULL | | - | type_id | int(10) | YES | | NULL | | - | amount | decimal(40,20) | YES | | NULL | | - | balance | decimal(40,20) | YES | | NULL | | - | balance_date | datetime | NO | | current_timestamp() | | - | decay | decimal(40,20) | YES | | NULL | | - | decay_start | datetime | YES | | NULL | | - | memo | varchar(255) | NO | | NULL | | - | creation_date | datetime | YES | | NULL | | - | linked_user_id | int(10) unsigned | YES | | NULL | | - | linked_transaction_id | int(10) | YES | | NULL | | - | transaction_link_id | int(10) unsigned | YES | | NULL | | + const creationDate = new Date('2020-03-30 06:59:55') - */ - - transactionDivData.forEach((transactionDivData, index) => { - let sqlQuery = "INSERT INTO 'transactions'(user_id," - let sqlValues = 'VALUES(275,' - if (index) { - sqlQuery += 'previous,' - sqlValues += 'LAST_INSERT_ID()' - } - sqlQuery += `type_id, amount, balance, - balance_date, - memo, creation_date` - sqlValues += '1, 1000, ?, ?, ?, ?' - - sqlQuery += ')' - sqlValues += ')' - queryFn(sqlQuery + sqlValues, [ - 1000 * (index + 1), - transactionDivData.date, - transactionDivData.memo, - transactionDivData.date, - ]) - }) - // remove original transaction - queryFn("DELETE FROM 'transactions' where id = 150") - - // update previous field of first transaction after splitted transaction - queryFn("UPDATE 'transactions' SET 'previous' = LAST_INSERT_ID() WHERE 'previous' = 150") + queryFn(`UPDATE 'transactions' set amount = 1000, memo = ? WHERE id = 150`, [transactionMemos[0]]) + queryFn( + `INSERT INTO 'transactions'( + user_id, previous, type_id, amount, balance, balance_date, memo, creation_date + ) VALUES( + 275, 150, 1, 1000, 2000, ?, ?, ? + )`, + [creationDate, transactionMemos[1], creationDate], + ) + queryFn( + `INSERT INTO 'transactions'( + user_id, previous, type_id, amount, balance, balance_date, memo, creation_date + ) VALUES( + 275, LAST_INSERT_ID(), 1, 1000, 3000, ?, ?, ? + )`, + [creationDate, transactionMemos[2], creationDate], + ) // ---------------------------------------------------------------------------------------------- // update creation_date for transactions with creation_date == balance_date @@ -105,31 +76,12 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { - // remove in upgrade added transactions - const creationDates: Date[] = [ - new Date('2019-12-01T01:00:00'), - new Date('2019-01-01T01:00:00'), - new Date('2019-02-01T01:00:00'), - ] + // remove added transaction queryFn( - "DELETE FROM 'transactions' WHERE 'user_id' = 275 AND 'creation_date' IN(?,?,?)", - creationDates, + "DELETE FROM 'transactions' WHERE 'user_id' = 275 AND 'balance' IN(2000, 3000) AND 'amount' = 1000", ) - // put back removed transaction + // rewind transaction to split queryFn( - `INSERT INTO 'transactions'( - id, user_id, - type_id, amount, - balance, balance_date, - memo, creation_date - ) VALUES( - 150, 275, - 1, 3000, - 3000, '2020-03-30 06:59:55', - 'Aktives Grundeinkommen für GL. Dez, Jan, Feb', '2020-03-30 06:59:55' - )`, + `UPDATE 'transactions' set amount = 3000, memo = 'Aktives Grundeinkommen für GL. Dez, Jan, Feb' WHERE id = 150`, ) - - // restore previous field of first transaction after splitted transaction - queryFn("UPDATE 'transactions' SET 'previous' = 150 WHERE 'id' = 278") } From 88e789c53edfd1c711a37e30e6b846d0e0d4362d Mon Sep 17 00:00:00 2001 From: Einhornimmond Date: Wed, 29 Jun 2022 16:09:31 +0200 Subject: [PATCH 04/75] tested and fixed --- ...0041-update_transactions_for_blockchain.ts | 87 ++++++++++++------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/database/migrations/0041-update_transactions_for_blockchain.ts b/database/migrations/0041-update_transactions_for_blockchain.ts index 98f794693..6ecdfffa9 100644 --- a/database/migrations/0041-update_transactions_for_blockchain.ts +++ b/database/migrations/0041-update_transactions_for_blockchain.ts @@ -11,28 +11,46 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis ] const creationDate = new Date('2020-03-30 06:59:55') - queryFn(`UPDATE 'transactions' set amount = 1000, memo = ? WHERE id = 150`, [transactionMemos[0]]) - queryFn( - `INSERT INTO 'transactions'( - user_id, previous, type_id, amount, balance, balance_date, memo, creation_date + await queryFn(`UPDATE \`transactions\` set \`amount\` = 1000, \`balance\` = 1000, \`memo\` = ? WHERE \`id\` = 150`, [ + transactionMemos[0], + ]) + + // [ RowDataPacket { 'MAX(`id`)': 6828 } ] + const lastTransactionId = (await queryFn(`SELECT MAX(\`id\`) as max_id from \`transactions\``))[0].max_id + // dummy id to insert two transactions before this (previous has an index on it) + await queryFn(`UPDATE \`transactions\` set \`previous\` = ? WHERE \`id\` = 278`, [lastTransactionId + 30]) + + await queryFn( + `INSERT INTO \`transactions\`( + \`user_id\`, \`previous\`, \`type_id\`, \`amount\`, \`balance\`, + \`balance_date\`, \`decay\`, \`memo\`, \`creation_date\` ) VALUES( - 275, 150, 1, 1000, 2000, ?, ?, ? + 275, 150, 1, 1000, 2000, + ?, 0, ?, ? )`, [creationDate, transactionMemos[1], creationDate], ) - queryFn( - `INSERT INTO 'transactions'( - user_id, previous, type_id, amount, balance, balance_date, memo, creation_date + await queryFn( + `INSERT INTO \`transactions\`( + \`user_id\`, \`previous\`, \`type_id\`, \`amount\`, \`balance\`, + \`balance_date\`, \`decay\`, \`memo\`, \`creation_date\` ) VALUES( - 275, LAST_INSERT_ID(), 1, 1000, 3000, ?, ?, ? + 275, LAST_INSERT_ID(), 1, 1000, 3000, + ?, 0, ?, ? )`, - [creationDate, transactionMemos[2], creationDate], + [creationDate, transactionMemos[2], creationDate], ) + await queryFn(`UPDATE \`transactions\` set \`previous\` = LAST_INSERT_ID() WHERE \`id\` = 278`) // ---------------------------------------------------------------------------------------------- // update creation_date for transactions with creation_date == balance_date // !cannot made be undone easily! + // make copy of transaction_creations table for easy debugging workflow + await queryFn(`DROP TABLE IF EXISTS \`transactions_temp\``) + await queryFn(`CREATE TABLE \`transactions_temp\` LIKE transactions`) + await queryFn(`INSERT INTO \`transactions_temp\` SELECT * FROM \`transactions\``) + // update entries from which memo contain month name (most cases) interface ReplaceSet { monthName: string @@ -40,30 +58,30 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis yearValue: number } const replaceSets: ReplaceSet[] = [ - { monthName: 'Dez', monthValue: 12, yearValue: 2019 }, - { monthName: 'Jan', monthValue: 1, yearValue: 2020 }, - { monthName: 'Feb', monthValue: 2, yearValue: 2020 }, - { monthName: 'M_rz', monthValue: 3, yearValue: 2020 }, - { monthName: 'April', monthValue: 4, yearValue: 2020 }, + { monthName: '%Dez%', monthValue: 12, yearValue: 2019 }, + { monthName: '%Jan%', monthValue: 1, yearValue: 2020 }, + { monthName: '%Feb%', monthValue: 2, yearValue: 2020 }, + { monthName: '%M_rz%', monthValue: 3, yearValue: 2020 }, + { monthName: '%April%', monthValue: 4, yearValue: 2020 }, ] - replaceSets.forEach((replaceSet) => { - let sqlQuery = `update 'transactions' - SET 'creation_date' = DATE_FORMAT('creation_date', CONCAT(?, '-', ?, '-', ` - if (replaceSet.monthName === 'Feb') { - sqlQuery += "IF(DATE_FORMAT(creation_date, '%d') <= 28, '%d', 28)" + for(const replaceSet of replaceSets) { + let sqlQuery = `update \`transactions_temp\` + SET \`creation_date\` = DATE_FORMAT(\`creation_date\`, CONCAT(?, '-', ?, '-', ` + if (replaceSet.monthName === '%Feb%') { + sqlQuery += "IF(DATE_FORMAT(`creation_date`, '%d') <= 28, '%d', 28)" } else { sqlQuery += "'%d'" } sqlQuery += `, ' %H:%i:%s')) - WHERE balance_date = creation_date - AND type_id = 1 - AND memo LIKE '%?%'` + WHERE \`balance_date\` = \`creation_date\` + AND \`type_id\` = 1 + AND \`memo\` LIKE ?` - queryFn(sqlQuery, [replaceSet.yearValue, replaceSet.monthValue, replaceSet.monthName]) - }) + await queryFn(sqlQuery, [replaceSet.yearValue, replaceSet.monthValue, replaceSet.monthName]) + } // update entries without month name in memo, simply move creation_date 1 month before balance_date - queryFn(`UPDATE 'transactions' + await queryFn(`UPDATE \`transactions_temp\` set creation_date = CAST(DATE_FORMAT(creation_date, CONCAT( IF(DATE_FORMAT(creation_date, '%m') = 1, DATE_FORMAT(creation_date, '%Y') - 1, '%Y'), '-', @@ -71,17 +89,24 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis '-', IF(DATE_FORMAT(creation_date, '%m') = 3, IF(DATE_FORMAT(creation_date, '%d') <= 28, '%d', 28), '%d'), ' %H:%i:%s')) AS DATETIME) - WHERE balance_date = creation_date + WHERE balance_date = creation_date `) } + export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // remove added transaction - queryFn( - "DELETE FROM 'transactions' WHERE 'user_id' = 275 AND 'balance' IN(2000, 3000) AND 'amount' = 1000", + await queryFn( + `DELETE FROM \`transactions\` + WHERE \`user_id\` = 275 AND \`balance\` IN (2000, 3000) AND \`amount\` = 1000`, ) + // rewind transaction to split - queryFn( - `UPDATE 'transactions' set amount = 3000, memo = 'Aktives Grundeinkommen für GL. Dez, Jan, Feb' WHERE id = 150`, + await queryFn( + `UPDATE \`transactions\` set \`amount\` = 3000, \`memo\` = 'Aktives Grundeinkommen für GL. Dez, Jan, Feb' + WHERE \`id\` = 150`, ) + + await queryFn(`UPDATE \`transactions\` set \`previous\` = 150 WHERE \`id\` = 278`) } From f8b0d52afd9b68be757e609bd215fa2c35e3c912 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 30 Jun 2022 13:57:30 +0200 Subject: [PATCH 05/75] Add ROLES and RIGHTS for users to query listContributions. --- backend/src/auth/RIGHTS.ts | 1 + backend/src/auth/ROLES.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index c10fc96de..6a6f8b7c0 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -26,6 +26,7 @@ export enum RIGHTS { LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS', GDT_BALANCE = 'GDT_BALANCE', CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION', + LIST_CONTRIBUTIONS = 'LIST_CONTRIBUTIONS', // Admin SEARCH_USERS = 'SEARCH_USERS', SET_USER_ROLE = 'SET_USER_ROLE', diff --git a/backend/src/auth/ROLES.ts b/backend/src/auth/ROLES.ts index 2d9ac2deb..f56106664 100644 --- a/backend/src/auth/ROLES.ts +++ b/backend/src/auth/ROLES.ts @@ -24,6 +24,7 @@ export const ROLE_USER = new Role('user', [ RIGHTS.LIST_TRANSACTION_LINKS, RIGHTS.GDT_BALANCE, RIGHTS.CREATE_CONTRIBUTION, + RIGHTS.LIST_CONTRIBUTIONS, ]) export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights From f19a6f1d15a14331711305e83e7a0df848c98923 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 30 Jun 2022 13:58:21 +0200 Subject: [PATCH 06/75] Create model for Contribution and create function to query listContributions. --- backend/src/graphql/model/Contribution.ts | 44 ++++++++++++++++ .../graphql/resolver/ContributionResolver.ts | 51 +++++++++++++++++-- 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 backend/src/graphql/model/Contribution.ts diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts new file mode 100644 index 000000000..cd8c94d74 --- /dev/null +++ b/backend/src/graphql/model/Contribution.ts @@ -0,0 +1,44 @@ +import { ObjectType, Field, Int } from 'type-graphql' +import Decimal from 'decimal.js-light' +import { Contribution as dbContribution } from '@entity/Contribution' +import { User } from './User' +import CONFIG from '@/config' + +@ObjectType() +export class Contribution { + constructor(contribution: dbContribution, user: User) { + this.id = contribution.id + this.user = user + this.amount = contribution.amount + this.memo = contribution.memo + this.createdAt = contribution.createdAt + this.deletedAt = contribution.deletedAt + } + + @Field(() => Number) + id: number + + @Field(() => User) + user: User + + @Field(() => Decimal) + amount: Decimal + + @Field(() => String) + memo: string + + @Field(() => Date) + createdAt: Date + + @Field(() => Date, { nullable: true }) + deletedAt: Date | null +} + +@ObjectType() +export class ContributionListResult { + @Field(() => Int) + linkCount: number + + @Field(() => [Contribution]) + linkList: Contribution[] +} diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 924108f87..c3b4c2127 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -1,10 +1,15 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' -import { Contribution } from '@entity/Contribution' -import { Args, Authorized, Ctx, Mutation, Resolver } from 'type-graphql' +import { Contribution as dbContribution } from '@entity/Contribution' +import { Arg, Args, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql' +import { IsNull, Not } from '../../../../database/node_modules/typeorm' import ContributionArgs from '../arg/ContributionArgs' +import Paginated from '../arg/Paginated' +import { Order } from '../enum/Order' +import { Contribution } from '../model/Contribution' import { UnconfirmedContribution } from '../model/UnconfirmedContribution' +import { User } from '../model/User' import { isContributionValid, getUserCreation } from './util/isContributionValid' @Resolver() @@ -21,7 +26,7 @@ export class ContributionResolver { const creationDateObj = new Date(creationDate) isContributionValid(creations, amount, creationDateObj) - const contribution = Contribution.create() + const contribution = dbContribution.create() contribution.userId = user.id contribution.amount = amount contribution.createdAt = new Date() @@ -29,7 +34,45 @@ export class ContributionResolver { contribution.memo = memo logger.trace('contribution to save', contribution) - await Contribution.save(contribution) + await dbContribution.save(contribution) return new UnconfirmedContribution(contribution, user, creations) } + + @Authorized([RIGHTS.LIST_CONTRIBUTIONS]) + @Query(() => [Contribution]) + async listContributions( + @Args() + { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, + @Arg('filterConfirmed', () => Boolean) + filterConfirmed: boolean | null, + @Ctx() context: Context, + ): Promise { + const user = getUser(context) + let contribution + if (filterConfirmed) { + contribution = await dbContribution.find({ + where: { + userId: user.id, + confirmedBy: IsNull(), + }, + order: { + createdAt: order, + }, + skip: (currentPage - 1) * pageSize, + take: pageSize, + }) + } else { + contribution = await dbContribution.find({ + where: { + userId: user.id, + }, + order: { + createdAt: order, + }, + skip: (currentPage - 1) * pageSize, + take: pageSize, + }) + } + return contribution.map((contr) => new Contribution(contr, new User(user))) + } } From 3ce80fc081101df68d6ecb92287c6fd19e921517 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 30 Jun 2022 16:47:44 +0200 Subject: [PATCH 07/75] Remove unused imports. --- backend/src/graphql/model/Contribution.ts | 1 - backend/src/graphql/resolver/ContributionResolver.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index cd8c94d74..dc1dd39e9 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -2,7 +2,6 @@ import { ObjectType, Field, Int } from 'type-graphql' import Decimal from 'decimal.js-light' import { Contribution as dbContribution } from '@entity/Contribution' import { User } from './User' -import CONFIG from '@/config' @ObjectType() export class Contribution { diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c3b4c2127..6669ef20d 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -3,7 +3,7 @@ import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' import { Arg, Args, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql' -import { IsNull, Not } from '../../../../database/node_modules/typeorm' +import { IsNull } from '../../../../database/node_modules/typeorm' import ContributionArgs from '../arg/ContributionArgs' import Paginated from '../arg/Paginated' import { Order } from '../enum/Order' From 1d862153751851b104f4b6be13fae3077662dab4 Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 1 Jul 2022 11:11:17 +0200 Subject: [PATCH 08/75] change link color --- frontend/src/components/Auth/AuthNavbar.vue | 4 ++-- frontend/src/components/LanguageSwitch2.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Auth/AuthNavbar.vue b/frontend/src/components/Auth/AuthNavbar.vue index e1f47e5a7..1192d6db3 100644 --- a/frontend/src/components/Auth/AuthNavbar.vue +++ b/frontend/src/components/Auth/AuthNavbar.vue @@ -46,7 +46,7 @@ export default {