mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into statistics-resolver
This commit is contained in:
commit
ff93ce3b29
@ -26,6 +26,8 @@ export enum RIGHTS {
|
|||||||
LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS',
|
LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS',
|
||||||
GDT_BALANCE = 'GDT_BALANCE',
|
GDT_BALANCE = 'GDT_BALANCE',
|
||||||
CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION',
|
CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION',
|
||||||
|
LIST_CONTRIBUTIONS = 'LIST_CONTRIBUTIONS',
|
||||||
|
UPDATE_CONTRIBUTION = 'UPDATE_CONTRIBUTION',
|
||||||
// Admin
|
// Admin
|
||||||
SEARCH_USERS = 'SEARCH_USERS',
|
SEARCH_USERS = 'SEARCH_USERS',
|
||||||
SET_USER_ROLE = 'SET_USER_ROLE',
|
SET_USER_ROLE = 'SET_USER_ROLE',
|
||||||
|
|||||||
@ -24,6 +24,8 @@ export const ROLE_USER = new Role('user', [
|
|||||||
RIGHTS.LIST_TRANSACTION_LINKS,
|
RIGHTS.LIST_TRANSACTION_LINKS,
|
||||||
RIGHTS.GDT_BALANCE,
|
RIGHTS.GDT_BALANCE,
|
||||||
RIGHTS.CREATE_CONTRIBUTION,
|
RIGHTS.CREATE_CONTRIBUTION,
|
||||||
|
RIGHTS.LIST_CONTRIBUTIONS,
|
||||||
|
RIGHTS.UPDATE_CONTRIBUTION,
|
||||||
])
|
])
|
||||||
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights
|
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ Decimal.set({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const constants = {
|
const constants = {
|
||||||
DB_VERSION: '0040-add_contribution_link_id_to_user',
|
DB_VERSION: '0042-update_transactions_for_blockchain',
|
||||||
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
|
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
|
||||||
LOG4JS_CONFIG: 'log4js-config.json',
|
LOG4JS_CONFIG: 'log4js-config.json',
|
||||||
// default log level on production should be info
|
// default log level on production should be info
|
||||||
|
|||||||
43
backend/src/graphql/model/Contribution.ts
Normal file
43
backend/src/graphql/model/Contribution.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { ObjectType, Field, Int } from 'type-graphql'
|
||||||
|
import Decimal from 'decimal.js-light'
|
||||||
|
import { Contribution as dbContribution } from '@entity/Contribution'
|
||||||
|
import { User } from './User'
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class Contribution {
|
||||||
|
constructor(contribution: dbContribution, user: User) {
|
||||||
|
this.id = contribution.id
|
||||||
|
this.user = user
|
||||||
|
this.amount = contribution.amount
|
||||||
|
this.memo = contribution.memo
|
||||||
|
this.createdAt = contribution.createdAt
|
||||||
|
this.deletedAt = contribution.deletedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Field(() => User)
|
||||||
|
user: User
|
||||||
|
|
||||||
|
@Field(() => Decimal)
|
||||||
|
amount: Decimal
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Field(() => Date)
|
||||||
|
createdAt: Date
|
||||||
|
|
||||||
|
@Field(() => Date, { nullable: true })
|
||||||
|
deletedAt: Date | null
|
||||||
|
}
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class ContributionListResult {
|
||||||
|
@Field(() => Int)
|
||||||
|
linkCount: number
|
||||||
|
|
||||||
|
@Field(() => [Contribution])
|
||||||
|
linkList: Contribution[]
|
||||||
|
}
|
||||||
@ -1,10 +1,12 @@
|
|||||||
import { ObjectType, Field } from 'type-graphql'
|
import { ObjectType, Field } from 'type-graphql'
|
||||||
import { KlickTipp } from './KlickTipp'
|
import { KlickTipp } from './KlickTipp'
|
||||||
import { User as dbUser } from '@entity/User'
|
import { User as dbUser } from '@entity/User'
|
||||||
|
import Decimal from 'decimal.js-light'
|
||||||
|
import { FULL_CREATION_AVAILABLE } from '../resolver/const/const'
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
export class User {
|
export class User {
|
||||||
constructor(user: dbUser) {
|
constructor(user: dbUser, creation: Decimal[] = FULL_CREATION_AVAILABLE) {
|
||||||
this.id = user.id
|
this.id = user.id
|
||||||
this.email = user.email
|
this.email = user.email
|
||||||
this.firstName = user.firstName
|
this.firstName = user.firstName
|
||||||
@ -17,6 +19,7 @@ export class User {
|
|||||||
this.isAdmin = user.isAdmin
|
this.isAdmin = user.isAdmin
|
||||||
this.klickTipp = null
|
this.klickTipp = null
|
||||||
this.hasElopage = null
|
this.hasElopage = null
|
||||||
|
this.creation = creation
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(() => Number)
|
@Field(() => Number)
|
||||||
@ -64,4 +67,7 @@ export class User {
|
|||||||
|
|
||||||
@Field(() => Boolean, { nullable: true })
|
@Field(() => Boolean, { nullable: true })
|
||||||
hasElopage: boolean | null
|
hasElopage: boolean | null
|
||||||
|
|
||||||
|
@Field(() => [Decimal])
|
||||||
|
creation: Decimal[]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,11 +47,11 @@ import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
|
|||||||
import { transactionLinkCode as contributionLinkCode } from './TransactionLinkResolver'
|
import { transactionLinkCode as contributionLinkCode } from './TransactionLinkResolver'
|
||||||
import CONFIG from '@/config'
|
import CONFIG from '@/config'
|
||||||
import {
|
import {
|
||||||
getCreationIndex,
|
|
||||||
getUserCreation,
|
getUserCreation,
|
||||||
getUserCreations,
|
getUserCreations,
|
||||||
validateContribution,
|
validateContribution,
|
||||||
isStartEndDateValid,
|
isStartEndDateValid,
|
||||||
|
updateCreations,
|
||||||
} from './util/creations'
|
} from './util/creations'
|
||||||
import {
|
import {
|
||||||
CONTRIBUTIONLINK_MEMO_MAX_CHARS,
|
CONTRIBUTIONLINK_MEMO_MAX_CHARS,
|
||||||
@ -321,6 +321,10 @@ export class AdminResolver {
|
|||||||
throw new Error('user of the pending contribution and send user does not correspond')
|
throw new Error('user of the pending contribution and send user does not correspond')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contributionToUpdate.moderatorId === null) {
|
||||||
|
throw new Error('An admin is not allowed to update a user contribution.')
|
||||||
|
}
|
||||||
|
|
||||||
const creationDateObj = new Date(creationDate)
|
const creationDateObj = new Date(creationDate)
|
||||||
let creations = await getUserCreation(user.id)
|
let creations = await getUserCreation(user.id)
|
||||||
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
|
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
|
||||||
@ -688,13 +692,3 @@ export class AdminResolver {
|
|||||||
return new ContributionLink(dbContributionLink)
|
return new ContributionLink(dbContributionLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCreations(creations: Decimal[], contribution: Contribution): Decimal[] {
|
|
||||||
const index = getCreationIndex(contribution.contributionDate.getMonth())
|
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
throw new Error('You cannot create GDD for a month older than the last three months.')
|
|
||||||
}
|
|
||||||
creations[index] = creations[index].plus(contribution.amount.toString())
|
|
||||||
return creations
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,14 +2,22 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
|
||||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||||
import { createContribution } from '@/seeds/graphql/mutations'
|
import {
|
||||||
import { login } from '@/seeds/graphql/queries'
|
adminUpdateContribution,
|
||||||
|
createContribution,
|
||||||
|
updateContribution,
|
||||||
|
} from '@/seeds/graphql/mutations'
|
||||||
|
import { listContributions, login } from '@/seeds/graphql/queries'
|
||||||
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
|
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
|
||||||
import { GraphQLError } from 'graphql'
|
import { GraphQLError } from 'graphql'
|
||||||
import { userFactory } from '@/seeds/factory/user'
|
import { userFactory } from '@/seeds/factory/user'
|
||||||
|
import { creationFactory } from '@/seeds/factory/creation'
|
||||||
|
import { creations } from '@/seeds/creation/index'
|
||||||
|
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||||
|
|
||||||
let mutate: any, query: any, con: any
|
let mutate: any, query: any, con: any
|
||||||
let testEnv: any
|
let testEnv: any
|
||||||
|
let result: any
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
testEnv = await testEnvironment()
|
testEnv = await testEnvironment()
|
||||||
@ -111,6 +119,7 @@ describe('ContributionResolver', () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
createContribution: {
|
createContribution: {
|
||||||
|
id: expect.any(Number),
|
||||||
amount: '100',
|
amount: '100',
|
||||||
memo: 'Test env contribution',
|
memo: 'Test env contribution',
|
||||||
},
|
},
|
||||||
@ -121,4 +130,312 @@ describe('ContributionResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('listContributions', () => {
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listContributions,
|
||||||
|
variables: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 25,
|
||||||
|
order: 'DESC',
|
||||||
|
filterConfirmed: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await userFactory(testEnv, bibiBloxberg)
|
||||||
|
await userFactory(testEnv, peterLustig)
|
||||||
|
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await creationFactory(testEnv, bibisCreation!)
|
||||||
|
await query({
|
||||||
|
query: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: createContribution,
|
||||||
|
variables: {
|
||||||
|
amount: 100.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('filter confirmed is false', () => {
|
||||||
|
it('returns creations', async () => {
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listContributions,
|
||||||
|
variables: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 25,
|
||||||
|
order: 'DESC',
|
||||||
|
filterConfirmed: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
listContributions: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
memo: 'Herzlich Willkommen bei Gradido!',
|
||||||
|
amount: '1000',
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
amount: '100',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('filter confirmed is true', () => {
|
||||||
|
it('returns only unconfirmed creations', async () => {
|
||||||
|
await expect(
|
||||||
|
query({
|
||||||
|
query: listContributions,
|
||||||
|
variables: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 25,
|
||||||
|
order: 'DESC',
|
||||||
|
filterConfirmed: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
listContributions: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
amount: '100',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('updateContribution', () => {
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: 1,
|
||||||
|
amount: 100.0,
|
||||||
|
memo: 'Test Contribution',
|
||||||
|
creationDate: 'not-valid',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await userFactory(testEnv, peterLustig)
|
||||||
|
await userFactory(testEnv, bibiBloxberg)
|
||||||
|
await query({
|
||||||
|
query: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
result = await mutate({
|
||||||
|
mutation: createContribution,
|
||||||
|
variables: {
|
||||||
|
amount: 100.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('wrong contribution id', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: -1,
|
||||||
|
amount: 100.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('No contribution found to given id.')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('wrong user tries to update the contribution', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await query({
|
||||||
|
query: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: result.data.createContribution.id,
|
||||||
|
amount: 10.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [
|
||||||
|
new GraphQLError(
|
||||||
|
'user of the pending contribution and send user does not correspond',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('admin tries to update a user contribution', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminUpdateContribution,
|
||||||
|
variables: {
|
||||||
|
id: result.data.createContribution.id,
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
amount: 10.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('An admin is not allowed to update a user contribution.')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('update too much so that the limit is exceeded', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await query({
|
||||||
|
query: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: result.data.createContribution.id,
|
||||||
|
amount: 1019.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [
|
||||||
|
new GraphQLError(
|
||||||
|
'The amount (1019 GDD) to be created exceeds the amount (1000 GDD) still available for this month.',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('update creation to a date that is older than 3 months', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
const date = new Date()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: result.data.createContribution.id,
|
||||||
|
amount: 10.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: date.setMonth(date.getMonth() - 3).toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [
|
||||||
|
new GraphQLError('No information for available creations for the given date'),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('valid input', () => {
|
||||||
|
it('updates contribution', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: updateContribution,
|
||||||
|
variables: {
|
||||||
|
contributionId: result.data.createContribution.id,
|
||||||
|
amount: 10.0,
|
||||||
|
memo: 'Test contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
updateContribution: {
|
||||||
|
id: result.data.createContribution.id,
|
||||||
|
amount: '10',
|
||||||
|
memo: 'Test contribution',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
import { RIGHTS } from '@/auth/RIGHTS'
|
import { RIGHTS } from '@/auth/RIGHTS'
|
||||||
import { Context, getUser } from '@/server/context'
|
import { Context, getUser } from '@/server/context'
|
||||||
import { backendLogger as logger } from '@/server/logger'
|
import { backendLogger as logger } from '@/server/logger'
|
||||||
import { Contribution } from '@entity/Contribution'
|
import { Contribution as dbContribution } from '@entity/Contribution'
|
||||||
import { Args, Authorized, Ctx, Mutation, Resolver } from 'type-graphql'
|
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
|
||||||
import ContributionArgs from '../arg/ContributionArgs'
|
import { FindOperator, IsNull } from '@dbTools/typeorm'
|
||||||
import { UnconfirmedContribution } from '../model/UnconfirmedContribution'
|
import ContributionArgs from '@arg/ContributionArgs'
|
||||||
import { validateContribution, getUserCreation } from './util/creations'
|
import Paginated from '@arg/Paginated'
|
||||||
|
import { Order } from '@enum/Order'
|
||||||
|
import { Contribution } from '@model/Contribution'
|
||||||
|
import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
|
||||||
|
import { User } from '@model/User'
|
||||||
|
import { validateContribution, getUserCreation, updateCreations } from './util/creations'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class ContributionResolver {
|
export class ContributionResolver {
|
||||||
@ -21,7 +26,7 @@ export class ContributionResolver {
|
|||||||
const creationDateObj = new Date(creationDate)
|
const creationDateObj = new Date(creationDate)
|
||||||
validateContribution(creations, amount, creationDateObj)
|
validateContribution(creations, amount, creationDateObj)
|
||||||
|
|
||||||
const contribution = Contribution.create()
|
const contribution = dbContribution.create()
|
||||||
contribution.userId = user.id
|
contribution.userId = user.id
|
||||||
contribution.amount = amount
|
contribution.amount = amount
|
||||||
contribution.createdAt = new Date()
|
contribution.createdAt = new Date()
|
||||||
@ -29,7 +34,69 @@ export class ContributionResolver {
|
|||||||
contribution.memo = memo
|
contribution.memo = memo
|
||||||
|
|
||||||
logger.trace('contribution to save', contribution)
|
logger.trace('contribution to save', contribution)
|
||||||
await Contribution.save(contribution)
|
await dbContribution.save(contribution)
|
||||||
return new UnconfirmedContribution(contribution, user, creations)
|
return new UnconfirmedContribution(contribution, user, creations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Authorized([RIGHTS.LIST_CONTRIBUTIONS])
|
||||||
|
@Query(() => [Contribution])
|
||||||
|
async listContributions(
|
||||||
|
@Args()
|
||||||
|
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
||||||
|
@Arg('filterConfirmed', () => Boolean)
|
||||||
|
filterConfirmed: boolean | null,
|
||||||
|
@Ctx() context: Context,
|
||||||
|
): Promise<Contribution[]> {
|
||||||
|
const user = getUser(context)
|
||||||
|
const where: {
|
||||||
|
userId: number
|
||||||
|
confirmedBy?: FindOperator<number> | null
|
||||||
|
} = { userId: user.id }
|
||||||
|
if (filterConfirmed) where.confirmedBy = IsNull()
|
||||||
|
const contributions = await dbContribution.find({
|
||||||
|
where,
|
||||||
|
order: {
|
||||||
|
createdAt: order,
|
||||||
|
},
|
||||||
|
skip: (currentPage - 1) * pageSize,
|
||||||
|
take: pageSize,
|
||||||
|
})
|
||||||
|
return contributions.map((contribution) => new Contribution(contribution, new User(user)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Authorized([RIGHTS.UPDATE_CONTRIBUTION])
|
||||||
|
@Mutation(() => UnconfirmedContribution)
|
||||||
|
async updateContribution(
|
||||||
|
@Arg('contributionId', () => Int)
|
||||||
|
contributionId: number,
|
||||||
|
@Args() { amount, memo, creationDate }: ContributionArgs,
|
||||||
|
@Ctx() context: Context,
|
||||||
|
): Promise<UnconfirmedContribution> {
|
||||||
|
const user = getUser(context)
|
||||||
|
|
||||||
|
const contributionToUpdate = await dbContribution.findOne({
|
||||||
|
where: { id: contributionId, confirmedAt: IsNull() },
|
||||||
|
})
|
||||||
|
if (!contributionToUpdate) {
|
||||||
|
throw new Error('No contribution found to given id.')
|
||||||
|
}
|
||||||
|
if (contributionToUpdate.userId !== user.id) {
|
||||||
|
throw new Error('user of the pending contribution and send user does not correspond')
|
||||||
|
}
|
||||||
|
|
||||||
|
const creationDateObj = new Date(creationDate)
|
||||||
|
let creations = await getUserCreation(user.id)
|
||||||
|
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
|
||||||
|
creations = updateCreations(creations, contributionToUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// all possible cases not to be true are thrown in this function
|
||||||
|
validateContribution(creations, amount, creationDateObj)
|
||||||
|
contributionToUpdate.amount = amount
|
||||||
|
contributionToUpdate.memo = memo
|
||||||
|
contributionToUpdate.contributionDate = new Date(creationDate)
|
||||||
|
dbContribution.save(contributionToUpdate)
|
||||||
|
|
||||||
|
return new UnconfirmedContribution(contributionToUpdate, user, creations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegi
|
|||||||
import { klicktippSignIn } from '@/apis/KlicktippController'
|
import { klicktippSignIn } from '@/apis/KlicktippController'
|
||||||
import { RIGHTS } from '@/auth/RIGHTS'
|
import { RIGHTS } from '@/auth/RIGHTS'
|
||||||
import { hasElopageBuys } from '@/util/hasElopageBuys'
|
import { hasElopageBuys } from '@/util/hasElopageBuys'
|
||||||
|
import { getUserCreation } from './util/creations'
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const sodium = require('sodium-native')
|
const sodium = require('sodium-native')
|
||||||
@ -224,7 +225,7 @@ export class UserResolver {
|
|||||||
logger.info('verifyLogin...')
|
logger.info('verifyLogin...')
|
||||||
// TODO refactor and do not have duplicate code with login(see below)
|
// TODO refactor and do not have duplicate code with login(see below)
|
||||||
const userEntity = getUser(context)
|
const userEntity = getUser(context)
|
||||||
const user = new User(userEntity)
|
const user = new User(userEntity, await getUserCreation(userEntity.id))
|
||||||
// user.pubkey = userEntity.pubKey.toString('hex')
|
// user.pubkey = userEntity.pubKey.toString('hex')
|
||||||
// Elopage Status & Stored PublisherId
|
// Elopage Status & Stored PublisherId
|
||||||
user.hasElopage = await this.hasElopage(context)
|
user.hasElopage = await this.hasElopage(context)
|
||||||
@ -274,7 +275,7 @@ export class UserResolver {
|
|||||||
logger.addContext('user', dbUser.id)
|
logger.addContext('user', dbUser.id)
|
||||||
logger.debug('login credentials valid...')
|
logger.debug('login credentials valid...')
|
||||||
|
|
||||||
const user = new User(dbUser)
|
const user = new User(dbUser, await getUserCreation(dbUser.id))
|
||||||
logger.debug('user=' + user)
|
logger.debug('user=' + user)
|
||||||
|
|
||||||
// Elopage Status & Stored PublisherId
|
// Elopage Status & Stored PublisherId
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||||
import { backendLogger as logger } from '@/server/logger'
|
import { backendLogger as logger } from '@/server/logger'
|
||||||
import { getConnection } from '@dbTools/typeorm'
|
import { getConnection } from '@dbTools/typeorm'
|
||||||
|
import { Contribution } from '@entity/Contribution'
|
||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '../const/const'
|
import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '../const/const'
|
||||||
|
|
||||||
@ -117,3 +118,13 @@ export const isStartEndDateValid = (
|
|||||||
throw new Error(`The value of validFrom must before or equals the validTo!`)
|
throw new Error(`The value of validFrom must before or equals the validTo!`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const updateCreations = (creations: Decimal[], contribution: Contribution): Decimal[] => {
|
||||||
|
const index = getCreationIndex(contribution.contributionDate.getMonth())
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
throw new Error('You cannot create GDD for a month older than the last three months.')
|
||||||
|
}
|
||||||
|
creations[index] = creations[index].plus(contribution.amount.toString())
|
||||||
|
return creations
|
||||||
|
}
|
||||||
|
|||||||
@ -234,6 +234,22 @@ export const deleteContributionLink = gql`
|
|||||||
export const createContribution = gql`
|
export const createContribution = gql`
|
||||||
mutation ($amount: Decimal!, $memo: String!, $creationDate: String!) {
|
mutation ($amount: Decimal!, $memo: String!, $creationDate: String!) {
|
||||||
createContribution(amount: $amount, memo: $memo, creationDate: $creationDate) {
|
createContribution(amount: $amount, memo: $memo, creationDate: $creationDate) {
|
||||||
|
id
|
||||||
|
amount
|
||||||
|
memo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const updateContribution = gql`
|
||||||
|
mutation ($contributionId: Int!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
|
||||||
|
updateContribution(
|
||||||
|
contributionId: $contributionId
|
||||||
|
amount: $amount
|
||||||
|
memo: $memo
|
||||||
|
creationDate: $creationDate
|
||||||
|
) {
|
||||||
|
id
|
||||||
amount
|
amount
|
||||||
memo
|
memo
|
||||||
}
|
}
|
||||||
|
|||||||
@ -172,6 +172,25 @@ export const queryTransactionLink = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const listContributions = gql`
|
||||||
|
query (
|
||||||
|
$currentPage: Int = 1
|
||||||
|
$pageSize: Int = 5
|
||||||
|
$order: Order
|
||||||
|
$filterConfirmed: Boolean = false
|
||||||
|
) {
|
||||||
|
listContributions(
|
||||||
|
currentPage: $currentPage
|
||||||
|
pageSize: $pageSize
|
||||||
|
order: $order
|
||||||
|
filterConfirmed: $filterConfirmed
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
amount
|
||||||
|
memo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
// from admin interface
|
// from admin interface
|
||||||
|
|
||||||
export const listUnconfirmedContributions = gql`
|
export const listUnconfirmedContributions = gql`
|
||||||
|
|||||||
130
database/migrations/0041-move_users_creation_date.ts
Normal file
130
database/migrations/0041-move_users_creation_date.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move forward the creation date of the users by 1 or 2 hours,
|
||||||
|
for which there are transactions created before their account creation.
|
||||||
|
|
||||||
|
Because of a error by importing data from old db format into new, all older transactions balance_date
|
||||||
|
are 1 or 2 hours off
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
/* generate raw mysql queries
|
||||||
|
const usersToMove = await queryFn(
|
||||||
|
`
|
||||||
|
SELECT u.id, u.created, t.balance_date
|
||||||
|
FROM \`users\` as u
|
||||||
|
LEFT JOIN \`transactions\` as t
|
||||||
|
ON t.user_id = u.id where t.balance_date < u.created
|
||||||
|
order by id
|
||||||
|
`
|
||||||
|
)
|
||||||
|
let downgradeQueries = ''
|
||||||
|
for(const id in usersToMove) {
|
||||||
|
const user = usersToMove[id]
|
||||||
|
const diff = (user.created - user.balance_date) / 1000
|
||||||
|
const correcture = diff < 3600 ? 1: 2
|
||||||
|
const correctedDate = new Date(user.created)
|
||||||
|
correctedDate.setHours(correctedDate.getHours() - correcture)
|
||||||
|
//console.log("%d, %s, %s, %s, %d", user.id, user.created, user.balance_date, diff, correcture)
|
||||||
|
console.log('await queryFn(`UPDATE \\`users\\` SET \\`created\\` = \'%s\' WHERE \\`id\\` = %d`)',
|
||||||
|
correctedDate.toISOString().slice(0, 19).replace('T', ' '),
|
||||||
|
user.id
|
||||||
|
)
|
||||||
|
downgradeQueries += 'await queryFn(`UPDATE \\`users\\` SET \\`created\\` = \''
|
||||||
|
downgradeQueries += user.created.toISOString().slice(0, 19).replace('T', ' ')
|
||||||
|
downgradeQueries += '\' WHERE \\`id\\` = '
|
||||||
|
downgradeQueries += user.id
|
||||||
|
downgradeQueries += '`)\n'
|
||||||
|
}
|
||||||
|
console.log('downgrade: \n%s', downgradeQueries)
|
||||||
|
*/
|
||||||
|
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-01-25 08:01:52' WHERE \`id\` = 179`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-05-26 10:21:57' WHERE \`id\` = 443`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-08 17:04:41' WHERE \`id\` = 490`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-12 20:07:17' WHERE \`id\` = 508`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-07-17 19:20:36' WHERE \`id\` = 621`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-11-22 16:31:48' WHERE \`id\` = 788`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-12-17 20:09:16' WHERE \`id\` = 825`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-01-26 13:09:35' WHERE \`id\` = 949`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-03-20 16:55:46' WHERE \`id\` = 1057`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 15:59:30' WHERE \`id\` = 1228`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:58:15' WHERE \`id\` = 1230`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:58:15' WHERE \`id\` = 1230`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-17 22:51:19' WHERE \`id\` = 1239`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-03 07:23:28' WHERE \`id\` = 1273`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-09 06:16:18' WHERE \`id\` = 1287`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-17 11:26:41' WHERE \`id\` = 1298`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 07:24:57' WHERE \`id\` = 1326`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 07:24:57' WHERE \`id\` = 1326`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-13 12:07:29' WHERE \`id\` = 1342`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-16 15:32:48' WHERE \`id\` = 1348`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-09-30 14:06:40' WHERE \`id\` = 1470`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-15 14:35:37' WHERE \`id\` = 1490`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 06:42:00' WHERE \`id\` = 1492`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 06:42:00' WHERE \`id\` = 1492`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-22 09:45:15' WHERE \`id\` = 1576`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-23 13:55:37' WHERE \`id\` = 1582`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 14:58:12' WHERE \`id\` = 1729`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 18:03:10' WHERE \`id\` = 1732`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 15:00:38' WHERE \`id\` = 1756`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 20:01:58' WHERE \`id\` = 1757`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-21 15:58:48' WHERE \`id\` = 1762`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-01-25 09:01:52' WHERE \`id\` = 179`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-05-26 11:21:57' WHERE \`id\` = 443`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-08 19:04:41' WHERE \`id\` = 490`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-12 22:07:17' WHERE \`id\` = 508`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-07-17 21:20:36' WHERE \`id\` = 621`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-11-22 17:31:48' WHERE \`id\` = 788`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-12-17 21:09:16' WHERE \`id\` = 825`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-01-26 14:09:35' WHERE \`id\` = 949`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-03-20 17:55:46' WHERE \`id\` = 1057`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:59:30' WHERE \`id\` = 1228`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:58:15' WHERE \`id\` = 1230`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:58:15' WHERE \`id\` = 1230`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-18 00:51:19' WHERE \`id\` = 1239`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-03 09:23:28' WHERE \`id\` = 1273`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-09 08:16:18' WHERE \`id\` = 1287`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-17 13:26:41' WHERE \`id\` = 1298`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 09:24:57' WHERE \`id\` = 1326`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 09:24:57' WHERE \`id\` = 1326`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-13 14:07:29' WHERE \`id\` = 1342`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-16 16:32:48' WHERE \`id\` = 1348`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-09-30 16:06:40' WHERE \`id\` = 1470`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-15 16:35:37' WHERE \`id\` = 1490`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 08:42:00' WHERE \`id\` = 1492`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 08:42:00' WHERE \`id\` = 1492`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-22 10:45:15' WHERE \`id\` = 1576`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-23 14:55:37' WHERE \`id\` = 1582`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 15:58:12' WHERE \`id\` = 1729`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 19:03:10' WHERE \`id\` = 1732`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 16:00:38' WHERE \`id\` = 1756`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 21:01:58' WHERE \`id\` = 1757`)
|
||||||
|
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-21 16:58:48' WHERE \`id\` = 1762`)
|
||||||
|
}
|
||||||
1917
database/migrations/0042-update_transactions_for_blockchain.ts
Normal file
1917
database/migrations/0042-update_transactions_for_blockchain.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
|||||||
{{ $t('auth.left.gratitude') }}
|
{{ $t('auth.left.gratitude') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="position-absolute h2 text-white zindex1000 w-100 text-center mt-9">
|
<div class="position-absolute h2 text-white zindex1000 w-100 text-center mt-9">
|
||||||
{{ $t('auth.left.newCurrency') }}
|
{{ $t('auth.left.oneGratitude') }}
|
||||||
</div>
|
</div>
|
||||||
<img
|
<img
|
||||||
src="/img/template/Blaetter.png"
|
src="/img/template/Blaetter.png"
|
||||||
|
|||||||
@ -12,10 +12,9 @@
|
|||||||
"hasAccount": "Du hast schon einen Account?",
|
"hasAccount": "Du hast schon einen Account?",
|
||||||
"hereLogin": "Hier Anmelden",
|
"hereLogin": "Hier Anmelden",
|
||||||
"learnMore": "Erfahre mehr …",
|
"learnMore": "Erfahre mehr …",
|
||||||
"newCurrency": "Die neue Währung",
|
|
||||||
"oneDignity": "Wir schenken einander und danken mit Gradido.",
|
"oneDignity": "Wir schenken einander und danken mit Gradido.",
|
||||||
"oneDonation": "Du bist ein Geschenk für die Gemeinschaft. 1000 Dank, weil du bei uns bist.",
|
"oneDonation": "Du bist ein Geschenk für die Gemeinschaft. 1000 Dank, weil du bei uns bist.",
|
||||||
"oneGratitude": "Die neue Währung. Für einander, für alle Menschen, für die Natur."
|
"oneGratitude": "Für einander, für alle Menschen, für die Natur."
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"aboutGradido": "Über Gradido"
|
"aboutGradido": "Über Gradido"
|
||||||
|
|||||||
@ -12,10 +12,9 @@
|
|||||||
"hasAccount": "You already have an account?",
|
"hasAccount": "You already have an account?",
|
||||||
"hereLogin": "Log in here",
|
"hereLogin": "Log in here",
|
||||||
"learnMore": "Learn more …",
|
"learnMore": "Learn more …",
|
||||||
"newCurrency": "The new currency",
|
|
||||||
"oneDignity": "We gift to each other and give thanks with Gradido.",
|
"oneDignity": "We gift to each other and give thanks with Gradido.",
|
||||||
"oneDonation": "You are a gift for the community. 1000 thanks because you are with us.",
|
"oneDonation": "You are a gift for the community. 1000 thanks because you are with us.",
|
||||||
"oneGratitude": "The new currency. For each other, for all people, for nature."
|
"oneGratitude": "For each other, for all people, for nature."
|
||||||
},
|
},
|
||||||
"navbar": {
|
"navbar": {
|
||||||
"aboutGradido": "About Gradido"
|
"aboutGradido": "About Gradido"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user