mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
196 lines
6.5 KiB
TypeScript
196 lines
6.5 KiB
TypeScript
import { User as dbUser } from '../../typeorm/entity/User'
|
|
import { TransactionList, Transaction } from '../models/Transaction'
|
|
import { UserTransaction as dbUserTransaction } from '../../typeorm/entity/UserTransaction'
|
|
import { Transaction as dbTransaction } from '../../typeorm/entity/Transaction'
|
|
import { Decay } from '../models/Decay'
|
|
import { calculateDecayWithInterval } from '../../util/decay'
|
|
import { roundFloorFrom4 } from '../../util/round'
|
|
|
|
async function calculateAndAddDecayTransactions(
|
|
userTransactions: dbUserTransaction[],
|
|
user: dbUser,
|
|
decay: boolean,
|
|
skipFirstTransaction: boolean,
|
|
): Promise<Transaction[]> {
|
|
const finalTransactions: Transaction[] = []
|
|
const transactionIds: number[] = []
|
|
const involvedUserIds: number[] = []
|
|
|
|
userTransactions.forEach((userTransaction: dbUserTransaction) => {
|
|
transactionIds.push(userTransaction.transactionId)
|
|
involvedUserIds.push(userTransaction.userId)
|
|
})
|
|
// remove duplicates
|
|
// https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates
|
|
const involvedUsersUnique = involvedUserIds.filter((v, i, a) => a.indexOf(v) === i)
|
|
const userIndiced = await dbUser.getUsersIndiced(involvedUsersUnique)
|
|
|
|
const transactions = await dbTransaction
|
|
.createQueryBuilder('transaction')
|
|
.where('transaction.id IN (:...transactions)', { transactions: transactionIds })
|
|
.leftJoinAndSelect(
|
|
'transaction.sendCoin',
|
|
'transactionSendCoin',
|
|
'transactionSendCoin.transactionid = transaction.id',
|
|
)
|
|
.leftJoinAndSelect(
|
|
'transaction.creation',
|
|
'transactionCreation',
|
|
'transactionSendCoin.transactionid = transaction.id',
|
|
)
|
|
.getMany()
|
|
|
|
const transactionIndiced: dbTransaction[] = []
|
|
transactions.forEach((transaction: dbTransaction) => {
|
|
transactionIndiced[transaction.id] = transaction
|
|
})
|
|
|
|
const decayStartTransaction = await Decay.getDecayStartBlock()
|
|
|
|
userTransactions.forEach(async (userTransaction: dbUserTransaction, i: number) => {
|
|
const transaction = transactionIndiced[userTransaction.transactionId]
|
|
const finalTransaction = new Transaction()
|
|
finalTransaction.transactionId = transaction.id
|
|
finalTransaction.date = transaction.received.toString()
|
|
finalTransaction.memo = transaction.memo
|
|
finalTransaction.totalBalance = roundFloorFrom4(userTransaction.balance)
|
|
|
|
const prev = i > 0 ? userTransactions[i - 1] : null
|
|
if (prev && prev.balance > 0) {
|
|
const current = userTransaction
|
|
const decay = await calculateDecayWithInterval(
|
|
prev.balance,
|
|
prev.balanceDate,
|
|
current.balanceDate,
|
|
)
|
|
const balance = prev.balance - decay.balance
|
|
|
|
if (balance) {
|
|
finalTransaction.decay = decay
|
|
finalTransaction.decay.balance = roundFloorFrom4(finalTransaction.decay.balance)
|
|
finalTransaction.decay.balance = roundFloorFrom4(balance)
|
|
if (
|
|
decayStartTransaction &&
|
|
prev.transactionId < decayStartTransaction.id &&
|
|
current.transactionId > decayStartTransaction.id
|
|
) {
|
|
finalTransaction.decay.decayStartBlock = decayStartTransaction.received.getTime()
|
|
}
|
|
}
|
|
}
|
|
|
|
// sender or receiver when user has sended money
|
|
// group name if creation
|
|
// type: gesendet / empfangen / geschöpft
|
|
// transaktion nr / id
|
|
// date
|
|
// balance
|
|
if (userTransaction.transactionTypeId === 1) {
|
|
// creation
|
|
const creation = transaction.transactionCreation
|
|
|
|
finalTransaction.name = 'Gradido Akademie'
|
|
finalTransaction.type = 'creation'
|
|
// finalTransaction.targetDate = creation.targetDate
|
|
finalTransaction.balance = roundFloorFrom4(creation.amount)
|
|
} else if (userTransaction.transactionTypeId === 2) {
|
|
// send coin
|
|
const sendCoin = transaction.transactionSendCoin
|
|
let otherUser: dbUser | undefined
|
|
finalTransaction.balance = roundFloorFrom4(sendCoin.amount)
|
|
if (sendCoin.userId === user.id) {
|
|
finalTransaction.type = 'send'
|
|
otherUser = userIndiced[sendCoin.recipiantUserId]
|
|
// finalTransaction.pubkey = sendCoin.recipiantPublic
|
|
} else if (sendCoin.recipiantUserId === user.id) {
|
|
finalTransaction.type = 'receive'
|
|
otherUser = userIndiced[sendCoin.userId]
|
|
// finalTransaction.pubkey = sendCoin.senderPublic
|
|
} else {
|
|
throw new Error('invalid transaction')
|
|
}
|
|
if (otherUser) {
|
|
finalTransaction.name = otherUser.firstName + ' ' + otherUser.lastName
|
|
finalTransaction.email = otherUser.email
|
|
}
|
|
}
|
|
if (i > 0 || !skipFirstTransaction) {
|
|
finalTransactions.push(finalTransaction)
|
|
}
|
|
if (i === userTransactions.length - 1 && decay) {
|
|
const now = new Date()
|
|
const decay = await calculateDecayWithInterval(
|
|
userTransaction.balance,
|
|
userTransaction.balanceDate,
|
|
now.getTime(),
|
|
)
|
|
const balance = userTransaction.balance - decay.balance
|
|
if (balance) {
|
|
const decayTransaction = new Transaction()
|
|
decayTransaction.type = 'decay'
|
|
decayTransaction.balance = roundFloorFrom4(balance)
|
|
decayTransaction.decayDuration = decay.decayDuration
|
|
decayTransaction.decayStart = decay.decayStart
|
|
decayTransaction.decayEnd = decay.decayEnd
|
|
finalTransactions.push(decayTransaction)
|
|
}
|
|
}
|
|
return finalTransactions
|
|
})
|
|
|
|
return finalTransactions
|
|
}
|
|
|
|
export default async function listTransactions(
|
|
firstPage: number,
|
|
items: number,
|
|
order: 'ASC' | 'DESC',
|
|
user: dbUser,
|
|
): Promise<TransactionList> {
|
|
let limit = items
|
|
let offset = 0
|
|
let skipFirstTransaction = false
|
|
if (firstPage > 1) {
|
|
offset = (firstPage - 1) * items - 1
|
|
limit++
|
|
}
|
|
|
|
if (offset && order === 'ASC') {
|
|
offset--
|
|
}
|
|
let [userTransactions, userTransactionsCount] = await dbUserTransaction.findByUserPaged(
|
|
user.id,
|
|
limit,
|
|
offset,
|
|
order,
|
|
)
|
|
skipFirstTransaction = userTransactionsCount > offset + limit
|
|
const decay = !(firstPage > 1)
|
|
let transactions: Transaction[] = []
|
|
if (userTransactions.length) {
|
|
if (order === 'DESC') {
|
|
userTransactions = userTransactions.reverse()
|
|
}
|
|
transactions = await calculateAndAddDecayTransactions(
|
|
userTransactions,
|
|
user,
|
|
decay,
|
|
skipFirstTransaction,
|
|
)
|
|
if (order === 'DESC') {
|
|
transactions = transactions.reverse()
|
|
}
|
|
}
|
|
|
|
const transactionList = new TransactionList({
|
|
gdtSum: 0,
|
|
count: userTransactionsCount,
|
|
balance: 0,
|
|
decay: 0,
|
|
decay_date: '',
|
|
transactions: transactions,
|
|
})
|
|
|
|
return transactionList
|
|
}
|