refactor(backend): field resolvers in statistics

This commit is contained in:
Moriz Wahl 2023-01-16 15:22:45 +01:00
parent becaa750e8
commit 7781011b1a
2 changed files with 103 additions and 62 deletions

View File

@ -2,13 +2,25 @@ import { ObjectType, Field } from 'type-graphql'
import Decimal from 'decimal.js-light'
@ObjectType()
export class CommunityStatistics {
@Field(() => Number)
totalUsers: number
export class TotalAvailable {
@Field(() => Number)
activeUsers: number
@Field(() => Decimal)
totalGradidoAvailable: Decimal
@Field(() => Decimal)
totalGradidoUnbookedDecayed: Decimal
}
@ObjectType()
export class CommunityStatistics {
@Field(() => Number)
allUsers: number
@Field(() => Number)
totalUsers: number
@Field(() => Number)
deletedUsers: number
@ -18,9 +30,6 @@ export class CommunityStatistics {
@Field(() => Decimal)
totalGradidoDecayed: Decimal
@Field(() => Decimal)
totalGradidoAvailable: Decimal
@Field(() => Decimal)
totalGradidoUnbookedDecayed: Decimal
@Field(() => TotalAvailable)
totalAvailable: TotalAvailable
}

View File

@ -1,81 +1,113 @@
import Decimal from 'decimal.js-light'
import { Resolver, Query, Authorized } from 'type-graphql'
import { Resolver, Query, Authorized, FieldResolver } from 'type-graphql'
import { getConnection } from '@dbTools/typeorm'
import { Transaction as DbTransaction } from '@entity/Transaction'
import { User as DbUser } from '@entity/User'
import { CommunityStatistics } from '@model/CommunityStatistics'
import { CommunityStatistics, TotalAvailable } from '@model/CommunityStatistics'
import { RIGHTS } from '@/auth/RIGHTS'
import { calculateDecay } from '@/util/decay'
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
@Resolver()
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
@Resolver((of) => CommunityStatistics)
export class StatisticsResolver {
@Authorized([RIGHTS.COMMUNITY_STATISTICS])
@Query(() => CommunityStatistics)
async communityStatistics(): Promise<CommunityStatistics> {
const allUsers = await DbUser.count({ withDeleted: true })
const totalUsers = await DbUser.count()
const deletedUsers = allUsers - totalUsers
return new CommunityStatistics()
}
@FieldResolver(() => Decimal)
async allUsers(): Promise<number> {
return await DbUser.count({ withDeleted: true })
}
@FieldResolver()
async totalUsers(): Promise<number> {
return await DbUser.count()
}
@FieldResolver()
async deletedUsers(): Promise<number> {
return (await this.allUsers()) - (await this.totalUsers())
}
@FieldResolver()
async totalGradidoCreated(): Promise<Decimal> {
const queryRunner = getConnection().createQueryRunner()
try {
await queryRunner.connect()
const { totalGradidoCreated } = await queryRunner.manager
.createQueryBuilder()
.select('SUM(transaction.amount) AS totalGradidoCreated')
.from(DbTransaction, 'transaction')
.where('transaction.typeId = 1')
.getRawOne()
return totalGradidoCreated
} finally {
await queryRunner.release()
}
}
@FieldResolver()
async totalGradidoDecayed(): Promise<Decimal> {
const queryRunner = getConnection().createQueryRunner()
try {
await queryRunner.connect()
const { totalGradidoDecayed } = await queryRunner.manager
.createQueryBuilder()
.select('SUM(transaction.decay) AS totalGradidoDecayed')
.from(DbTransaction, 'transaction')
.where('transaction.decay IS NOT NULL')
.getRawOne()
return totalGradidoDecayed
} finally {
await queryRunner.release()
}
}
@FieldResolver()
async totalAvailable(): Promise<TotalAvailable> {
let totalGradidoAvailable: Decimal = new Decimal(0)
let totalGradidoUnbookedDecayed: Decimal = new Decimal(0)
const receivedCallDate = new Date()
const queryRunner = getConnection().createQueryRunner()
await queryRunner.connect()
try {
await queryRunner.connect()
const lastUserTransactions = await queryRunner.manager
.createQueryBuilder(DbUser, 'user')
.select('transaction.balance', 'balance')
.addSelect('transaction.balance_date', 'balanceDate')
.innerJoin(DbTransaction, 'transaction', 'user.id = transaction.user_id')
.where(
`transaction.balance_date = (SELECT MAX(t.balance_date) FROM transactions AS t WHERE t.user_id = user.id)`,
)
.orderBy('transaction.balance_date', 'DESC')
.addOrderBy('transaction.id', 'DESC')
.getRawMany()
const lastUserTransactions = await queryRunner.manager
.createQueryBuilder(DbUser, 'user')
.select('transaction.balance', 'balance')
.addSelect('transaction.balance_date', 'balanceDate')
.innerJoin(DbTransaction, 'transaction', 'user.id = transaction.user_id')
.where(
`transaction.balance_date = (SELECT MAX(t.balance_date) FROM transactions AS t WHERE t.user_id = user.id)`,
)
.orderBy('transaction.balance_date', 'DESC')
.addOrderBy('transaction.id', 'DESC')
.getRawMany()
const activeUsers = lastUserTransactions.length
const activeUsers = lastUserTransactions.length
lastUserTransactions.forEach(({ balance, balanceDate }) => {
const decay = calculateDecay(new Decimal(balance), new Date(balanceDate), receivedCallDate)
if (decay) {
totalGradidoAvailable = totalGradidoAvailable.plus(decay.balance.toString())
totalGradidoUnbookedDecayed = totalGradidoUnbookedDecayed.plus(decay.decay.toString())
lastUserTransactions.forEach(({ balance, balanceDate }) => {
const decay = calculateDecay(new Decimal(balance), new Date(balanceDate), receivedCallDate)
if (decay) {
totalGradidoAvailable = totalGradidoAvailable.plus(decay.balance.toString())
totalGradidoUnbookedDecayed = totalGradidoUnbookedDecayed.plus(decay.decay.toString())
}
})
return {
activeUsers,
totalGradidoAvailable,
totalGradidoUnbookedDecayed,
}
})
const { totalGradidoCreated } = await queryRunner.manager
.createQueryBuilder()
.select('SUM(transaction.amount) AS totalGradidoCreated')
.from(DbTransaction, 'transaction')
.where('transaction.typeId = 1')
.getRawOne()
const { totalGradidoDecayed } = await queryRunner.manager
.createQueryBuilder()
.select('SUM(transaction.decay) AS totalGradidoDecayed')
.from(DbTransaction, 'transaction')
.where('transaction.decay IS NOT NULL')
.getRawOne()
await queryRunner.release()
return {
totalUsers,
activeUsers,
deletedUsers,
totalGradidoCreated,
totalGradidoDecayed,
totalGradidoAvailable,
totalGradidoUnbookedDecayed,
} finally {
await queryRunner.release()
}
}
}