mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
new graphql interface,
things build
This commit is contained in:
parent
dd8ddbad42
commit
97b4e16f40
@ -4,6 +4,8 @@ export enum TransactionTypeId {
|
||||
CREATION = 1,
|
||||
SEND = 2,
|
||||
RECEIVE = 3,
|
||||
// This is a virtual property, never occurring on the database
|
||||
DECAY = 4,
|
||||
}
|
||||
|
||||
registerEnumType(TransactionTypeId, {
|
||||
|
||||
@ -1,33 +1,36 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { ObjectType, Field, Int } from 'type-graphql'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class Decay {
|
||||
constructor(json?: any) {
|
||||
if (json) {
|
||||
this.balance = Number(json.balance)
|
||||
this.decayStart = json.decay_start
|
||||
this.decayEnd = json.decay_end
|
||||
this.decayDuration = json.decay_duration
|
||||
this.decayStartBlock = json.decay_start_block
|
||||
}
|
||||
constructor(
|
||||
balance: Decimal,
|
||||
decay: Decimal | null,
|
||||
start: Date | null,
|
||||
end: Date | null,
|
||||
duration: number | null,
|
||||
) {
|
||||
this.balance = balance
|
||||
this.decay = decay
|
||||
this.start = start
|
||||
this.end = end
|
||||
this.duration = duration
|
||||
}
|
||||
|
||||
@Field(() => Number)
|
||||
balance: number
|
||||
@Field(() => Decimal)
|
||||
balance: Decimal
|
||||
|
||||
// timestamp in seconds
|
||||
@Field(() => Int, { nullable: true })
|
||||
decayStart: string
|
||||
@Field(() => Decimal, { nullable: true })
|
||||
decay: Decimal | null
|
||||
|
||||
// timestamp in seconds
|
||||
@Field(() => Int, { nullable: true })
|
||||
decayEnd: string
|
||||
@Field(() => Date, { nullable: true })
|
||||
start: Date | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
decayDuration?: number
|
||||
@Field(() => Date, { nullable: true })
|
||||
end: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
decayStartBlock?: string
|
||||
@Field(() => Number, { nullable: true })
|
||||
duration: number | null
|
||||
}
|
||||
|
||||
@ -3,54 +3,70 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
import { Decay } from './Decay'
|
||||
|
||||
// we need a better solution for the decay block:
|
||||
// the first transaction on the first page shows the decay since the last transaction
|
||||
// the format is actually a Decay and not a Transaction.
|
||||
// Therefore we have a lot of nullable fields, which should be always present
|
||||
import { Transaction as dbTransaction } from '@entity/Transaction'
|
||||
import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
export class Transaction {
|
||||
constructor() {
|
||||
this.type = ''
|
||||
this.balance = new Decimal(0)
|
||||
this.totalBalance = new Decimal(0)
|
||||
this.memo = ''
|
||||
constructor(transaction: dbTransaction, user: User, linkedUser: User | null = null) {
|
||||
this.id = transaction.id
|
||||
this.user = user
|
||||
this.previous = transaction.previous
|
||||
this.typeId = transaction.typeId
|
||||
this.amount = transaction.amount
|
||||
this.balance = transaction.balance
|
||||
this.balanceDate = transaction.balanceDate
|
||||
if (!transaction.decayStart) {
|
||||
this.decay = new Decay(transaction.balance, null, null, null, null)
|
||||
} else {
|
||||
this.decay = new Decay(
|
||||
transaction.balance,
|
||||
transaction.decay,
|
||||
transaction.decayStart,
|
||||
transaction.balanceDate,
|
||||
(transaction.balanceDate.getTime() - transaction.decayStart.getTime()) / 1000,
|
||||
)
|
||||
}
|
||||
this.memo = transaction.memo
|
||||
this.creationDate = transaction.creationDate
|
||||
this.linkedUser = linkedUser
|
||||
this.linkedTransactionId = transaction.linkedTransactionId
|
||||
}
|
||||
|
||||
@Field(() => String)
|
||||
type: string
|
||||
@Field(() => Number)
|
||||
id: number
|
||||
|
||||
@Field(() => User)
|
||||
user: User
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
previous: number | null
|
||||
|
||||
@Field(() => TransactionTypeId)
|
||||
typeId: TransactionTypeId
|
||||
|
||||
@Field(() => Decimal)
|
||||
amount: Decimal
|
||||
|
||||
@Field(() => Decimal)
|
||||
balance: Decimal
|
||||
|
||||
@Field(() => Decimal)
|
||||
totalBalance: Decimal
|
||||
@Field(() => Date)
|
||||
balanceDate: Date
|
||||
|
||||
@Field({ nullable: true })
|
||||
decayStart?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
decayEnd?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
decayDuration?: number
|
||||
@Field(() => Decay)
|
||||
decay: Decay
|
||||
|
||||
@Field(() => String)
|
||||
memo: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
creationDate: Date | null
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
linkedUser: User | null
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
transactionId?: number
|
||||
|
||||
@Field({ nullable: true })
|
||||
name?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
email?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
date?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
decay?: Decay
|
||||
linkedTransactionId?: number | null
|
||||
}
|
||||
|
||||
@ -2,19 +2,27 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
import CONFIG from '../../config'
|
||||
import { Transaction } from './Transaction'
|
||||
|
||||
@ObjectType()
|
||||
export class TransactionList {
|
||||
constructor() {
|
||||
this.gdtSum = 0
|
||||
this.count = 0
|
||||
this.balance = new Decimal(0)
|
||||
this.decayStartBlock = null
|
||||
constructor(
|
||||
balance: Decimal,
|
||||
transactions: Transaction[],
|
||||
count: number,
|
||||
balanceGDT?: number | null,
|
||||
decayStartBlock: Date = CONFIG.DECAY_START_TIME,
|
||||
) {
|
||||
this.balance = balance
|
||||
this.transactions = transactions
|
||||
this.count = count
|
||||
this.balanceGDT = balanceGDT || null
|
||||
this.decayStartBlock = decayStartBlock
|
||||
}
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
gdtSum: number | null
|
||||
balanceGDT: number | null
|
||||
|
||||
@Field(() => Number)
|
||||
count: number
|
||||
@ -22,8 +30,8 @@ export class TransactionList {
|
||||
@Field(() => Number)
|
||||
balance: Decimal
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
decayStartBlock: Date | null
|
||||
@Field(() => Date)
|
||||
decayStartBlock: Date
|
||||
|
||||
@Field(() => [Transaction])
|
||||
transactions: Transaction[]
|
||||
|
||||
@ -1,75 +1,76 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { ObjectType, Field, Int } from 'type-graphql'
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
import { KlickTipp } from './KlickTipp'
|
||||
import { User as dbUser } from '@entity/User'
|
||||
|
||||
@ObjectType()
|
||||
export class User {
|
||||
/*
|
||||
@Field(() => ID)
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
*/
|
||||
constructor(json?: any) {
|
||||
if (json) {
|
||||
this.id = json.id
|
||||
this.email = json.email
|
||||
this.firstName = json.first_name
|
||||
this.lastName = json.last_name
|
||||
this.pubkey = json.public_hex
|
||||
this.language = json.language
|
||||
this.publisherId = json.publisher_id
|
||||
this.isAdmin = json.isAdmin
|
||||
}
|
||||
constructor(user: dbUser) {
|
||||
this.id = user.id
|
||||
this.email = user.email
|
||||
this.firstName = user.firstName
|
||||
this.lastName = user.lastName
|
||||
this.deletedAt = user.deletedAt
|
||||
this.createdAt = user.createdAt
|
||||
this.emailChecked = user.emailChecked
|
||||
this.language = user.language
|
||||
this.publisherId = user.publisherId
|
||||
// TODO
|
||||
this.isAdmin = null
|
||||
this.coinanimation = null
|
||||
this.klickTipp = null
|
||||
this.hasElopage = null
|
||||
}
|
||||
|
||||
@Field(() => Number)
|
||||
id: number
|
||||
|
||||
// `public_key` binary(32) DEFAULT NULL,
|
||||
// `privkey` binary(80) DEFAULT NULL,
|
||||
|
||||
// TODO privacy issue here
|
||||
@Field(() => String)
|
||||
email: string
|
||||
|
||||
@Field(() => String)
|
||||
firstName: string
|
||||
@Field(() => String, { nullable: true })
|
||||
firstName: string | null
|
||||
|
||||
@Field(() => String)
|
||||
lastName: string
|
||||
@Field(() => String, { nullable: true })
|
||||
lastName: string | null
|
||||
|
||||
@Field(() => String)
|
||||
pubkey: string
|
||||
/*
|
||||
@Field(() => String)
|
||||
pubkey: string
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt: Date | null
|
||||
|
||||
// not sure about the type here. Maybe better to have a string
|
||||
@Field(() => number)
|
||||
created: number
|
||||
// `password` bigint(20) unsigned DEFAULT 0,
|
||||
// `email_hash` binary(32) DEFAULT NULL,
|
||||
|
||||
@Field(() =>>> Boolean)
|
||||
@Field(() => Date)
|
||||
createdAt: Date
|
||||
|
||||
@Field(() => Boolean)
|
||||
emailChecked: boolean
|
||||
*/
|
||||
|
||||
@Field(() => String)
|
||||
language: string
|
||||
|
||||
/*
|
||||
@Field(() => Boolean)
|
||||
disabled: boolean
|
||||
*/
|
||||
// This is not the users publisherId, but the one of the users who recommend him
|
||||
@Field(() => Number, { nullable: true })
|
||||
publisherId: number | null
|
||||
|
||||
// what is publisherId?
|
||||
@Field(() => Int, { nullable: true })
|
||||
publisherId?: number
|
||||
// `passphrase` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
|
||||
@Field(() => Boolean)
|
||||
isAdmin: boolean
|
||||
|
||||
@Field(() => Boolean)
|
||||
coinanimation: boolean
|
||||
|
||||
@Field(() => KlickTipp)
|
||||
klickTipp: KlickTipp
|
||||
// TODO this is a bit inconsistent with what we query from the database
|
||||
// therefore all those fields are now nullable with default value null
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
isAdmin: boolean | null
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
hasElopage?: boolean
|
||||
coinanimation: boolean | null
|
||||
|
||||
@Field(() => KlickTipp, { nullable: true })
|
||||
klickTipp: KlickTipp | null
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
hasElopage: boolean | null
|
||||
}
|
||||
|
||||
@ -20,15 +20,17 @@ import { Order } from '../enum/Order'
|
||||
import { UserRepository } from '../../typeorm/repository/User'
|
||||
import { TransactionRepository } from '../../typeorm/repository/Transaction'
|
||||
|
||||
import { User as dbUser, User } from '@entity/User'
|
||||
import { User as dbUser } from '@entity/User'
|
||||
import { Transaction as dbTransaction } from '@entity/Transaction'
|
||||
|
||||
import { apiPost } from '../../apis/HttpRequest'
|
||||
import { calculateDecay } from '../../util/decay'
|
||||
import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
import { TransactionType } from '../enum/TransactionType'
|
||||
import { calculateBalance, isHexPublicKey } from '../../util/validate'
|
||||
import { RIGHTS } from '../../auth/RIGHTS'
|
||||
import { User } from '../model/User'
|
||||
import { communityUser } from '../../util/communityUser'
|
||||
import { virtualDecayTransaction } from '../../util/virtualDecayTransaction'
|
||||
|
||||
@Resolver()
|
||||
export class TransactionResolver {
|
||||
@ -87,88 +89,57 @@ export class TransactionResolver {
|
||||
// remove duplicates
|
||||
involvedUserIds = involvedUserIds.filter((value, index, self) => self.indexOf(value) === index)
|
||||
// We need to show the name for deleted users for old transactions
|
||||
const involvedUsers = await User.createQueryBuilder()
|
||||
const involvedDbUsers = await dbUser
|
||||
.createQueryBuilder()
|
||||
.withDeleted()
|
||||
.where('user.id IN (:...userIds)', { involvedUserIds })
|
||||
.getMany()
|
||||
const involvedUsers = involvedDbUsers.map((u) => new User(u))
|
||||
|
||||
const self = new User(user)
|
||||
const transactions: Transaction[] = []
|
||||
|
||||
// decay transaction
|
||||
if (currentPage === 1 && order === Order.DESC) {
|
||||
const now = new Date()
|
||||
const decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, now)
|
||||
const balance = decay.balance.minus(lastTransaction.balance)
|
||||
|
||||
const decayTransaction = new Transaction()
|
||||
decayTransaction.type = 'decay'
|
||||
decayTransaction.balance = balance
|
||||
// TODO
|
||||
// decayTransaction.decayDuration = decay.duration
|
||||
// decayTransaction.decayStart = decay.start
|
||||
// decayTransaction.decayEnd = decay.end
|
||||
transactions.push(decayTransaction)
|
||||
transactions.push(
|
||||
virtualDecayTransaction(lastTransaction.balance, lastTransaction.balanceDate, now, self),
|
||||
)
|
||||
}
|
||||
|
||||
if (userTransactions.length) {
|
||||
for (let i = 0; i < userTransactions.length; i++) {
|
||||
const userTransaction = userTransactions[i]
|
||||
const finalTransaction = new Transaction()
|
||||
finalTransaction.transactionId = userTransaction.id
|
||||
finalTransaction.date = userTransaction.balanceDate.toISOString()
|
||||
finalTransaction.memo = userTransaction.memo
|
||||
finalTransaction.totalBalance = userTransaction.balance
|
||||
finalTransaction.balance = userTransaction.amount
|
||||
|
||||
const otherUser = involvedUsers.find((u) => u.id === userTransaction.linkedUserId)
|
||||
switch (userTransaction.typeId) {
|
||||
case TransactionTypeId.CREATION:
|
||||
finalTransaction.name = 'Gradido Akademie'
|
||||
finalTransaction.type = TransactionType.CREATION
|
||||
break
|
||||
case TransactionTypeId.SEND:
|
||||
finalTransaction.type = TransactionType.SEND
|
||||
if (otherUser) {
|
||||
finalTransaction.name = otherUser.firstName + ' ' + otherUser.lastName
|
||||
finalTransaction.email = otherUser.email
|
||||
}
|
||||
break
|
||||
case TransactionTypeId.RECEIVE:
|
||||
finalTransaction.type = TransactionType.RECIEVE
|
||||
if (otherUser) {
|
||||
finalTransaction.name = otherUser.firstName + ' ' + otherUser.lastName
|
||||
finalTransaction.email = otherUser.email
|
||||
}
|
||||
break
|
||||
default:
|
||||
throw new Error('invalid transaction')
|
||||
}
|
||||
transactions.push(finalTransaction)
|
||||
for (let i = 0; i < userTransactions.length; i++) {
|
||||
const userTransaction = userTransactions[i]
|
||||
let linkedUser = null
|
||||
if (userTransaction.typeId === TransactionTypeId.CREATION) {
|
||||
linkedUser = communityUser
|
||||
} else {
|
||||
linkedUser = involvedUsers.find((u) => u.id === userTransaction.linkedUserId)
|
||||
}
|
||||
transactions.push(new Transaction(userTransaction, self, linkedUser))
|
||||
}
|
||||
|
||||
const transactionList = new TransactionList()
|
||||
transactionList.count = userTransactionsCount
|
||||
transactionList.transactions = transactions
|
||||
|
||||
// get gdt sum
|
||||
transactionList.gdtSum = null
|
||||
// get GDT
|
||||
let balanceGDT = null
|
||||
try {
|
||||
const resultGDTSum = await apiPost(`${CONFIG.GDT_API_URL}/GdtEntries/sumPerEmailApi`, {
|
||||
email: user.email,
|
||||
})
|
||||
if (resultGDTSum.success) transactionList.gdtSum = Number(resultGDTSum.data.sum) || 0
|
||||
} catch (err: any) {}
|
||||
if (!resultGDTSum.success) {
|
||||
throw new Error('Call not successful')
|
||||
}
|
||||
balanceGDT = Number(resultGDTSum.data.sum) || 0
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Could not query GDT Server', err)
|
||||
}
|
||||
|
||||
// get balance
|
||||
transactionList.balance = lastTransaction.balance
|
||||
transactionList.decayStartBlock = CONFIG.DECAY_START_TIME
|
||||
// const now = new Date()
|
||||
// TODO this seems duplicated
|
||||
// transactionList.decay = calculateDecay(lastTransaction.balance, lastTransaction.balanceDate, now)
|
||||
// transactionList.decayDate = now.toString()
|
||||
|
||||
return transactionList
|
||||
// Construct Result
|
||||
return new TransactionList(
|
||||
lastTransaction.balance,
|
||||
transactions,
|
||||
userTransactionsCount,
|
||||
balanceGDT,
|
||||
)
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.SEND_COINS])
|
||||
|
||||
@ -216,14 +216,8 @@ export class UserResolver {
|
||||
// TODO refactor and do not have duplicate code with login(see below)
|
||||
const userRepository = getCustomRepository(UserRepository)
|
||||
const userEntity = await userRepository.findByPubkeyHex(context.pubKey)
|
||||
const user = new User()
|
||||
user.id = userEntity.id
|
||||
user.email = userEntity.email
|
||||
user.firstName = userEntity.firstName
|
||||
user.lastName = userEntity.lastName
|
||||
user.pubkey = userEntity.pubKey.toString('hex')
|
||||
user.language = userEntity.language
|
||||
|
||||
const user = new User(userEntity)
|
||||
// user.pubkey = userEntity.pubKey.toString('hex')
|
||||
// Elopage Status & Stored PublisherId
|
||||
user.hasElopage = await this.hasElopage(context)
|
||||
|
||||
@ -271,12 +265,9 @@ export class UserResolver {
|
||||
throw new Error('No user with this credentials')
|
||||
}
|
||||
|
||||
const user = new User()
|
||||
user.id = dbUser.id
|
||||
user.email = email
|
||||
user.firstName = dbUser.firstName
|
||||
user.lastName = dbUser.lastName
|
||||
user.pubkey = dbUser.pubKey.toString('hex')
|
||||
const user = new User(dbUser)
|
||||
// user.email = email
|
||||
// user.pubkey = dbUser.pubKey.toString('hex')
|
||||
user.language = dbUser.language
|
||||
|
||||
// Elopage Status & Stored PublisherId
|
||||
|
||||
44
backend/src/util/communityUser.ts
Normal file
44
backend/src/util/communityUser.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
import { SaveOptions, RemoveOptions } from '@dbTools/typeorm'
|
||||
import { User as dbUser } from '@entity/User'
|
||||
import { User } from '../graphql/model/User'
|
||||
|
||||
const communityDbUser: dbUser = {
|
||||
id: -1,
|
||||
email: 'support@gradido.net',
|
||||
firstName: 'Gradido',
|
||||
lastName: 'Akademie',
|
||||
pubKey: Buffer.from(''),
|
||||
privKey: Buffer.from(''),
|
||||
deletedAt: null,
|
||||
password: BigInt(0),
|
||||
emailHash: Buffer.from(''),
|
||||
createdAt: new Date(),
|
||||
emailChecked: false,
|
||||
language: '',
|
||||
publisherId: 0,
|
||||
passphrase: '',
|
||||
settings: [],
|
||||
hasId: function (): boolean {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
save: function (options?: SaveOptions): Promise<dbUser> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
remove: function (options?: RemoveOptions): Promise<dbUser> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
softRemove: function (options?: SaveOptions): Promise<dbUser> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
recover: function (options?: SaveOptions): Promise<dbUser> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
reload: function (): Promise<void> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
}
|
||||
const communityUser = new User(communityDbUser)
|
||||
|
||||
export { communityDbUser, communityUser }
|
||||
@ -1,14 +1,8 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import CONFIG from '../config'
|
||||
import { Decay } from '../graphql/model/Decay'
|
||||
|
||||
// TODO: externalize all those definitions and functions into an external decay library
|
||||
interface Decay {
|
||||
balance: Decimal
|
||||
decay: Decimal | null
|
||||
start: Date | null
|
||||
end: Date | null
|
||||
duration: number | null
|
||||
}
|
||||
|
||||
function decayFormula(value: Decimal, seconds: number): Decimal {
|
||||
return value.mul(new Decimal('0.99999997803504048973201202316767079413460520837376').pow(seconds))
|
||||
|
||||
52
backend/src/util/virtualDecayTransaction.ts
Normal file
52
backend/src/util/virtualDecayTransaction.ts
Normal file
@ -0,0 +1,52 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { SaveOptions, RemoveOptions } from '@dbTools/typeorm'
|
||||
import { Transaction as dbTransaction } from '@entity/Transaction'
|
||||
import { calculateDecay } from './decay'
|
||||
import { TransactionTypeId } from '../graphql/enum/TransactionTypeId'
|
||||
import { Transaction } from '../graphql/model/Transaction'
|
||||
import { User } from '../graphql/model/User'
|
||||
|
||||
const virtualDecayTransaction = (
|
||||
balance: Decimal,
|
||||
balanceDate: Date,
|
||||
time: Date = new Date(),
|
||||
user: User,
|
||||
): Transaction => {
|
||||
const decay = calculateDecay(balance, balanceDate, time)
|
||||
// const balance = decay.balance.minus(lastTransaction.balance)
|
||||
const decayDbTransaction: dbTransaction = {
|
||||
id: -1,
|
||||
userId: -1,
|
||||
previous: -1,
|
||||
typeId: TransactionTypeId.DECAY,
|
||||
amount: new Decimal(0),
|
||||
balance: decay.balance,
|
||||
balanceDate: time,
|
||||
decay: decay.decay ? decay.decay : new Decimal(0),
|
||||
decayStart: decay.start,
|
||||
memo: '',
|
||||
creationDate: null,
|
||||
hasId: function (): boolean {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
save: function (options?: SaveOptions): Promise<dbTransaction> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
remove: function (options?: RemoveOptions): Promise<dbTransaction> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
softRemove: function (options?: SaveOptions): Promise<dbTransaction> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
recover: function (options?: SaveOptions): Promise<dbTransaction> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
reload: function (): Promise<void> {
|
||||
throw new Error('Function not implemented.')
|
||||
},
|
||||
}
|
||||
return new Transaction(decayDbTransaction, user)
|
||||
}
|
||||
|
||||
export { virtualDecayTransaction }
|
||||
Loading…
x
Reference in New Issue
Block a user