Merge branch 'master' into 2392-refactor-more-emails-to-translatables

This commit is contained in:
Ulf Gebhardt 2022-12-09 12:59:59 +01:00 committed by GitHub
commit 486777cb35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 90 additions and 45 deletions

View File

@ -42,7 +42,9 @@ export class Transaction {
this.creationDate = transaction.creationDate this.creationDate = transaction.creationDate
this.linkedUser = linkedUser this.linkedUser = linkedUser
this.linkedTransactionId = transaction.linkedTransactionId this.linkedTransactionId = transaction.linkedTransactionId
this.transactionLinkId = transaction.transactionLinkId this.linkId = transaction.contribution
? transaction.contribution.contributionLinkId
: transaction.transactionLinkId
} }
@Field(() => Number) @Field(() => Number)
@ -81,7 +83,7 @@ export class Transaction {
@Field(() => Number, { nullable: true }) @Field(() => Number, { nullable: true })
linkedTransactionId?: number | null linkedTransactionId?: number | null
// Links to the TransactionLink when transaction was created by a link // Links to the TransactionLink/ContributionLink when transaction was created by a link
@Field(() => Number, { nullable: true }) @Field(() => Number, { nullable: true })
transactionLinkId?: number | null linkId?: number | null
} }

View File

@ -368,6 +368,19 @@ describe('AdminResolver', () => {
expect(new Date(result.data.deleteUser)).toEqual(expect.any(Date)) expect(new Date(result.data.deleteUser)).toEqual(expect.any(Date))
}) })
it('has deleted_at set in users and user contacts', async () => {
await expect(
User.findOneOrFail({
where: { id: user.id },
withDeleted: true,
relations: ['emailContact'],
}),
).resolves.toMatchObject({
deletedAt: expect.any(Date),
emailContact: expect.objectContaining({ deletedAt: expect.any(Date) }),
})
})
describe('delete deleted user', () => { describe('delete deleted user', () => {
it('throws an error', async () => { it('throws an error', async () => {
jest.clearAllMocks() jest.clearAllMocks()
@ -491,6 +504,15 @@ describe('AdminResolver', () => {
}), }),
) )
}) })
it('has deleted_at set to null in users and user contacts', async () => {
await expect(
User.findOneOrFail({ where: { id: user.id }, relations: ['emailContact'] }),
).resolves.toMatchObject({
deletedAt: null,
emailContact: expect.objectContaining({ deletedAt: null }),
})
})
}) })
}) })
}) })

View File

