From a34a8c2c539a5fae3a04b403bd0b35b8f94e9d46 Mon Sep 17 00:00:00 2001 From: christiansegercrantz <44305721+christiansegercrantz@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:02:09 +0300 Subject: [PATCH] Add undo function (#7) * Add undo function * Change undoing db mechanism * Stop undoing positive transactions --- backend/src/admin/saldo.ts | 4 +-- backend/src/db_setup.ts | 2 +- backend/src/index.ts | 52 ++++++++++++++++++++++++++++++++++--- backend/src/transactions.ts | 9 ++++--- backend/src/utils.ts | 16 +++++++++--- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/backend/src/admin/saldo.ts b/backend/src/admin/saldo.ts index 539a24b..2ff9258 100644 --- a/backend/src/admin/saldo.ts +++ b/backend/src/admin/saldo.ts @@ -36,9 +36,7 @@ const allHistoryCommand = bot.command('historia_all', async (ctx) => { parsedHistory.forEach((row) => { res += `\n${row.user_name.split(' ').slice(0, -1).join(' ')}, ` + - `${formatDateToString( - row.created_at - )} ${row.created_at.toLocaleTimeString('sv-fi')}, ` + + `${formatDateToString(row.created_at, true)}, ` + `${centsToEuroString(-row.amount_cents)}, ` + `${row.description}` }) diff --git a/backend/src/db_setup.ts b/backend/src/db_setup.ts index 5028986..fc9e5b4 100644 --- a/backend/src/db_setup.ts +++ b/backend/src/db_setup.ts @@ -11,7 +11,7 @@ await pool.query( `CREATE TABLE IF NOT EXISTS transactions( id SERIAL, created_at TIMESTAMP NOT NULL DEFAULT NOW(), - user_id BIGINT, + user_id BIGINT NOT NULL, user_name TEXT, description TEXT, amount_cents INTEGER diff --git a/backend/src/index.ts b/backend/src/index.ts index 17c22ed..f6d9a6a 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -2,6 +2,7 @@ import { Context, Markup, Telegraf, session } from 'telegraf' import { config } from './config.js' import { + TransactionInsert, exportTransactionsForOneUser, getBalanceForMember, purchaseItemForMember, @@ -164,7 +165,7 @@ products.forEach(({ name, description, price_cents }) => { //#region History bot.command('historia', async (ctx) => { - const history = await exportTransactionsForOneUser(ctx.from.id) + const history = await exportTransactionsForOneUser(ctx.from.id, 30) const parsedHistory = history.rows.map( ({ created_at, description, amount_cents }) => { @@ -179,9 +180,7 @@ bot.command('historia', async (ctx) => { var res = `Ditt nuvarande saldo är ${saldo}. Här är din historia:\`\`\`` parsedHistory.forEach((row) => { res += - `\n${formatDateToString( - row.created_at - )} ${row.created_at.toLocaleTimeString('sv-fi')}, ` + + `\n${formatDateToString(row.created_at, true)}, ` + `${centsToEuroString(-row.amount_cents)}, ` + `${row.description}` }) @@ -191,6 +190,50 @@ bot.command('historia', async (ctx) => { //endregion +//#region Undo + +bot.command('undo', async (ctx) => { + const queryResult = await exportTransactionsForOneUser(ctx.from.id, 1) + const latestTransaction = queryResult.rows[0] + + const description = latestTransaction.description + if (description.includes('_undo') || description.includes('Manuell_')) { + return ctx.reply('Din senaste händelse är redan ångrad') + } + + if (latestTransaction.amount_cents > 0) { + return ctx.reply('Du kan inte ångra en insättning') + } + + try { + const productUndone = { + userId: latestTransaction.user_id, + userName: latestTransaction.user_name, + description: latestTransaction.description + '_undo', + amountCents: String(-latestTransaction.amount_cents), + } as TransactionInsert + await purchaseItemForMember(productUndone) + + const message = + 'Följande transaction har ångrats: \n' + + `\t\tTid: ${formatDateToString(latestTransaction.created_at, true)}\n` + + `\t\tProdukt: ${latestTransaction.description}\n` + + `\t\tPris: ${centsToEuroString(latestTransaction.amount_cents)}` + + ctx.reply(message) + console.log( + `User id ${ctx.from.id} undid transaction id ${latestTransaction.id}` + ) + } catch (e) { + ctx.reply('Kunde inte ångra din senaste transaktion, kontakta Cropieren') + console.log( + `User id ${ctx.from.id} tried to undo a transaction and faced the following problem error: ${e}` + ) + } +}) + +//endregion + //#region Misc commands bot.command('saldo', async (ctx) => { @@ -217,6 +260,7 @@ bot.telegram.setMyCommands([ { command: 'info', description: 'Visar information om bottens användning' }, { command: 'meny', description: 'Tar upp köp menyn för alla produkter' }, { command: 'historia', description: 'Se din egna transaktionshistorik' }, + { command: 'undo', description: 'Ångra ditt senaste köp' }, ]) // Admin middleware is used for all commands added after this line! diff --git a/backend/src/transactions.ts b/backend/src/transactions.ts index 5a390fd..d8f48ad 100644 --- a/backend/src/transactions.ts +++ b/backend/src/transactions.ts @@ -5,7 +5,7 @@ import { QueryResult } from 'pg' export interface Transaction { id: number created_at: Date - userId: number + user_id: number user_name: string description: string amount_cents: number @@ -60,7 +60,8 @@ export const exportTransactions = async (): Promise< } export const exportTransactionsForOneUser = async ( - userId: number + userId: number, + transactionCount: number ): Promise> => { const res = await pool.query( `--sql @@ -68,8 +69,8 @@ export const exportTransactionsForOneUser = async ( FROM transactions WHERE user_id = $1 ORDER BY id DESC - LIMIT 30`, - [userId] + LIMIT $2`, + [userId, transactionCount] ) return res } diff --git a/backend/src/utils.ts b/backend/src/utils.ts index 9145e97..60bdd38 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -13,12 +13,22 @@ export const createCsv = (queryResult: QueryResult) => { ${rows.join('\n')}` } -export const formatDateToString = (date: Date) => { - return `${date.toLocaleDateString('sv-fi', { +export const formatDateToString = ( + date: Date, + includeTime: Boolean = false +) => { + const dateFormated = date.toLocaleDateString('sv-fi', { year: '2-digit', month: '2-digit', day: '2-digit', - })} ${date.toLocaleDateString('sv-fi', { weekday: 'short' })}` + }) + const dayFormated = date.toLocaleDateString('sv-fi', { + weekday: 'short', + }) + const timeFormated = includeTime + ? `kl. ${date.toLocaleTimeString('sv-fi')}` + : '' + return `${dateFormated} ${dayFormated} ${timeFormated}` } /**