mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 2547-normalized-amount-transaction-is-processed-again
This commit is contained in:
commit
aadd2149aa
@ -557,7 +557,6 @@ export class ContributionResolver {
|
||||
): Promise<boolean> {
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
|
||||
try {
|
||||
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
||||
const contribution = await DbContribution.findOne(id)
|
||||
@ -664,7 +663,6 @@ export class ContributionResolver {
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
import { transactionLinkCode } from './TransactionLinkResolver'
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||
import { cleanDB, testEnvironment, resetToken } from '@test/helpers'
|
||||
import { cleanDB, testEnvironment, resetToken, resetEntity } from '@test/helpers'
|
||||
import { creationFactory } from '@/seeds/factory/creation'
|
||||
import { creations } from '@/seeds/creation/index'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
@ -50,7 +50,137 @@ afterAll(async () => {
|
||||
})
|
||||
|
||||
describe('TransactionLinkResolver', () => {
|
||||
// TODO: have this test separated into a transactionLink and a contributionLink part (if possible)
|
||||
describe('redeemTransactionLink', () => {
|
||||
describe('contributionLink', () => {
|
||||
describe('input not valid', () => {
|
||||
beforeAll(async () => {
|
||||
await mutate({
|
||||
mutation: login,
|
||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||
})
|
||||
})
|
||||
|
||||
it('throws error when link does not exists', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: redeemTransactionLink,
|
||||
variables: {
|
||||
code: 'CL-123456',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
new GraphQLError(
|
||||
'Creation from contribution link was not successful. Error: No contribution link found to given code: CL-123456',
|
||||
),
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('throws error when link is not valid yet', async () => {
|
||||
const now = new Date()
|
||||
const {
|
||||
data: { createContributionLink: contributionLink },
|
||||
} = await mutate({
|
||||
mutation: createContributionLink,
|
||||
variables: {
|
||||
amount: new Decimal(5),
|
||||
name: 'Daily Contribution Link',
|
||||
memo: 'Thank you for contribute daily to the community',
|
||||
cycle: 'DAILY',
|
||||
validFrom: new Date(now.getFullYear() + 1, 0, 1).toISOString(),
|
||||
validTo: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
||||
maxAmountPerMonth: new Decimal(200),
|
||||
maxPerCycle: 1,
|
||||
},
|
||||
})
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: redeemTransactionLink,
|
||||
variables: {
|
||||
code: 'CL-' + contributionLink.code,
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
new GraphQLError(
|
||||
'Creation from contribution link was not successful. Error: Contribution link not valid yet',
|
||||
),
|
||||
],
|
||||
})
|
||||
await resetEntity(DbContributionLink)
|
||||
})
|
||||
|
||||
it('throws error when contributionLink cycle is invalid', async () => {
|
||||
const now = new Date()
|
||||
const {
|
||||
data: { createContributionLink: contributionLink },
|
||||
} = await mutate({
|
||||
mutation: createContributionLink,
|
||||
variables: {
|
||||
amount: new Decimal(5),
|
||||
name: 'Daily Contribution Link',
|
||||
memo: 'Thank you for contribute daily to the community',
|
||||
cycle: 'INVALID',
|
||||
validFrom: new Date(now.getFullYear(), 0, 1).toISOString(),
|
||||
validTo: new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999).toISOString(),
|
||||
maxAmountPerMonth: new Decimal(200),
|
||||
maxPerCycle: 1,
|
||||
},
|
||||
})
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: redeemTransactionLink,
|
||||
variables: {
|
||||
code: 'CL-' + contributionLink.code,
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
new GraphQLError(
|
||||
'Creation from contribution link was not successful. Error: Contribution link has unknown cycle',
|
||||
),
|
||||
],
|
||||
})
|
||||
await resetEntity(DbContributionLink)
|
||||
})
|
||||
|
||||
it('throws error when link is no longer valid', async () => {
|
||||
const now = new Date()
|
||||
const {
|
||||
data: { createContributionLink: contributionLink },
|
||||
} = await mutate({
|
||||
mutation: createContributionLink,
|
||||
variables: {
|
||||
amount: new Decimal(5),
|
||||
name: 'Daily Contribution Link',
|
||||
memo: 'Thank you for contribute daily to the community',
|
||||
cycle: 'DAILY',
|
||||
validFrom: new Date(now.getFullYear() - 1, 0, 1).toISOString(),
|
||||
validTo: new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
||||
maxAmountPerMonth: new Decimal(200),
|
||||
maxPerCycle: 1,
|
||||
},
|
||||
})
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: redeemTransactionLink,
|
||||
variables: {
|
||||
code: 'CL-' + contributionLink.code,
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
new GraphQLError(
|
||||
'Creation from contribution link was not successful. Error: Contribution link is no longer valid',
|
||||
),
|
||||
],
|
||||
})
|
||||
await resetEntity(DbContributionLink)
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: have this test separated into a transactionLink and a contributionLink part
|
||||
describe('redeem daily Contribution Link', () => {
|
||||
const now = new Date()
|
||||
let contributionLink: DbContributionLink | undefined
|
||||
@ -237,6 +367,7 @@ describe('TransactionLinkResolver', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('transaction links list', () => {
|
||||
const variables = {
|
||||
@ -305,7 +436,9 @@ describe('TransactionLinkResolver', () => {
|
||||
variables.userId = user.id
|
||||
variables.pageSize = 25
|
||||
// bibi needs GDDs
|
||||
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
|
||||
const bibisCreation = creations.find(
|
||||
(creation) => creation.email === 'bibi@bloxberg.de',
|
||||
)
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
await creationFactory(testEnv, bibisCreation!)
|
||||
// bibis transaktion links
|
||||
@ -505,9 +638,9 @@ describe('TransactionLinkResolver', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('transactionLinkCode', () => {
|
||||
describe('transactionLinkCode', () => {
|
||||
const date = new Date()
|
||||
|
||||
it('returns a string of length 24', () => {
|
||||
@ -518,4 +651,5 @@ describe('transactionLinkCode', () => {
|
||||
const regexp = new RegExp(date.getTime().toString(16) + '$')
|
||||
expect(transactionLinkCode(date)).toEqual(expect.stringMatching(regexp))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -170,6 +170,7 @@ export class TransactionLinkResolver {
|
||||
if (code.match(/^CL-/)) {
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
try {
|
||||
logger.info('redeem contribution link...')
|
||||
const now = new Date()
|
||||
const queryRunner = getConnection().createQueryRunner()
|
||||
@ -184,7 +185,7 @@ export class TransactionLinkResolver {
|
||||
.getOne()
|
||||
if (!contributionLink) {
|
||||
logger.error('no contribution link found to given code:', code)
|
||||
throw new Error('No contribution link found')
|
||||
throw new Error(`No contribution link found to given code: ${code}`)
|
||||
}
|
||||
logger.info('...contribution link found with id', contributionLink.id)
|
||||
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
||||
@ -196,8 +197,11 @@ export class TransactionLinkResolver {
|
||||
}
|
||||
if (contributionLink.validTo) {
|
||||
if (new Date(contributionLink.validTo).setHours(23, 59, 59) < now.getTime()) {
|
||||
logger.error('contribution link is depricated. Valid to: ', contributionLink.validTo)
|
||||
throw new Error('Contribution link is depricated')
|
||||
logger.error(
|
||||
'contribution link is no longer valid. Valid to: ',
|
||||
contributionLink.validTo,
|
||||
)
|
||||
throw new Error('Contribution link is no longer valid')
|
||||
}
|
||||
}
|
||||
let alreadyRedeemed: DbContribution | undefined
|
||||
@ -312,6 +316,8 @@ export class TransactionLinkResolver {
|
||||
throw new Error(`Creation from contribution link was not successful. ${e}`)
|
||||
} finally {
|
||||
await queryRunner.release()
|
||||
}
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
return true
|
||||
|
||||
@ -45,6 +45,9 @@ export const executeTransaction = async (
|
||||
recipient: dbUser,
|
||||
transactionLink?: dbTransactionLink | null,
|
||||
): Promise<boolean> => {
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
try {
|
||||
logger.info(
|
||||
`executeTransaction(amount=${amount}, memo=${memo}, sender=${sender}, recipient=${recipient})...`,
|
||||
)
|
||||
@ -64,10 +67,6 @@ export const executeTransaction = async (
|
||||
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
|
||||
}
|
||||
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
|
||||
try {
|
||||
// validate amount
|
||||
const receivedCallDate = new Date()
|
||||
const sendBalance = await calculateBalance(
|
||||
@ -187,10 +186,10 @@ export const executeTransaction = async (
|
||||
})
|
||||
}
|
||||
logger.info(`finished executeTransaction successfully`)
|
||||
return true
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@Resolver()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user