use new Contribution Data Model

This commit is contained in:
Moriz Wahl 2022-05-30 14:15:34 +02:00
parent 4c7fc10d8f
commit 69a3cc0264
2 changed files with 68 additions and 61 deletions

View File

@ -2,7 +2,7 @@ import { ObjectType, Field, Int } from 'type-graphql'
import Decimal from 'decimal.js-light'
@ObjectType()
export class PendingCreation {
export class PendingContribution {
@Field(() => String)
firstName: string

View File

@ -11,7 +11,7 @@ import {
FindOperator,
} from '@dbTools/typeorm'
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
import { PendingCreation } from '@model/PendingCreation'
import { PendingContribution } from '@model/PendingContribution'
import { CreatePendingCreations } from '@model/CreatePendingCreations'
import { UpdatePendingCreation } from '@model/UpdatePendingCreation'
import { RIGHTS } from '@/auth/RIGHTS'
@ -25,7 +25,7 @@ import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
import { TransactionRepository } from '@repository/Transaction'
import { calculateDecay } from '@/util/decay'
import { AdminPendingCreation } from '@entity/AdminPendingCreation'
import { Contribution } from '@entity/Contribution'
import { hasElopageBuys } from '@/util/hasElopageBuys'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { User as dbUser } from '@entity/User'
@ -183,15 +183,15 @@ export class AdminResolver {
const creations = await getUserCreation(user.id)
const creationDateObj = new Date(creationDate)
if (isCreationValid(creations, amount, creationDateObj)) {
const adminPendingCreation = AdminPendingCreation.create()
adminPendingCreation.userId = user.id
adminPendingCreation.amount = amount
adminPendingCreation.created = new Date()
adminPendingCreation.date = creationDateObj
adminPendingCreation.memo = memo
adminPendingCreation.moderator = moderator.id
const contribution = Contribution.create()
contribution.userId = user.id
contribution.amount = amount
contribution.createdAt = new Date()
contribution.contributionDate = creationDateObj
contribution.memo = memo
contribution.moderatorId = moderator.id
await AdminPendingCreation.save(adminPendingCreation)
await Contribution.save(contribution)
}
return getUserCreation(user.id)
}
@ -200,20 +200,20 @@ export class AdminResolver {
@Mutation(() => CreatePendingCreations)
async createPendingCreations(
@Arg('pendingCreations', () => [CreatePendingCreationArgs])
pendingCreations: CreatePendingCreationArgs[],
contributions: CreatePendingCreationArgs[],
@Ctx() context: Context,
): Promise<CreatePendingCreations> {
let success = false
const successfulCreation: string[] = []
const failedCreation: string[] = []
for (const pendingCreation of pendingCreations) {
await this.createPendingCreation(pendingCreation, context)
for (const contribution of contributions) {
await this.createPendingCreation(contribution, context)
.then(() => {
successfulCreation.push(pendingCreation.email)
successfulCreation.push(contribution.email)
success = true
})
.catch(() => {
failedCreation.push(pendingCreation.email)
failedCreation.push(contribution.email)
})
}
return {
@ -239,34 +239,34 @@ export class AdminResolver {
const moderator = getUser(context)
const pendingCreationToUpdate = await AdminPendingCreation.findOne({ id })
const contributionToUpdate = await Contribution.findOne({ id })
if (!pendingCreationToUpdate) {
throw new Error('No creation found to given id.')
if (!contributionToUpdate) {
throw new Error('No contribution found to given id.')
}
if (pendingCreationToUpdate.userId !== user.id) {
throw new Error('user of the pending creation and send user does not correspond')
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 (pendingCreationToUpdate.date.getMonth() === creationDateObj.getMonth()) {
creations = updateCreations(creations, pendingCreationToUpdate)
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
creations = updateCreations(creations, contributionToUpdate)
}
// all possible cases not to be true are thrown in this function
isCreationValid(creations, amount, creationDateObj)
pendingCreationToUpdate.amount = amount
pendingCreationToUpdate.memo = memo
pendingCreationToUpdate.date = new Date(creationDate)
pendingCreationToUpdate.moderator = moderator.id
contributionToUpdate.amount = amount
contributionToUpdate.memo = memo
contributionToUpdate.contributionDate = new Date(creationDate)
contributionToUpdate.moderatorId = moderator.id
await AdminPendingCreation.save(pendingCreationToUpdate)
await Contribution.save(contributionToUpdate)
const result = new UpdatePendingCreation()
result.amount = amount
result.memo = pendingCreationToUpdate.memo
result.date = pendingCreationToUpdate.date
result.memo = contributionToUpdate.memo
result.date = contributionToUpdate.contributionDate
result.creation = await getUserCreation(user.id)
@ -274,24 +274,28 @@ export class AdminResolver {
}
@Authorized([RIGHTS.SEARCH_PENDING_CREATION])
@Query(() => [PendingCreation])
async getPendingCreations(): Promise<PendingCreation[]> {
const pendingCreations = await AdminPendingCreation.find()
if (pendingCreations.length === 0) {
@Query(() => [PendingContribution])
async getPendingCreations(): Promise<PendingContribution[]> {
const contributions = await Contribution.find()
if (contributions.length === 0) {
return []
}
const userIds = pendingCreations.map((p) => p.userId)
const userIds = contributions.map((p) => p.userId)
const userCreations = await getUserCreations(userIds)
const users = await dbUser.find({ where: { id: In(userIds) }, withDeleted: true })
return pendingCreations.map((pendingCreation) => {
const user = users.find((u) => u.id === pendingCreation.userId)
const creation = userCreations.find((c) => c.id === pendingCreation.userId)
return contributions.map((contribution) => {
const user = users.find((u) => u.id === contribution.userId)
const creation = userCreations.find((c) => c.id === contribution.userId)
return {
...pendingCreation,
amount: pendingCreation.amount,
id: contribution.id,
userId: contribution.userId,
date: contribution.contributionDate,
memo: contribution.memo,
amount: contribution.amount,
moderator: contribution.moderatorId,
firstName: user ? user.firstName : '',
lastName: user ? user.lastName : '',
email: user ? user.email : '',
@ -303,11 +307,11 @@ export class AdminResolver {
@Authorized([RIGHTS.DELETE_PENDING_CREATION])
@Mutation(() => Boolean)
async deletePendingCreation(@Arg('id', () => Int) id: number): Promise<boolean> {
const pendingCreation = await AdminPendingCreation.findOne(id)
if (!pendingCreation) {
const contribution = await Contribution.findOne(id)
if (!contribution) {
throw new Error('Creation not found for given id.')
}
const res = await AdminPendingCreation.delete(pendingCreation)
const res = await contribution.softRemove()
return !!res
}
@ -317,26 +321,26 @@ export class AdminResolver {
@Arg('id', () => Int) id: number,
@Ctx() context: Context,
): Promise<boolean> {
const pendingCreation = await AdminPendingCreation.findOne(id)
if (!pendingCreation) {
const contribution = await Contribution.findOne(id)
if (!contribution) {
throw new Error('Creation not found to given id.')
}
const moderatorUser = getUser(context)
if (moderatorUser.id === pendingCreation.userId)
if (moderatorUser.id === contribution.userId)
throw new Error('Moderator can not confirm own pending creation')
const user = await dbUser.findOneOrFail({ id: pendingCreation.userId }, { withDeleted: true })
const user = await dbUser.findOneOrFail({ id: contribution.userId }, { withDeleted: true })
if (user.deletedAt) throw new Error('This user was deleted. Cannot confirm a creation.')
const creations = await getUserCreation(pendingCreation.userId, false)
if (!isCreationValid(creations, pendingCreation.amount, pendingCreation.date)) {
const creations = await getUserCreation(contribution.userId, false)
if (!isCreationValid(creations, contribution.amount, contribution.contributionDate)) {
throw new Error('Creation is not valid!!')
}
const receivedCallDate = new Date()
const transactionRepository = getCustomRepository(TransactionRepository)
const lastTransaction = await transactionRepository.findLastForUser(pendingCreation.userId)
const lastTransaction = await transactionRepository.findLastForUser(contribution.userId)
let newBalance = new Decimal(0)
let decay: Decay | null = null
@ -344,15 +348,15 @@ export class AdminResolver {
decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, receivedCallDate)
newBalance = decay.balance
}
newBalance = newBalance.add(pendingCreation.amount.toString())
newBalance = newBalance.add(contribution.amount.toString())
const transaction = new DbTransaction()
transaction.typeId = TransactionTypeId.CREATION
transaction.memo = pendingCreation.memo
transaction.userId = pendingCreation.userId
transaction.memo = contribution.memo
transaction.userId = contribution.userId
transaction.previous = lastTransaction ? lastTransaction.id : null
transaction.amount = pendingCreation.amount
transaction.creationDate = pendingCreation.date
transaction.amount = contribution.amount
transaction.creationDate = contribution.contributionDate
transaction.balance = newBalance
transaction.balanceDate = receivedCallDate
transaction.decay = decay ? decay.decay : new Decimal(0)
@ -361,7 +365,10 @@ export class AdminResolver {
throw new Error('Unable to confirm creation.')
})
await AdminPendingCreation.delete(pendingCreation)
contribution.confirmedAt = receivedCallDate
contribution.confirmedBy = moderatorUser.id
await Contribution.save(contribution)
return true
}
@ -478,9 +485,9 @@ async function getUserCreations(ids: number[], includePending = true): Promise<C
const unionString = includePending
? `
UNION
SELECT date AS date, amount AS amount, userId AS userId FROM admin_pending_creations
SELECT contribution_date AS date, amount AS amount, user_id AS userId FROM contributions
WHERE userId IN (${ids.toString()})
AND date >= ${dateFilter}`
AND contribution_date >= ${dateFilter}`
: ''
const unionQuery = await queryRunner.manager.query(`
@ -510,13 +517,13 @@ async function getUserCreations(ids: number[], includePending = true): Promise<C
})
}
function updateCreations(creations: Decimal[], pendingCreation: AdminPendingCreation): Decimal[] {
const index = getCreationIndex(pendingCreation.date.getMonth())
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(pendingCreation.amount.toString())
creations[index] = creations[index].plus(contribution.amount.toString())
return creations
}