@ -203,7 +203,7 @@ export class AdminResolver {
@Arg('userId', () => Int) userId: number, @Arg('userId', () => Int) userId: number,
@Ctx() context: Context, @Ctx() context: Context,
): Promise<Date | null> { ): Promise<Date | null> {
const user = await dbUser.findOne({ id: userId }) const user = await dbUser.findOne({ where: { id: userId }, relations: ['emailContact'] })
// user exists ? // user exists ?
if (!user) { if (!user) {
logger.error(`Could not find user with userId: ${userId}`) logger.error(`Could not find user with userId: ${userId}`)
@ -217,6 +217,7 @@ export class AdminResolver {
} }
// soft-delete user // soft-delete user
await user.softRemove() await user.softRemove()
await user.emailContact.softRemove()
const newUser = await dbUser.findOne({ id: userId }, { withDeleted: true }) const newUser = await dbUser.findOne({ id: userId }, { withDeleted: true })
return newUser ? newUser.deletedAt : null return newUser ? newUser.deletedAt : null
} }
@ -224,7 +225,10 @@ export class AdminResolver {
@Authorized([RIGHTS.UNDELETE_USER]) @Authorized([RIGHTS.UNDELETE_USER])
@Mutation(() => Date, { nullable: true }) @Mutation(() => Date, { nullable: true })
async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise<Date | null> { async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise<Date | null> {
const user = await dbUser.findOne({ id: userId }, { withDeleted: true }) const user = await dbUser.findOne(
{ id: userId },
{ withDeleted: true, relations: ['emailContact'] },
)
if (!user) { if (!user) {
logger.error(`Could not find user with userId: ${userId}`) logger.error(`Could not find user with userId: ${userId}`)
throw new Error(`Could not find user with userId: ${userId}`) throw new Error(`Could not find user with userId: ${userId}`)
@ -234,6 +238,7 @@ export class AdminResolver {
throw new Error('User is not deleted') throw new Error('User is not deleted')
} }
await user.recover() await user.recover()
await user.emailContact.recover()
return null return null
} }

View File

@ -204,7 +204,7 @@ export class TransactionResolver {
// find current balance // find current balance
const lastTransaction = await dbTransaction.findOne( const lastTransaction = await dbTransaction.findOne(
{ userId: user.id }, { userId: user.id },
{ order: { balanceDate: 'DESC' } }, { order: { balanceDate: 'DESC' }, relations: ['contribution'] },
) )
logger.debug(`lastTransaction=${lastTransaction}`) logger.debug(`lastTransaction=${lastTransaction}`)
@ -326,7 +326,6 @@ export class TransactionResolver {
// validate recipient user // validate recipient user
const recipientUser = await findUserByEmail(email) const recipientUser = await findUserByEmail(email)
if (recipientUser.deletedAt) { if (recipientUser.deletedAt) {
logger.error(`The recipient account was deleted: recipientUser=${recipientUser}`) logger.error(`The recipient account was deleted: recipientUser=${recipientUser}`)
throw new Error('The recipient account was deleted') throw new Error('The recipient account was deleted')

View File

@ -12,29 +12,24 @@ export class TransactionRepository extends Repository<Transaction> {
order: Order, order: Order,
onlyCreation?: boolean, onlyCreation?: boolean,
): Promise<[Transaction[], number]> { ): Promise<[Transaction[], number]> {
if (onlyCreation) { const query = this.createQueryBuilder('userTransaction')
return this.createQueryBuilder('userTransaction') .leftJoinAndSelect(
'userTransaction.contribution',
'contribution',
'userTransaction.id = contribution.transactionId',
)
.where('userTransaction.userId = :userId', { userId }) .where('userTransaction.userId = :userId', { userId })
.andWhere('userTransaction.typeId = :typeId', {
if (onlyCreation) {
query.andWhere('userTransaction.typeId = :typeId', {
typeId: TransactionTypeId.CREATION, typeId: TransactionTypeId.CREATION,
}) })
.orderBy('userTransaction.balanceDate', order)
.limit(limit)
.offset(offset)
.getManyAndCount()
}
return this.createQueryBuilder('userTransaction')
.where('userTransaction.userId = :userId', { userId })
.orderBy('userTransaction.balanceDate', order)
.limit(limit)
.offset(offset)
.getManyAndCount()
} }
findLastForUser(userId: number): Promise<Transaction | undefined> { return query
return this.createQueryBuilder('userTransaction') .orderBy('userTransaction.balanceDate', order)
.where('userTransaction.userId = :userId', { userId }) .limit(limit)
.orderBy('userTransaction.balanceDate', 'DESC') .offset(offset)
.getOne() .getManyAndCount()
} }
} }

View File

@ -49,6 +49,7 @@ const virtualLinkTransaction = (
decay: decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), decay: decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR),
memo: '', memo: '',
creationDate: null, creationDate: null,
contribution: null,
...defaultModelFunctions, ...defaultModelFunctions,
} }
return new Transaction(linkDbTransaction, user) return new Transaction(linkDbTransaction, user)
@ -78,6 +79,7 @@ const virtualDecayTransaction = (
decayStart: decay.start, decayStart: decay.start,
memo: '', memo: '',
creationDate: null, creationDate: null,
contribution: null,
...defaultModelFunctions, ...defaultModelFunctions,
} }
return new Transaction(decayDbTransaction, user) return new Transaction(decayDbTransaction, user)

View File

@ -1,6 +1,7 @@
import Decimal from 'decimal.js-light' import Decimal from 'decimal.js-light'
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm' import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
import { Contribution } from '../Contribution'
@Entity('transactions') @Entity('transactions')
export class Transaction extends BaseEntity { export class Transaction extends BaseEntity {
@ -91,4 +92,8 @@ export class Transaction extends BaseEntity {
default: null, default: null,
}) })
transactionLinkId?: number | null transactionLinkId?: number | null
@OneToOne(() => Contribution, (contribution) => contribution.transaction)
@JoinColumn({ name: 'id', referencedColumnName: 'transactionId' })
contribution?: Contribution | null
} }

