mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge remote-tracking branch 'origin/master' into
1798-feature-gradidoid-1-adapt-and-migrate-database-schema
This commit is contained in:
commit
b3bf7fecc4
@ -8,10 +8,7 @@ import { Context, getUser } from '@/server/context'
|
||||
import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql'
|
||||
import { getCustomRepository, getConnection } from '@dbTools/typeorm'
|
||||
|
||||
import {
|
||||
sendTransactionLinkRedeemedEmail,
|
||||
sendTransactionReceivedEmail,
|
||||
} from '@/mailer/sendTransactionReceivedEmail'
|
||||
import { sendTransactionReceivedEmail } from '@/mailer/sendTransactionReceivedEmail'
|
||||
|
||||
import { Transaction } from '@model/Transaction'
|
||||
import { TransactionList } from '@model/TransactionList'
|
||||
@ -39,6 +36,7 @@ import Decimal from 'decimal.js-light'
|
||||
import { BalanceResolver } from './BalanceResolver'
|
||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
|
||||
import { findUserByEmail } from './UserResolver'
|
||||
import { sendTransactionLinkRedeemedEmail } from '@/mailer/sendTransactionLinkRedeemed'
|
||||
|
||||
export const executeTransaction = async (
|
||||
amount: Decimal,
|
||||
@ -155,7 +153,6 @@ export const executeTransaction = async (
|
||||
email: recipient.emailContact.email,
|
||||
senderEmail: sender.emailContact.email,
|
||||
amount,
|
||||
memo,
|
||||
overviewURL: CONFIG.EMAIL_LINK_OVERVIEW,
|
||||
})
|
||||
if (transactionLink) {
|
||||
|
||||
@ -4,7 +4,14 @@
|
||||
import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
import { createUser, setPassword, forgotPassword, updateUserInfos } from '@/seeds/graphql/mutations'
|
||||
import {
|
||||
createUser,
|
||||
setPassword,
|
||||
forgotPassword,
|
||||
updateUserInfos,
|
||||
createContribution,
|
||||
confirmContribution,
|
||||
} from '@/seeds/graphql/mutations'
|
||||
import { login, logout, verifyLogin, queryOptIn, searchAdminUsers } from '@/seeds/graphql/queries'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import { User } from '@entity/User'
|
||||
@ -14,16 +21,19 @@ import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegi
|
||||
import { sendResetPasswordEmail } from '@/mailer/sendResetPasswordEmail'
|
||||
import { printTimeDuration, activationLink } from './UserResolver'
|
||||
import { contributionLinkFactory } from '@/seeds/factory/contributionLink'
|
||||
// import { transactionLinkFactory } from '@/seeds/factory/transactionLink'
|
||||
import { transactionLinkFactory } from '@/seeds/factory/transactionLink'
|
||||
import { ContributionLink } from '@model/ContributionLink'
|
||||
// import { TransactionLink } from '@entity/TransactionLink'
|
||||
import { TransactionLink } from '@entity/TransactionLink'
|
||||
|
||||
import { EventProtocolType } from '@/event/EventProtocolType'
|
||||
import { EventProtocol } from '@entity/EventProtocol'
|
||||
import { logger } from '@test/testSetup'
|
||||
import { validate as validateUUID, version as versionUUID } from 'uuid'
|
||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||
import { UserContact } from '@entity/UserContact'
|
||||
import { OptInType } from '../enum/OptInType'
|
||||
import { UserContactType } from '../enum/UserContactType'
|
||||
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
|
||||
|
||||
// import { klicktippSignIn } from '@/apis/KlicktippController'
|
||||
|
||||
@ -175,6 +185,15 @@ describe('UserResolver', () => {
|
||||
duration: expect.any(String),
|
||||
})
|
||||
})
|
||||
|
||||
it('stores the send confirmation event in the database', () => {
|
||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
|
||||
userId: user[0].id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('email already exists', () => {
|
||||
@ -215,13 +234,12 @@ describe('UserResolver', () => {
|
||||
variables: { ...variables, email: 'bibi@bloxberg.de', language: 'it' },
|
||||
})
|
||||
await expect(User.find({ relations: ['emailContact'] })).resolves.toContain(
|
||||
expect.objectContaining({
|
||||
emailContact: expect.objectContaining({
|
||||
email: 'bibi@bloxberg.de',
|
||||
}),
|
||||
language: 'de',
|
||||
expect.objectContaining({
|
||||
emailContact: expect.objectContaining({
|
||||
email: 'bibi@bloxberg.de',
|
||||
}),
|
||||
]),
|
||||
language: 'de',
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -246,33 +264,47 @@ describe('UserResolver', () => {
|
||||
})
|
||||
|
||||
describe('redeem codes', () => {
|
||||
let result: any
|
||||
let link: ContributionLink
|
||||
|
||||
describe('contribution link', () => {
|
||||
let link: ContributionLink
|
||||
beforeAll(async () => {
|
||||
// activate account of admin Peter Lustig
|
||||
await mutate({
|
||||
mutation: setPassword,
|
||||
variables: { code: emailVerificationCode, password: 'Aa12345_' },
|
||||
})
|
||||
|
||||
// make Peter Lustig Admin
|
||||
const peter = await User.findOneOrFail({ id: user[0].id })
|
||||
peter.isAdmin = new Date()
|
||||
await peter.save()
|
||||
|
||||
// date statement
|
||||
const actualDate = new Date()
|
||||
const futureDate = new Date() // Create a future day from the executed day
|
||||
futureDate.setDate(futureDate.getDate() + 1)
|
||||
|
||||
// factory logs in as Peter Lustig
|
||||
link = await contributionLinkFactory(testEnv, {
|
||||
name: 'Dokumenta 2022',
|
||||
memo: 'Vielen Dank für deinen Besuch bei der Dokumenta 2022',
|
||||
amount: 200,
|
||||
validFrom: new Date(2022, 5, 18),
|
||||
validTo: new Date(2022, 8, 25),
|
||||
validFrom: actualDate,
|
||||
validTo: futureDate,
|
||||
})
|
||||
|
||||
resetToken()
|
||||
await mutate({
|
||||
result = await mutate({
|
||||
mutation: createUser,
|
||||
variables: { ...variables, email: 'ein@besucher.de', redeemCode: 'CL-' + link.code },
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDB()
|
||||
})
|
||||
|
||||
it('sets the contribution link id', async () => {
|
||||
await expect(
|
||||
UserContact.findOne({ email: 'ein@besucher.de' }, { relations: ['user'] }),
|
||||
@ -284,6 +316,104 @@ describe('UserResolver', () => {
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('stores the account activated event in the database', () => {
|
||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: EventProtocolType.ACTIVATE_ACCOUNT,
|
||||
userId: user[0].id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('stores the redeem register event in the database', () => {
|
||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: EventProtocolType.REDEEM_REGISTER,
|
||||
userId: result.data.createUser.id,
|
||||
contributionId: link.id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('transaction link', () => {
|
||||
let contribution: any
|
||||
let bob: any
|
||||
let transactionLink: TransactionLink
|
||||
let newUser: any
|
||||
|
||||
const bobData = {
|
||||
email: 'bob@baumeister.de',
|
||||
password: 'Aa12345_',
|
||||
publisherId: 1234,
|
||||
}
|
||||
|
||||
const peterData = {
|
||||
email: 'peter@lustig.de',
|
||||
password: 'Aa12345_',
|
||||
publisherId: 1234,
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await userFactory(testEnv, peterLustig)
|
||||
await userFactory(testEnv, bobBaumeister)
|
||||
await query({ query: login, variables: bobData })
|
||||
|
||||
// create contribution as user bob
|
||||
contribution = await mutate({
|
||||
mutation: createContribution,
|
||||
variables: { amount: 1000, memo: 'testing', creationDate: new Date().toISOString() },
|
||||
})
|
||||
|
||||
// login as admin
|
||||
await query({ query: login, variables: peterData })
|
||||
|
||||
// confirm the contribution
|
||||
contribution = await mutate({
|
||||
mutation: confirmContribution,
|
||||
variables: { id: contribution.data.createContribution.id },
|
||||
})
|
||||
|
||||
// login as user bob
|
||||
bob = await query({ query: login, variables: bobData })
|
||||
|
||||
// create transaction link
|
||||
await transactionLinkFactory(testEnv, {
|
||||
email: 'bob@baumeister.de',
|
||||
amount: 19.99,
|
||||
memo: `testing transaction link`,
|
||||
})
|
||||
|
||||
transactionLink = await TransactionLink.findOneOrFail()
|
||||
|
||||
resetToken()
|
||||
|
||||
// create new user using transaction link of bob
|
||||
newUser = await mutate({
|
||||
mutation: createUser,
|
||||
variables: {
|
||||
...variables,
|
||||
email: 'which@ever.de',
|
||||
redeemCode: transactionLink.code,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('sets the referrer id to bob baumeister id', async () => {
|
||||
await expect(User.findOne({ email: 'which@ever.de' })).resolves.toEqual(
|
||||
expect.objectContaining({ referrerId: bob.data.login.id }),
|
||||
)
|
||||
})
|
||||
|
||||
it('stores the redeem register event in the database', async () => {
|
||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: EventProtocolType.REDEEM_REGISTER,
|
||||
userId: newUser.data.createUser.id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
/* A transaction link requires GDD on account
|
||||
@ -295,7 +425,7 @@ describe('UserResolver', () => {
|
||||
email: 'peter@lustig.de',
|
||||
amount: 19.99,
|
||||
memo: `Kein Trick, keine Zauberrei,
|
||||
bei Gradidio sei dabei!`,
|
||||
bei Gradidio sei dabei!`,
|
||||
})
|
||||
const transactionLink = await TransactionLink.findOneOrFail()
|
||||
resetToken()
|
||||
@ -304,14 +434,14 @@ bei Gradidio sei dabei!`,
|
||||
variables: { ...variables, email: 'neuer@user.de', redeemCode: transactionLink.code },
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('sets the referrer id to Peter Lustigs id', async () => {
|
||||
await expect(User.findOne({ email: 'neuer@user.de' })).resolves.toEqual(expect.objectContaining({
|
||||
referrerId: user[0].id,
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
*/
|
||||
})
|
||||
})
|
||||
@ -399,6 +529,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith('Password entered is lexically invalid')
|
||||
})
|
||||
})
|
||||
|
||||
describe('no valid optin code', () => {
|
||||
@ -421,6 +555,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith('Could not login with emailVerificationCode')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -449,6 +587,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith('User with email=bibi@bloxberg.de does not exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('user is in database and correct login data', () => {
|
||||
@ -491,6 +633,7 @@ bei Gradidio sei dabei!`,
|
||||
describe('user is in database and wrong password', () => {
|
||||
beforeAll(async () => {
|
||||
await userFactory(testEnv, bibiBloxberg)
|
||||
result = await query({ query: login, variables: { ...variables, password: 'wrong' } })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@ -498,14 +641,16 @@ bei Gradidio sei dabei!`,
|
||||
})
|
||||
|
||||
it('returns an error', () => {
|
||||
expect(
|
||||
query({ query: login, variables: { ...variables, password: 'wrong' } }),
|
||||
).resolves.toEqual(
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('No user with this credentials')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith('The User has no valid credentials.')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -578,6 +723,8 @@ bei Gradidio sei dabei!`,
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let user: User[]
|
||||
|
||||
const variables = {
|
||||
email: 'bibi@bloxberg.de',
|
||||
password: 'Aa12345_',
|
||||
@ -585,6 +732,7 @@ bei Gradidio sei dabei!`,
|
||||
|
||||
beforeAll(async () => {
|
||||
await query({ query: login, variables })
|
||||
user = await User.find()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
@ -611,6 +759,15 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('stores the login event in the database', () => {
|
||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: EventProtocolType.LOGIN,
|
||||
userId: user[0].id,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -695,6 +852,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith(`email already sent less than 10 minutes minutes ago`)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -805,7 +966,7 @@ bei Gradidio sei dabei!`,
|
||||
})
|
||||
|
||||
describe('language is not valid', () => {
|
||||
it('thows an error', async () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updateUserInfos,
|
||||
@ -819,6 +980,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith(`"not-valid" isn't a valid language`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('password', () => {
|
||||
@ -838,6 +1003,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith(`Old password is invalid`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('invalid new password', () => {
|
||||
@ -860,6 +1029,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error found', () => {
|
||||
expect(logger.error).toBeCalledWith('newPassword does not fullfil the rules')
|
||||
})
|
||||
})
|
||||
|
||||
describe('correct old and new password', () => {
|
||||
@ -879,7 +1052,7 @@ bei Gradidio sei dabei!`,
|
||||
)
|
||||
})
|
||||
|
||||
it('can login wtih new password', async () => {
|
||||
it('can login with new password', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: login,
|
||||
@ -899,7 +1072,7 @@ bei Gradidio sei dabei!`,
|
||||
)
|
||||
})
|
||||
|
||||
it('cannot login wtih old password', async () => {
|
||||
it('cannot login with old password', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: login,
|
||||
@ -914,6 +1087,10 @@ bei Gradidio sei dabei!`,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('logs the error thrown', () => {
|
||||
expect(logger.error).toBeCalledWith('The User has no valid credentials.')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -30,6 +30,7 @@ import {
|
||||
EventRegister,
|
||||
EventSendAccountMultiRegistrationEmail,
|
||||
EventSendConfirmationEmail,
|
||||
EventActivateAccount,
|
||||
} from '@/event/Event'
|
||||
import { getUserCreation } from './util/creations'
|
||||
import { UserContactType } from '../enum/UserContactType'
|
||||
@ -558,10 +559,10 @@ export class UserResolver {
|
||||
|
||||
if (redeemCode) {
|
||||
eventRedeemRegister.userId = dbUser.id
|
||||
eventProtocol.writeEvent(event.setEventRedeemRegister(eventRedeemRegister))
|
||||
await eventProtocol.writeEvent(event.setEventRedeemRegister(eventRedeemRegister))
|
||||
} else {
|
||||
eventRegister.userId = dbUser.id
|
||||
eventProtocol.writeEvent(event.setEventRegister(eventRegister))
|
||||
await eventProtocol.writeEvent(event.setEventRegister(eventRegister))
|
||||
}
|
||||
|
||||
return new User(dbUser)
|
||||
@ -620,6 +621,7 @@ export class UserResolver {
|
||||
logger.info(`setPassword(${code}, ***)...`)
|
||||
// Validate Password
|
||||
if (!isPassword(password)) {
|
||||
logger.error('Password entered is lexically invalid')
|
||||
throw new Error(
|
||||
'Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character!',
|
||||
)
|
||||
@ -688,6 +690,8 @@ export class UserResolver {
|
||||
await queryRunner.connect()
|
||||
await queryRunner.startTransaction('REPEATABLE READ')
|
||||
|
||||
const event = new Event()
|
||||
|
||||
try {
|
||||
// Save user
|
||||
await queryRunner.manager.save(user).catch((error) => {
|
||||
@ -702,6 +706,10 @@ export class UserResolver {
|
||||
|
||||
await queryRunner.commitTransaction()
|
||||
logger.info('User and UserContact data written successfully...')
|
||||
|
||||
const eventActivateAccount = new EventActivateAccount()
|
||||
eventActivateAccount.userId = user.id
|
||||
eventProtocol.writeEvent(event.setEventActivateAccount(eventActivateAccount))
|
||||
} catch (e) {
|
||||
await queryRunner.rollbackTransaction()
|
||||
logger.error('Error on writing User and UserContact data:' + e)
|
||||
@ -816,6 +824,7 @@ export class UserResolver {
|
||||
|
||||
try {
|
||||
await queryRunner.manager.save(userEntity).catch((error) => {
|
||||
logger.error('error saving user: ' + error)
|
||||
throw new Error('error saving user: ' + error)
|
||||
})
|
||||
|
||||
|
||||
44
backend/src/mailer/sendTransactionLinkRedeemed.test.ts
Normal file
44
backend/src/mailer/sendTransactionLinkRedeemed.test.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { sendEMail } from './sendEMail'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { sendTransactionLinkRedeemedEmail } from './sendTransactionLinkRedeemed'
|
||||
|
||||
jest.mock('./sendEMail', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
sendEMail: jest.fn(),
|
||||
}
|
||||
})
|
||||
|
||||
describe('sendTransactionLinkRedeemedEmail', () => {
|
||||
beforeEach(async () => {
|
||||
await sendTransactionLinkRedeemedEmail({
|
||||
email: 'bibi@bloxberg.de',
|
||||
senderFirstName: 'Peter',
|
||||
senderLastName: 'Lustig',
|
||||
recipientFirstName: 'Bibi',
|
||||
recipientLastName: 'Bloxberg',
|
||||
senderEmail: 'peter@lustig.de',
|
||||
amount: new Decimal(42.0),
|
||||
memo: 'Vielen Dank dass Du dabei bist',
|
||||
overviewURL: 'http://localhost/overview',
|
||||
})
|
||||
})
|
||||
|
||||
it('calls sendEMail', () => {
|
||||
expect(sendEMail).toBeCalledWith({
|
||||
to: `Bibi Bloxberg <bibi@bloxberg.de>`,
|
||||
subject: 'Gradido-Link wurde eingelöst',
|
||||
text:
|
||||
expect.stringContaining('Hallo Bibi Bloxberg') &&
|
||||
expect.stringContaining(
|
||||
'Peter Lustig (peter@lustig.de) hat soeben deinen Link eingelöst.',
|
||||
) &&
|
||||
expect.stringContaining('Betrag: 42,00 GDD,') &&
|
||||
expect.stringContaining('Memo: Vielen Dank dass Du dabei bist') &&
|
||||
expect.stringContaining(
|
||||
'Details zur Transaktion findest du in deinem Gradido-Konto: http://localhost/overview',
|
||||
) &&
|
||||
expect.stringContaining('Bitte antworte nicht auf diese E-Mail!'),
|
||||
})
|
||||
})
|
||||
})
|
||||
28
backend/src/mailer/sendTransactionLinkRedeemed.ts
Normal file
28
backend/src/mailer/sendTransactionLinkRedeemed.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { sendEMail } from './sendEMail'
|
||||
import { transactionLinkRedeemed } from './text/transactionLinkRedeemed'
|
||||
|
||||
export const sendTransactionLinkRedeemedEmail = (data: {
|
||||
email: string
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): Promise<boolean> => {
|
||||
logger.info(
|
||||
`sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName},
|
||||
<${data.email}>,
|
||||
subject=${transactionLinkRedeemed.de.subject},
|
||||
text=${transactionLinkRedeemed.de.text(data)}`,
|
||||
)
|
||||
return sendEMail({
|
||||
to: `${data.recipientFirstName} ${data.recipientLastName} <${data.email}>`,
|
||||
subject: transactionLinkRedeemed.de.subject,
|
||||
text: transactionLinkRedeemed.de.text(data),
|
||||
})
|
||||
}
|
||||
@ -19,7 +19,6 @@ describe('sendTransactionReceivedEmail', () => {
|
||||
email: 'peter@lustig.de',
|
||||
senderEmail: 'bibi@bloxberg.de',
|
||||
amount: new Decimal(42.0),
|
||||
memo: 'Vielen herzlichen Dank für den neuen Hexenbesen!',
|
||||
overviewURL: 'http://localhost/overview',
|
||||
})
|
||||
})
|
||||
@ -33,7 +32,6 @@ describe('sendTransactionReceivedEmail', () => {
|
||||
expect.stringContaining('42,00 GDD') &&
|
||||
expect.stringContaining('Bibi Bloxberg') &&
|
||||
expect.stringContaining('(bibi@bloxberg.de)') &&
|
||||
expect.stringContaining('Vielen herzlichen Dank für den neuen Hexenbesen!') &&
|
||||
expect.stringContaining('http://localhost/overview'),
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { sendEMail } from './sendEMail'
|
||||
import { transactionLinkRedeemed, transactionReceived } from './text/transactionReceived'
|
||||
import { transactionReceived } from './text/transactionReceived'
|
||||
|
||||
export const sendTransactionReceivedEmail = (data: {
|
||||
senderFirstName: string
|
||||
@ -11,7 +11,6 @@ export const sendTransactionReceivedEmail = (data: {
|
||||
email: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): Promise<boolean> => {
|
||||
logger.info(
|
||||
@ -26,27 +25,3 @@ export const sendTransactionReceivedEmail = (data: {
|
||||
text: transactionReceived.de.text(data),
|
||||
})
|
||||
}
|
||||
|
||||
export const sendTransactionLinkRedeemedEmail = (data: {
|
||||
email: string
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): Promise<boolean> => {
|
||||
logger.info(
|
||||
`sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName},
|
||||
<${data.email}>,
|
||||
subject=${transactionLinkRedeemed.de.subject},
|
||||
text=${transactionLinkRedeemed.de.text(data)}`,
|
||||
)
|
||||
return sendEMail({
|
||||
to: `${data.recipientFirstName} ${data.recipientLastName} <${data.email}>`,
|
||||
subject: transactionLinkRedeemed.de.subject,
|
||||
text: transactionLinkRedeemed.de.text(data),
|
||||
})
|
||||
}
|
||||
|
||||
@ -14,9 +14,10 @@ export const contributionConfirmed = {
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName},
|
||||
|
||||
Dein Gradido Schöpfungsantrag "${data.contributionMemo}" wurde soeben von ${data.senderFirstName} ${
|
||||
data.senderLastName
|
||||
} bestätigt.
|
||||
Dein eingereichter Gemeinwohl-Beitrag "${data.contributionMemo}" wurde soeben von ${
|
||||
data.senderFirstName
|
||||
} ${data.senderLastName} bestätigt.
|
||||
|
||||
Betrag: ${data.contributionAmount.toFixed(2).replace('.', ',')} GDD
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
@ -14,17 +14,15 @@ export const contributionMessageReceived = {
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName},
|
||||
|
||||
Du hast soeben zu deinem eingereichten Gradido Schöpfungsantrag "${data.contributionMemo}" eine Rückfrage von ${data.senderFirstName} ${data.senderLastName} erhalten.
|
||||
Die Rückfrage lautet:
|
||||
du hast soeben zu deinem eingereichten Gemeinwohl-Beitrag "${data.contributionMemo}" eine Rückfrage von ${data.senderFirstName} ${data.senderLastName} erhalten.
|
||||
|
||||
${data.message}
|
||||
Bitte beantworte die Rückfrage in deinem Gradido-Konto im Menü "Gemeinschaft" im Tab "Meine Beiträge zum Gemeinwohl"!
|
||||
|
||||
Link zu deinem Konto: ${data.overviewURL}
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
dein Gradido-Team
|
||||
|
||||
|
||||
Link zu deinem Konto: ${data.overviewURL}`,
|
||||
dein Gradido-Team`,
|
||||
},
|
||||
}
|
||||
|
||||
33
backend/src/mailer/text/transactionLinkRedeemed.ts
Normal file
33
backend/src/mailer/text/transactionLinkRedeemed.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
export const transactionLinkRedeemed = {
|
||||
de: {
|
||||
subject: 'Gradido-Link wurde eingelöst',
|
||||
text: (data: {
|
||||
email: string
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName}
|
||||
|
||||
${data.senderFirstName} ${data.senderLastName} (${
|
||||
data.senderEmail
|
||||
}) hat soeben deinen Link eingelöst.
|
||||
|
||||
Betrag: ${data.amount.toFixed(2).replace('.', ',')} GDD,
|
||||
Memo: ${data.memo}
|
||||
|
||||
Details zur Transaktion findest du in deinem Gradido-Konto: ${data.overviewURL}
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
dein Gradido-Team`,
|
||||
},
|
||||
}
|
||||
@ -11,7 +11,6 @@ export const transactionReceived = {
|
||||
email: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName}
|
||||
@ -19,47 +18,12 @@ export const transactionReceived = {
|
||||
Du hast soeben ${data.amount.toFixed(2).replace('.', ',')} GDD von ${data.senderFirstName} ${
|
||||
data.senderLastName
|
||||
} (${data.senderEmail}) erhalten.
|
||||
${data.senderFirstName} ${data.senderLastName} schreibt:
|
||||
|
||||
${data.memo}
|
||||
Details zur Transaktion findest du in deinem Gradido-Konto: ${data.overviewURL}
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
dein Gradido-Team
|
||||
|
||||
|
||||
Link zu deinem Konto: ${data.overviewURL}`,
|
||||
},
|
||||
}
|
||||
|
||||
export const transactionLinkRedeemed = {
|
||||
de: {
|
||||
subject: 'Gradido link eingelösst',
|
||||
text: (data: {
|
||||
email: string
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
senderEmail: string
|
||||
amount: Decimal
|
||||
memo: string
|
||||
overviewURL: string
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName}
|
||||
|
||||
${data.senderFirstName} ${data.senderLastName} (${
|
||||
data.senderEmail
|
||||
}) hat soeben deinen Link eingelösst.
|
||||
Betrag: ${data.amount.toFixed(2).replace('.', ',')} GDD,
|
||||
Memo: ${data.memo}
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
dein Gradido-Team
|
||||
|
||||
Link zu deinem Konto: ${data.overviewURL}`,
|
||||
dein Gradido-Team`,
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,30 +6,41 @@ With the business event protocol the gradido application will capture and persis
|
||||
|
||||
The different event types will be defined as Enum. The following list is a first draft and will grow with further event types in the future.
|
||||
|
||||
| EventType | Value | Description |
|
||||
| ----------------------------------- | ----- | ------------------------------------------------------------------------------------------------------ |
|
||||
| BasicEvent | 0 | the basic event is the root of all further extending event types |
|
||||
| VisitGradidoEvent | 10 | if a user visits a gradido page without login or register |
|
||||
| RegisterEvent | 20 | the user presses the register button |
|
||||
| RedeemRegisterEvent | 21 | the user presses the register button initiated by the redeem link |
|
||||
| InActiveAccountEvent | 22 | the systems create an inactive account during the register process |
|
||||
| SendConfirmEmailEvent | 23 | the system send a confirmation email to the user during the register process |
|
||||
| ConfirmEmailEvent | 24 | the user confirms his email during the register process |
|
||||
| RegisterEmailKlickTippEvent | 25 | the system registers the confirmed email at klicktipp |
|
||||
| LoginEvent | 30 | the user presses the login button |
|
||||
| RedeemLoginEvent | 31 | the user presses the login button initiated by the redeem link |
|
||||
| ActivateAccountEvent | 32 | the system activates the users account during the first login process |
|
||||
| PasswordChangeEvent | 33 | the user changes his password |
|
||||
| TransactionSendEvent | 40 | the user creates a transaction and sends it online |
|
||||
| TransactionSendRedeemEvent | 41 | the user creates a transaction and sends it per redeem link |
|
||||
| TransactionRepeateRedeemEvent | 42 | the user recreates a redeem link of a still open transaction |
|
||||
| TransactionCreationEvent | 50 | the user receives a creation transaction for his confirmed contribution |
|
||||
| TransactionReceiveEvent | 51 | the user receives a transaction from an other user and posts the amount on his account |
|
||||
| TransactionReceiveRedeemEvent | 52 | the user activates the redeem link and receives the transaction and posts the amount on his account |
|
||||
| ContributionCreateEvent | 60 | the user enters his contribution and asks for confirmation |
|
||||
| ContributionConfirmEvent | 61 | the user confirms a contribution of an other user (for future multi confirmation from several users) |
|
||||
| ContributionLinkDefineEvent | 70 | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium |
|
||||
| ContributionLinkActivateRedeemEvent | 71 | the user activates a received contributionLink to create a contribution entry for the contributionLink |
|
||||
| EventType | Description |
|
||||
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| BasicEvent | the basic event is the root of all further extending event types |
|
||||
| VisitGradidoEvent | if a user visits a gradido page without login or register; possible as soon as a request-response-loop for the first page will be invoked |
|
||||
| RegisterEvent | the user presses the register button |
|
||||
| LoginEvent | the user presses the login button |
|
||||
| VerifyRedeemEvent | the user presses a redeem link independent from transaction or contribution redeem |
|
||||
| RedeemRegisterEvent | the user presses the register-button initiated by the redeem link |
|
||||
| RedeemLoginEvent | the user presses the login-button initiated by the redeem link |
|
||||
| ActivateAccountEvent | the system activates the users account after a successful confirmEmail-Event or during a reactivation of a deactivated account |
|
||||
| InActiveAccountEvent | the systems creates an inactive account during the register process or an active account will be reset to inactive |
|
||||
| SetPasswordEvent | the system sets a new password after ConfirmEmailEvent or SendForgotPasswordEvent |
|
||||
| RegisterEmailKlickTippEvent | the system registers the confirmed email at klicktipp |
|
||||
| PasswordChangeEvent | the user changes his password in his Profile |
|
||||
| TransactionSendEvent | the user creates a transaction and sends it online; paired with TransactionReceiveEvent |
|
||||
| TransactionLinkCreateEvent | the user creates a transaction link |
|
||||
| TransactionReceiveEvent | the user receives a transaction from an other user and posts the amount on his account; paired with TransactionSendEvent |
|
||||
| TransactionLinkRedeemEvent | the user activates the redeem link and receives the transaction and posts the amount on his account |
|
||||
| ContributionCreateEvent | the user enters his contribution and asks for confirmation |
|
||||
| ContributionConfirmEvent | the admin user confirms a contribution of an other user (for future multi confirmation from several users) |
|
||||
| ContributionDenyEvent | the admin user denies a contribution of an other user |
|
||||
| ContributionLinkDefineEvent | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium |
|
||||
| ContributionLinkRedeemEvent | the user activates a received contributionLink to create a contribution entry for the contributionLink |
|
||||
| UserCreateContributionMessageEvent | the user captures a new message for a contribution |
|
||||
| AdminCreateContributionMessageEvent | the admin user captures a new message for a contribution |
|
||||
| LogoutEvent | the user invokes a logout |
|
||||
| SendConfirmEmailEvent | the system sends a confirmation email to the user during the registration process |
|
||||
| SendAccountMultiRegistrationEmailEvent | the system sends a info email to the user, that an other user tries to register with his existing email address |
|
||||
| SendForgotPasswordEmailEvent | the system sends the forgot password email including a special link to start the forgot password process |
|
||||
| SendTransactionSendEmailEvent | the system sends an email to inform the user about his transaction was sent to an other user |
|
||||
| SendTransactionReceiveEmailEvent | the system sends an email to inform the user about a received transaction from an other user |
|
||||
| SendAddedContributionEmailEvent | the system sends an email to inform the user about the creation of his captured contribution |
|
||||
| SendContributionConfirmEmailEvent | the system sends an email to inform the user about the confirmation of his contribution |
|
||||
| SendTransactionLinkRedeemEmailEvent | the system sends an email to the user, who created the transactionlink, that the link was redeemed |
|
||||
| | |
|
||||
|
||||
## EventProtocol - Entity
|
||||
|
||||
@ -49,32 +60,44 @@ The business events will be stored in database in the new table `EventProtocol`.
|
||||
|
||||
## Event Types
|
||||
|
||||
The following table lists for each event type the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table:
|
||||
The following table lists for each event type the mapping between old and new key, the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table:
|
||||
|
||||
| EventType | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount |
|
||||
| :---------------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: |
|
||||
| BasicEvent | x | x | x | | | | | | |
|
||||
| VisitGradidoEvent | x | x | x | | | | | | |
|
||||
| RegisterEvent | x | x | x | x | | | | | |
|
||||
| RedeemRegisterEvent | x | x | x | x | | | (x) | (x) | |
|
||||
| InActiveAccountEvent | x | x | x | x | | | | | |
|
||||
| SendConfirmEmailEvent | x | x | x | x | | | | | |
|
||||
| ConfirmEmailEvent | x | x | x | x | | | | | |
|
||||
| RegisterEmailKlickTippEvent | x | x | x | x | | | | | |
|
||||
| LoginEvent | x | x | x | x | | | | | |
|
||||
| RedeemLoginEvent | x | x | x | x | | | (x) | (x) | |
|
||||
| ActivateAccountEvent | x | x | x | x | | | | | |
|
||||
| PasswordChangeEvent | x | x | x | x | | | | | |
|
||||
| TransactionSendEvent | x | x | x | x | x | x | x | | x |
|
||||
| TransactionSendRedeemEvent | x | x | x | x | x | x | x | | x |
|
||||
| TransactionRepeateRedeemEvent | x | x | x | x | x | x | x | | x |
|
||||
| TransactionCreationEvent | x | x | x | x | | | x | | x |
|
||||
| TransactionReceiveEvent | x | x | x | x | x | x | x | | x |
|
||||
| TransactionReceiveRedeemEvent | x | x | x | x | x | x | x | | x |
|
||||
| ContributionCreateEvent | x | x | x | x | | | | x | x |
|
||||
| ContributionConfirmEvent | x | x | x | x | x | x | | x | x |
|
||||
| ContributionLinkDefineEvent | x | x | x | x | | | | | x |
|
||||
| ContributionLinkActivateRedeemEvent | x | x | x | x | | | | x | x |
|
||||
| EventType - old key | EventType - new key | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount |
|
||||
| :-------------------------------- | :------------------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: |
|
||||
| BASIC | BasicEvent | x | x | x | | | | | | |
|
||||
| VISIT_GRADIDO | VisitGradidoEvent | x | x | x | | | | | | |
|
||||
| REGISTER | RegisterEvent | x | x | x | x | | | | | |
|
||||
| LOGIN | LoginEvent | x | x | x | x | | | | | |
|
||||
| | VerifyRedeemEvent | | | | | | | | | |
|
||||
| REDEEM_REGISTER | RedeemRegisterEvent | x | x | x | x | | | (x) | (x) | |
|
||||
| REDEEM_LOGIN | RedeemLoginEvent | x | x | x | x | | | (x) | (x) | |
|
||||
| ACTIVATE_ACCOUNT | ActivateAccountEvent | x | x | x | x | | | | | |
|
||||
| INACTIVE_ACCOUNT | InActiveAccountEvent | x | x | x | x | | | | | |
|
||||
| CONFIRM_EMAIL | SetPasswordEvent | x | x | x | x | | | | | |
|
||||
| REGISTER_EMAIL_KLICKTIPP | RegisterEmailKlickTippEvent | x | x | x | x | | | | | |
|
||||
| PASSWORD_CHANGE | PasswordChangeEvent | x | x | x | x | | | | | |
|
||||
| TRANSACTION_SEND | TransactionSendEvent | x | x | x | x | x | x | x | | x |
|
||||
| TRANSACTION_CREATION | TransactionLinkCreateEvent | x | x | x | x | | | x | | x |
|
||||
| TRANSACTION_RECEIVE | TransactionReceiveEvent | x | x | x | x | x | x | x | | x |
|
||||
| TRANSACTION_SEND_REDEEM | TransactionLinkRedeemEvent | x | x | x | x | x | x | x | | x |
|
||||
| CONTRIBUTION_CREATE | ContributionCreateEvent | x | x | x | x | | | | x | x |
|
||||
| CONTRIBUTION_CONFIRM | ContributionConfirmEvent | x | x | x | x | x | x | | x | x |
|
||||
| | ContributionDenyEvent | x | x | x | x | x | x | | x | x |
|
||||
| CONTRIBUTION_LINK_DEFINE | ContributionLinkDefineEvent | x | x | x | x | | | | | x |
|
||||
| CONTRIBUTION_LINK_ACTIVATE_REDEEM | ContributionLinkRedeemEvent | x | x | x | x | | | | x | x |
|
||||
| | UserCreateContributionMessageEvent | x | x | x | x | | | | x | x |
|
||||
| | AdminCreateContributionMessageEvent | x | x | x | x | | | | x | x |
|
||||
| | LogoutEvent | x | x | x | x | | | | x | x |
|
||||
| SEND_CONFIRMATION_EMAIL | SendConfirmEmailEvent | x | x | x | x | | | | | |
|
||||
| | SendAccountMultiRegistrationEmailEvent | x | x | x | x | | | | | |
|
||||
| | SendForgotPasswordEmailEvent | x | x | x | x | | | | | |
|
||||
| | SendTransactionSendEmailEvent | x | x | x | x | x | x | x | | x |
|
||||
| | SendTransactionReceiveEmailEvent | x | x | x | x | x | x | x | | x |
|
||||
| | SendAddedContributionEmailEvent | x | x | x | x | | | | x | x |
|
||||
| | SendContributionConfirmEmailEvent | x | x | x | x | | | | x | x |
|
||||
| | SendTransactionLinkRedeemEmailEvent | x | x | x | x | x | x | x | | x |
|
||||
| TRANSACTION_REPEATE_REDEEM | - | | | | | | | | | |
|
||||
| TRANSACTION_RECEIVE_REDEEM | - | | | | | | | | | |
|
||||
|
||||
## Event creation
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<redeem-information v-bind="linkData" :isContributionLink="isContributionLink" />
|
||||
<b-jumbotron>
|
||||
<div class="mb-3 text-center">
|
||||
<b-button variant="primary" @click="$emit('redeem-link', linkData.amount)" size="lg">
|
||||
<b-button variant="primary" @click="$emit('mutation-link', linkData.amount)" size="lg">
|
||||
{{ $t('gdd_per_link.redeem') }}
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
@ -178,7 +178,6 @@
|
||||
"no-redeem": "Du darfst deinen eigenen Link nicht einlösen!",
|
||||
"not-copied": "Dein Gerät lässt das Kopieren leider nicht zu! Bitte kopiere den Link von Hand!",
|
||||
"redeem": "Einlösen",
|
||||
"redeem-text": "Willst du den Betrag jetzt einlösen?",
|
||||
"redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.",
|
||||
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
|
||||
"redeemed-title": "eingelöst",
|
||||
|
||||
@ -178,7 +178,6 @@
|
||||
"no-redeem": "You not allowed to redeem your own link!",
|
||||
"not-copied": "Unfortunately, your device does not allow copying! Please copy the link by hand!",
|
||||
"redeem": "Redeem",
|
||||
"redeem-text": "Do you want to redeem the amount now?",
|
||||
"redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.",
|
||||
"redeemed-at": "The link was already redeemed on {date}.",
|
||||
"redeemed-title": "redeemed",
|
||||
|
||||
@ -180,7 +180,6 @@
|
||||
"no-redeem": "No puedes canjear tu propio enlace!",
|
||||
"not-copied": "¡Desafortunadamente, su dispositivo no permite copiar! Copie el enlace manualmente!",
|
||||
"redeem": "Canjear",
|
||||
"redeem-text": "¿Quieres canjear el importe ahora?",
|
||||
"redeemed": "¡Canjeado con éxito! Tu cuenta ha sido acreditada con {n} GDD.",
|
||||
"redeemed-at": "El enlace ya se canjeó el {date}.",
|
||||
"redeemed-title": "canjeado",
|
||||
|
||||
@ -180,7 +180,6 @@
|
||||
"no-redeem": "Vous n´êtes pas autorisé à percevoir votre propre lien!",
|
||||
"not-copied": "Malheureusement votre appareil ne permet pas de copier! Veuillez copier le lien manuellement svp!",
|
||||
"redeem": "Encaisser",
|
||||
"redeem-text": "Voulez-vous percevoir le montant maintenant?",
|
||||
"redeemed": "Encaissé avec succès! Votre compte est crédité de {n} GDD.",
|
||||
"redeemed-at": "Le lien a déjà été perçu le {date}.",
|
||||
"redeemed-title": "encaisser",
|
||||
|
||||
@ -180,7 +180,6 @@
|
||||
"no-redeem": "Je mag je eigen link niet inwisselen!",
|
||||
"not-copied": "Jouw apparaat laat het kopiëren helaas niet toe! Kopieer de link alsjeblieft met de hand!",
|
||||
"redeem": "Inwisselen",
|
||||
"redeem-text": "Wil je het bedrag nu inwisselen?",
|
||||
"redeemed": "Succesvol ingewisseld! Op jouw rekening werden {n} GDD bijgeschreven.",
|
||||
"redeemed-at": "De link werd al op {date} ingewisseld.",
|
||||
"redeemed-title": "ingewisseld",
|
||||
|
||||
@ -282,19 +282,11 @@ describe('TransactionLink', () => {
|
||||
})
|
||||
|
||||
describe('redeem link with success', () => {
|
||||
let spy
|
||||
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockResolvedValue()
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
|
||||
})
|
||||
|
||||
it('opens the modal', () => {
|
||||
expect(spy).toBeCalledWith('gdd_per_link.redeem-text')
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
@ -316,37 +308,9 @@ describe('TransactionLink', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('cancel redeem link', () => {
|
||||
let spy
|
||||
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockResolvedValue()
|
||||
spy.mockImplementation(() => Promise.resolve(false))
|
||||
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
|
||||
})
|
||||
|
||||
it('does not call the API', () => {
|
||||
expect(apolloMutateMock).not.toBeCalled()
|
||||
})
|
||||
|
||||
it('does not toasts a success message', () => {
|
||||
expect(mocks.$t).not.toBeCalledWith('gdd_per_link.redeemed', { n: '22' })
|
||||
expect(toastSuccessSpy).not.toBeCalled()
|
||||
})
|
||||
|
||||
it('does not push the route', () => {
|
||||
expect(routerPushMock).not.toBeCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('redeem link with error', () => {
|
||||
let spy
|
||||
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' })
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
|
||||
})
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<redeem-valid
|
||||
:linkData="linkData"
|
||||
:isContributionLink="isContributionLink"
|
||||
@redeem-link="redeemLink"
|
||||
@mutation-link="mutationLink"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -98,11 +98,6 @@ export default {
|
||||
this.$router.push('/overview')
|
||||
})
|
||||
},
|
||||
redeemLink(amount) {
|
||||
this.$bvModal.msgBoxConfirm(this.$t('gdd_per_link.redeem-text')).then((value) => {
|
||||
if (value) this.mutationLink(amount)
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isContributionLink() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user