mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
separate error cases, have some basic testing for transaction links, reorder tests
This commit is contained in:
parent
f38f931418
commit
283e09ea3d
@ -16,6 +16,7 @@ import {
|
|||||||
redeemTransactionLink,
|
redeemTransactionLink,
|
||||||
createContribution,
|
createContribution,
|
||||||
updateContribution,
|
updateContribution,
|
||||||
|
createTransactionLink,
|
||||||
} from '@/seeds/graphql/mutations'
|
} from '@/seeds/graphql/mutations'
|
||||||
import { listTransactionLinksAdmin } from '@/seeds/graphql/queries'
|
import { listTransactionLinksAdmin } from '@/seeds/graphql/queries'
|
||||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||||
@ -51,6 +52,69 @@ afterAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('TransactionLinkResolver', () => {
|
describe('TransactionLinkResolver', () => {
|
||||||
|
describe('createTransactionLink', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when amount is zero', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: 0,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when amount is negative', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: -10,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(-10))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when user has not enough GDD', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: 1001,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('User has not enough GDD')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('User has not enough GDD', expect.any(Number))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('redeemTransactionLink', () => {
|
describe('redeemTransactionLink', () => {
|
||||||
describe('contributionLink', () => {
|
describe('contributionLink', () => {
|
||||||
describe('input not valid', () => {
|
describe('input not valid', () => {
|
||||||
@ -408,22 +472,52 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('transaction links list', () => {
|
describe('listTransactionLinksAdmin', () => {
|
||||||
const variables = {
|
const variables = {
|
||||||
userId: 1, // dummy, may be replaced
|
userId: 1, // dummy, may be replaced
|
||||||
filters: null,
|
filters: null,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there is a test not cleaning up after itself! Fix it!
|
// TODO: there is a test not cleaning up after itself! Fix it!
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDB()
|
await cleanDB()
|
||||||
resetToken()
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables,
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated', () => {
|
||||||
|
describe('without admin rights', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await userFactory(testEnv, bibiBloxberg)
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
describe('unauthenticated', () => {
|
|
||||||
it('returns an error', async () => {
|
it('returns an error', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
@ -438,22 +532,40 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('with admin rights', () => {
|
||||||
describe('without admin rights', () => {
|
beforeAll(async () => {
|
||||||
beforeAll(async () => {
|
// admin 'peter@lustig.de' has to exists for 'creationFactory'
|
||||||
user = await userFactory(testEnv, bibiBloxberg)
|
await userFactory(testEnv, peterLustig)
|
||||||
await mutate({
|
|
||||||
mutation: login,
|
|
||||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
user = await userFactory(testEnv, bibiBloxberg)
|
||||||
await cleanDB()
|
variables.userId = user.id
|
||||||
resetToken()
|
variables.pageSize = 25
|
||||||
})
|
// bibi needs GDDs
|
||||||
|
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
|
||||||
|
const bibisTransaktionLinks = transactionLinks.filter(
|
||||||
|
(transactionLink) => transactionLink.email === 'bibi@bloxberg.de',
|
||||||
|
)
|
||||||
|
for (let i = 0; i < bibisTransaktionLinks.length; i++) {
|
||||||
|
await transactionLinkFactory(testEnv, bibisTransaktionLinks[i])
|
||||||
|
}
|
||||||
|
|
||||||
it('returns an error', async () => {
|
// admin: only now log in
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('without any filters', () => {
|
||||||
|
it('finds 6 open transaction links and no deleted or redeemed', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: listTransactionLinksAdmin,
|
query: listTransactionLinksAdmin,
|
||||||
@ -461,219 +573,169 @@ describe('TransactionLinkResolver', () => {
|
|||||||
}),
|
}),
|
||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
errors: [new GraphQLError('401 Unauthorized')],
|
data: {
|
||||||
|
listTransactionLinksAdmin: {
|
||||||
|
linkCount: 6,
|
||||||
|
linkList: expect.not.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
deletedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with admin rights', () => {
|
describe('all filters are null', () => {
|
||||||
beforeAll(async () => {
|
it('finds 6 open transaction links and no deleted or redeemed', async () => {
|
||||||
// admin 'peter@lustig.de' has to exists for 'creationFactory'
|
await expect(
|
||||||
await userFactory(testEnv, peterLustig)
|
query({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
user = await userFactory(testEnv, bibiBloxberg)
|
variables: {
|
||||||
variables.userId = user.id
|
...variables,
|
||||||
variables.pageSize = 25
|
filters: {
|
||||||
// bibi needs GDDs
|
withDeleted: null,
|
||||||
const bibisCreation = creations.find(
|
withExpired: null,
|
||||||
(creation) => creation.email === 'bibi@bloxberg.de',
|
withRedeemed: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
listTransactionLinksAdmin: {
|
||||||
|
linkCount: 6,
|
||||||
|
linkList: expect.not.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
deletedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
})
|
||||||
await creationFactory(testEnv, bibisCreation!)
|
})
|
||||||
// bibis transaktion links
|
|
||||||
const bibisTransaktionLinks = transactionLinks.filter(
|
describe('filter with deleted', () => {
|
||||||
(transactionLink) => transactionLink.email === 'bibi@bloxberg.de',
|
it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => {
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables: {
|
||||||
|
...variables,
|
||||||
|
filters: {
|
||||||
|
withDeleted: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
listTransactionLinksAdmin: {
|
||||||
|
linkCount: 7,
|
||||||
|
linkList: expect.arrayContaining([
|
||||||
|
expect.not.objectContaining({
|
||||||
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
deletedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
for (let i = 0; i < bibisTransaktionLinks.length; i++) {
|
|
||||||
await transactionLinkFactory(testEnv, bibisTransaktionLinks[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// admin: only now log in
|
|
||||||
await mutate({
|
|
||||||
mutation: login,
|
|
||||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
describe('filter by expired', () => {
|
||||||
await cleanDB()
|
it('finds 5 open transaction links, 1 expired, and no redeemed', async () => {
|
||||||
resetToken()
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables: {
|
||||||
|
...variables,
|
||||||
|
filters: {
|
||||||
|
withExpired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
listTransactionLinksAdmin: {
|
||||||
|
linkCount: 7,
|
||||||
|
linkList: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
deletedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('without any filters', () => {
|
// TODO: works not as expected, because 'redeemedAt' and 'redeemedBy' have to be added to the transaktion link factory
|
||||||
it('finds 6 open transaction links and no deleted or redeemed', async () => {
|
describe.skip('filter by redeemed', () => {
|
||||||
await expect(
|
it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => {
|
||||||
query({
|
await expect(
|
||||||
query: listTransactionLinksAdmin,
|
query({
|
||||||
variables,
|
query: listTransactionLinksAdmin,
|
||||||
}),
|
variables: {
|
||||||
).resolves.toEqual(
|
...variables,
|
||||||
expect.objectContaining({
|
filters: {
|
||||||
data: {
|
withDeleted: null,
|
||||||
listTransactionLinksAdmin: {
|
withExpired: null,
|
||||||
linkCount: 6,
|
withRedeemed: true,
|
||||||
linkList: expect.not.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
|
||||||
createdAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Da habe ich mich wohl etwas übernommen.',
|
|
||||||
deletedAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
)
|
}),
|
||||||
})
|
).resolves.toEqual(
|
||||||
})
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
describe('all filters are null', () => {
|
listTransactionLinksAdmin: {
|
||||||
it('finds 6 open transaction links and no deleted or redeemed', async () => {
|
linkCount: 6,
|
||||||
await expect(
|
linkList: expect.arrayContaining([
|
||||||
query({
|
expect.not.objectContaining({
|
||||||
query: listTransactionLinksAdmin,
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
variables: {
|
createdAt: expect.any(String),
|
||||||
...variables,
|
}),
|
||||||
filters: {
|
expect.objectContaining({
|
||||||
withDeleted: null,
|
memo: 'Yeah, eingelöst!',
|
||||||
withExpired: null,
|
redeemedAt: expect.any(String),
|
||||||
withRedeemed: null,
|
redeemedBy: expect.any(Number),
|
||||||
},
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
deletedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
).resolves.toEqual(
|
}),
|
||||||
expect.objectContaining({
|
)
|
||||||
data: {
|
|
||||||
listTransactionLinksAdmin: {
|
|
||||||
linkCount: 6,
|
|
||||||
linkList: expect.not.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
|
||||||
createdAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Da habe ich mich wohl etwas übernommen.',
|
|
||||||
deletedAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('filter with deleted', () => {
|
|
||||||
it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => {
|
|
||||||
await expect(
|
|
||||||
query({
|
|
||||||
query: listTransactionLinksAdmin,
|
|
||||||
variables: {
|
|
||||||
...variables,
|
|
||||||
filters: {
|
|
||||||
withDeleted: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
listTransactionLinksAdmin: {
|
|
||||||
linkCount: 7,
|
|
||||||
linkList: expect.arrayContaining([
|
|
||||||
expect.not.objectContaining({
|
|
||||||
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
|
||||||
createdAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Da habe ich mich wohl etwas übernommen.',
|
|
||||||
deletedAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('filter by expired', () => {
|
|
||||||
it('finds 5 open transaction links, 1 expired, and no redeemed', async () => {
|
|
||||||
await expect(
|
|
||||||
query({
|
|
||||||
query: listTransactionLinksAdmin,
|
|
||||||
variables: {
|
|
||||||
...variables,
|
|
||||||
filters: {
|
|
||||||
withExpired: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
listTransactionLinksAdmin: {
|
|
||||||
linkCount: 7,
|
|
||||||
linkList: expect.arrayContaining([
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
|
||||||
createdAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
expect.not.objectContaining({
|
|
||||||
memo: 'Da habe ich mich wohl etwas übernommen.',
|
|
||||||
deletedAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: works not as expected, because 'redeemedAt' and 'redeemedBy' have to be added to the transaktion link factory
|
|
||||||
describe.skip('filter by redeemed', () => {
|
|
||||||
it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => {
|
|
||||||
await expect(
|
|
||||||
query({
|
|
||||||
query: listTransactionLinksAdmin,
|
|
||||||
variables: {
|
|
||||||
...variables,
|
|
||||||
filters: {
|
|
||||||
withDeleted: null,
|
|
||||||
withExpired: null,
|
|
||||||
withRedeemed: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
listTransactionLinksAdmin: {
|
|
||||||
linkCount: 6,
|
|
||||||
linkList: expect.arrayContaining([
|
|
||||||
expect.not.objectContaining({
|
|
||||||
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
|
||||||
createdAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
memo: 'Yeah, eingelöst!',
|
|
||||||
redeemedAt: expect.any(String),
|
|
||||||
redeemedBy: expect.any(Number),
|
|
||||||
}),
|
|
||||||
expect.not.objectContaining({
|
|
||||||
memo: 'Da habe ich mich wohl etwas übernommen.',
|
|
||||||
deletedAt: expect.any(String),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -64,12 +64,16 @@ export class TransactionLinkResolver {
|
|||||||
const createdDate = new Date()
|
const createdDate = new Date()
|
||||||
const validUntil = transactionLinkExpireDate(createdDate)
|
const validUntil = transactionLinkExpireDate(createdDate)
|
||||||
|
|
||||||
|
if (amount.lessThanOrEqualTo(0)) {
|
||||||
|
throw new LogError('Amount must be a positive number', amount)
|
||||||
|
}
|
||||||
|
|
||||||
const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay)
|
const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay)
|
||||||
|
|
||||||
// validate amount
|
// validate amount
|
||||||
const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate)
|
const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate)
|
||||||
if (!sendBalance) {
|
if (!sendBalance) {
|
||||||
throw new Error("user hasn't enough GDD or amount is < 0")
|
throw new LogError('User has not enough GDD', user.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const transactionLink = DbTransactionLink.create()
|
const transactionLink = DbTransactionLink.create()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user