View File

@ -8,10 +8,12 @@ import {
JoinColumn, JoinColumn,
ManyToOne, ManyToOne,
OneToMany, OneToMany,
OneToOne,
} from 'typeorm' } from 'typeorm'
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
import { User } from '../User' import { User } from '../User'
import { ContributionMessage } from '../ContributionMessage' import { ContributionMessage } from '../ContributionMessage'
import { Transaction } from '../Transaction'
@Entity('contributions') @Entity('contributions')
export class Contribution extends BaseEntity { export class Contribution extends BaseEntity {
@ -92,4 +94,8 @@ export class Contribution extends BaseEntity {
@OneToMany(() => ContributionMessage, (message) => message.contribution) @OneToMany(() => ContributionMessage, (message) => message.contribution)
@JoinColumn({ name: 'contribution_id' }) @JoinColumn({ name: 'contribution_id' })
messages?: ContributionMessage[] messages?: ContributionMessage[]
@OneToOne(() => Transaction, (transaction) => transaction.contribution)
@JoinColumn({ name: 'transaction_id' })
transaction?: Transaction | null
} }

View File

@ -10,11 +10,13 @@
</b-col> </b-col>
<b-col cols="7"> <b-col cols="7">
<div class="gdd-transaction-list-item-name"> <div class="gdd-transaction-list-item-name">
<div v-if="linkedUser && linkedUser.email"> <span v-if="linkedUser && linkedUser.email">
<b-link @click.stop="tunnelEmail"> <b-link @click.stop="tunnelEmail">
{{ itemText }} {{ itemText }}
</b-link> </b-link>
<span v-if="transactionLinkId"> </span>
<span v-else>{{ itemText }}</span>
<span v-if="linkId">
{{ $t('via_link') }} {{ $t('via_link') }}
<b-icon <b-icon
icon="link45deg" icon="link45deg"
@ -24,8 +26,6 @@
/> />
</span> </span>
</div> </div>
<span v-else>{{ itemText }}</span>
</div>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
@ -46,7 +46,7 @@ export default {
type: String, type: String,
required: false, required: false,
}, },
transactionLinkId: { linkId: {
type: Number, type: Number,
required: false, required: false,
default: null, default: null,

View File

@ -12,7 +12,12 @@
<b-col cols="11"> <b-col cols="11">
<!-- Amount / Name || Text --> <!-- Amount / Name || Text -->
<amount-and-name-row :amount="amount" :linkedUser="linkedUser" v-on="$listeners" /> <amount-and-name-row
:amount="amount"
:linkedUser="linkedUser"
v-on="$listeners"
:linkId="linkId"
/>
<!-- Nachricht Memo --> <!-- Nachricht Memo -->
<memo-row :memo="memo" /> <memo-row :memo="memo" />
@ -77,6 +82,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
linkId: {
type: Number,
required: false,
},
previousBookedBalance: { previousBookedBalance: {
type: String, type: String,
required: true, required: true,

View File

@ -17,7 +17,7 @@
v-on="$listeners" v-on="$listeners"
:amount="amount" :amount="amount"
:linkedUser="linkedUser" :linkedUser="linkedUser"
:transactionLinkId="transactionLinkId" :linkId="linkId"
/> />
<!-- Nachricht Memo --> <!-- Nachricht Memo -->
@ -82,7 +82,7 @@ export default {
typeId: { typeId: {
type: String, type: String,
}, },
transactionLinkId: { linkId: {
type: Number, type: Number,
required: false, required: false,
}, },

View File

@ -17,7 +17,7 @@
v-on="$listeners" v-on="$listeners"
:amount="amount" :amount="amount"
:linkedUser="linkedUser" :linkedUser="linkedUser"
:transactionLinkId="transactionLinkId" :linkId="linkId"
/> />
<!-- Memo --> <!-- Memo -->
@ -83,7 +83,7 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
transactionLinkId: { linkId: {
type: Number, type: Number,
required: false, required: false,
}, },

View File

@ -45,7 +45,7 @@ export const transactionsQuery = gql`
end end
duration duration
} }
transactionLinkId linkId
} }
} }
} }