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> {
|
): Promise<boolean> {
|
||||||
// acquire lock
|
// acquire lock
|
||||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
||||||
const contribution = await DbContribution.findOne(id)
|
const contribution = await DbContribution.findOne(id)
|
||||||
@ -664,7 +663,6 @@ export class ContributionResolver {
|
|||||||
} finally {
|
} finally {
|
||||||
releaseLock()
|
releaseLock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
import { transactionLinkCode } from './TransactionLinkResolver'
|
import { transactionLinkCode } from './TransactionLinkResolver'
|
||||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
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 { creationFactory } from '@/seeds/factory/creation'
|
||||||
import { creations } from '@/seeds/creation/index'
|
import { creations } from '@/seeds/creation/index'
|
||||||
import { userFactory } from '@/seeds/factory/user'
|
import { userFactory } from '@/seeds/factory/user'
|
||||||
@ -50,7 +50,137 @@ afterAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('TransactionLinkResolver', () => {
|
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', () => {
|
describe('redeem daily Contribution Link', () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
let contributionLink: DbContributionLink | undefined
|
let contributionLink: DbContributionLink | undefined
|
||||||
@ -237,6 +367,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('transaction links list', () => {
|
describe('transaction links list', () => {
|
||||||
const variables = {
|
const variables = {
|
||||||
@ -305,7 +436,9 @@ describe('TransactionLinkResolver', () => {
|
|||||||
variables.userId = user.id
|
variables.userId = user.id
|
||||||
variables.pageSize = 25
|
variables.pageSize = 25
|
||||||
// bibi needs GDDs
|
// 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
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
await creationFactory(testEnv, bibisCreation!)
|
await creationFactory(testEnv, bibisCreation!)
|
||||||
// bibis transaktion links
|
// bibis transaktion links
|
||||||
@ -519,3 +652,4 @@ describe('transactionLinkCode', () => {
|
|||||||
expect(transactionLinkCode(date)).toEqual(expect.stringMatching(regexp))
|
expect(transactionLinkCode(date)).toEqual(expect.stringMatching(regexp))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|||||||
@ -170,6 +170,7 @@ export class TransactionLinkResolver {
|
|||||||
if (code.match(/^CL-/)) {
|
if (code.match(/^CL-/)) {
|
||||||
// acquire lock
|
// acquire lock
|
||||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||||
|
try {
|
||||||
logger.info('redeem contribution link...')
|
logger.info('redeem contribution link...')
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const queryRunner = getConnection().createQueryRunner()
|
const queryRunner = getConnection().createQueryRunner()
|
||||||
@ -184,7 +185,7 @@ export class TransactionLinkResolver {
|
|||||||
.getOne()
|
.getOne()
|
||||||
if (!contributionLink) {
|
if (!contributionLink) {
|
||||||
logger.error('no contribution link found to given code:', code)
|
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)
|
logger.info('...contribution link found with id', contributionLink.id)
|
||||||
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
||||||
@ -196,8 +197,11 @@ export class TransactionLinkResolver {
|
|||||||
}
|
}
|
||||||
if (contributionLink.validTo) {
|
if (contributionLink.validTo) {
|
||||||
if (new Date(contributionLink.validTo).setHours(23, 59, 59) < now.getTime()) {
|
if (new Date(contributionLink.validTo).setHours(23, 59, 59) < now.getTime()) {
|
||||||
logger.error('contribution link is depricated. Valid to: ', contributionLink.validTo)
|
logger.error(
|
||||||
throw new Error('Contribution link is depricated')
|
'contribution link is no longer valid. Valid to: ',
|
||||||
|
contributionLink.validTo,
|
||||||
|
)
|
||||||
|
throw new Error('Contribution link is no longer valid')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let alreadyRedeemed: DbContribution | undefined
|
let alreadyRedeemed: DbContribution | undefined
|
||||||
@ -312,6 +316,8 @@ export class TransactionLinkResolver {
|
|||||||
throw new Error(`Creation from contribution link was not successful. ${e}`)
|
throw new Error(`Creation from contribution link was not successful. ${e}`)
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release()
|
await queryRunner.release()
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
releaseLock()
|
releaseLock()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -45,6 +45,9 @@ export const executeTransaction = async (
|
|||||||
recipient: dbUser,
|
recipient: dbUser,
|
||||||
transactionLink?: dbTransactionLink | null,
|
transactionLink?: dbTransactionLink | null,
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
|
// acquire lock
|
||||||
|
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||||
|
try {
|
||||||
logger.info(
|
logger.info(
|
||||||
`executeTransaction(amount=${amount}, memo=${memo}, sender=${sender}, recipient=${recipient})...`,
|
`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)`)
|
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// acquire lock
|
|
||||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
|
||||||
|
|
||||||
try {
|
|
||||||
// validate amount
|
// validate amount
|
||||||
const receivedCallDate = new Date()
|
const receivedCallDate = new Date()
|
||||||
const sendBalance = await calculateBalance(
|
const sendBalance = await calculateBalance(
|
||||||
@ -187,10 +186,10 @@ export const executeTransaction = async (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
logger.info(`finished executeTransaction successfully`)
|
logger.info(`finished executeTransaction successfully`)
|
||||||
return true
|
|
||||||
} finally {
|
} finally {
|
||||||
releaseLock()
|
releaseLock()
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user