Merge pull request #1203 from gradido/adminCreateMultiplePendingCreations

Admin create multiple pending creations
This commit is contained in:
Hannes Heine 2022-01-04 02:37:45 +01:00 committed by GitHub
commit 0e203a313f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 143 additions and 37 deletions

View File

@ -99,7 +99,10 @@ describe('CreationFormular', () => {
describe('with mass creation', () => { describe('with mass creation', () => {
beforeEach(async () => { beforeEach(async () => {
jest.clearAllMocks() jest.clearAllMocks()
await wrapper.setProps({ type: 'massCreation' }) await wrapper.setProps({ type: 'massCreation', creation: [200, 400, 600] })
await wrapper.setData({ rangeMin: 180 })
await wrapper.setData({ text: 'Test create coins' })
await wrapper.setData({ value: 90 })
}) })
describe('first radio button', () => { describe('first radio button', () => {

View File

@ -123,6 +123,7 @@
<script> <script>
import { verifyLogin } from '../graphql/verifyLogin' import { verifyLogin } from '../graphql/verifyLogin'
import { createPendingCreation } from '../graphql/createPendingCreation' import { createPendingCreation } from '../graphql/createPendingCreation'
import { createPendingCreations } from '../graphql/createPendingCreations'
export default { export default {
name: 'CreationFormular', name: 'CreationFormular',
props: { props: {
@ -207,24 +208,45 @@ export default {
submitCreation() { submitCreation() {
if (this.type === 'massCreation') { if (this.type === 'massCreation') {
// Die anzahl der Mitglieder aus der Mehrfachschöpfung // Die anzahl der Mitglieder aus der Mehrfachschöpfung
const i = Object.keys(this.itemsMassCreation).length const i = Object.keys(this.items).length
// hinweis das eine Mehrfachschöpfung ausgeführt wird an (Anzahl der MItgleider an die geschöpft wird) // hinweis das eine Mehrfachschöpfung ausgeführt wird an (Anzahl der MItgleider an die geschöpft wird)
this.submitObj = [ // eslint-disable-next-line no-console
{ console.log('SUBMIT CREATION => ' + this.type + ' >> für VIELE ' + i + ' Mitglieder')
item: this.itemsMassCreation, this.submitObj = []
email: this.item.email, this.items.forEach((item) => {
this.submitObj.push({
email: item.email,
creationDate: this.radioSelected.long, creationDate: this.radioSelected.long,
amount: this.value, amount: Number(this.value),
memo: this.text, memo: this.text,
moderator: this.$store.state.moderator.id, moderator: Number(this.$store.state.moderator.id),
})
})
// eslint-disable-next-line no-console
console.log('MehrfachSCHÖPFUNG ABSENDEN FÜR >> ' + i + ' Mitglieder')
this.$apollo
.mutate({
mutation: createPendingCreations,
variables: {
pendingCreations: this.submitObj,
}, },
] fetchPolicy: 'no-cache',
})
// $store - offene Schöpfungen hochzählen .then((result) => {
this.$store.commit('openCreationsPlus', i) this.$store.commit(
'openCreationsPlus',
// lösche alle Mitglieder aus der MehrfachSchöpfungsListe nach dem alle Mehrfachschpfungen zum bestätigen gesendet wurden. result.data.createPendingCreations.successfulCreation.length,
)
if (result.data.createPendingCreations.failedCreation.length > 0) {
result.data.createPendingCreations.failedCreation.forEach((failed) => {
this.$toasted.error('Could not created PendingCreation for ' + failed)
})
}
this.$emit('remove-all-bookmark') this.$emit('remove-all-bookmark')
})
.catch((error) => {
this.$toasted.error(error.message)
})
} else if (this.type === 'singleCreation') { } else if (this.type === 'singleCreation') {
this.submitObj = { this.submitObj = {
email: this.item.email, email: this.item.email,

View File

@ -16,6 +16,7 @@ const apolloMutateMock = jest.fn().mockResolvedValue({
const stateCommitMock = jest.fn() const stateCommitMock = jest.fn()
const toastedErrorMock = jest.fn() const toastedErrorMock = jest.fn()
const toastedSuccessMock = jest.fn()
const mocks = { const mocks = {
$t: jest.fn((t) => t), $t: jest.fn((t) => t),
@ -43,6 +44,7 @@ const mocks = {
}, },
$toasted: { $toasted: {
error: toastedErrorMock, error: toastedErrorMock,
success: toastedSuccessMock,
}, },
} }
@ -53,6 +55,10 @@ const propsData = {
amount: 100, amount: 100,
date: '2021-12-01', date: '2021-12-01',
}, },
item: {
id: 0,
email: 'bob@baumeister.de',
},
} }
describe('EditCreationFormular', () => { describe('EditCreationFormular', () => {
@ -109,8 +115,8 @@ describe('EditCreationFormular', () => {
variables: { variables: {
amount: 90, amount: 90,
creationDate: 'YYYY-MM-01', creationDate: 'YYYY-MM-01',
email: undefined, email: 'bob@baumeister.de',
id: undefined, id: 0,
memo: 'Test create coins', memo: 'Test create coins',
moderator: 0, moderator: 0,
}, },
@ -118,6 +124,23 @@ describe('EditCreationFormular', () => {
) )
}) })
it('emits update-user-data', () => {
expect(wrapper.emitted('update-user-data')).toBeTruthy()
expect(wrapper.emitted('update-user-data')).toEqual([
[
{
id: 0,
email: 'bob@baumeister.de',
},
[0, 0, 0],
],
])
})
it('toast success message', () => {
expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_update')
})
describe('sendForm with error', () => { describe('sendForm with error', () => {
beforeEach(async () => { beforeEach(async () => {
jest.clearAllMocks() jest.clearAllMocks()
@ -164,8 +187,8 @@ describe('EditCreationFormular', () => {
variables: { variables: {
amount: 90, amount: 90,
creationDate: 'YYYY-MM-01', creationDate: 'YYYY-MM-01',
email: undefined, email: 'bob@baumeister.de',
id: undefined, id: 0,
memo: 'Test create coins', memo: 'Test create coins',
moderator: 0, moderator: 0,
}, },
@ -220,8 +243,8 @@ describe('EditCreationFormular', () => {
variables: { variables: {
amount: 90, amount: 90,
creationDate: 'YYYY-MM-DD', creationDate: 'YYYY-MM-DD',
email: undefined, email: 'bob@baumeister.de',
id: undefined, id: 0,
memo: 'Test create coins', memo: 'Test create coins',
moderator: 0, moderator: 0,
}, },

View File

@ -129,10 +129,7 @@ export default {
props: { props: {
item: { item: {
type: Object, type: Object,
required: false, required: true,
default() {
return {}
},
}, },
row: { row: {
type: Object, type: Object,
@ -143,10 +140,7 @@ export default {
}, },
creationUserData: { creationUserData: {
type: Object, type: Object,
required: false, required: true,
default() {
return {}
},
}, },
creation: { creation: {
type: Array, type: Array,

View File

@ -0,0 +1,11 @@
import gql from 'graphql-tag'
export const createPendingCreations = gql`
mutation ($pendingCreations: [CreatePendingCreationArgs!]!) {
createPendingCreations(pendingCreations: $pendingCreations) {
success
successfulCreation
failedCreation
}
}
`

View File

@ -21,4 +21,9 @@ export enum RIGHTS {
HAS_ELOPAGE = 'HAS_ELOPAGE', HAS_ELOPAGE = 'HAS_ELOPAGE',
// Admin // Admin
SEARCH_USERS = 'SEARCH_USERS', SEARCH_USERS = 'SEARCH_USERS',
CREATE_PENDING_CREATION = 'CREATE_PENDING_CREATION',
UPDATE_PENDING_CREATION = 'UPDATE_PENDING_CREATION',
SEARCH_PENDING_CREATION = 'SEARCH_PENDING_CREATION',
DELETE_PENDING_CREATION = 'DELETE_PENDING_CREATION',
CONFIRM_PENDING_CREATION = 'CONFIRM_PENDING_CREATION',
} }

View File

@ -1,5 +1,6 @@
import { ArgsType, Field, Float, Int } from 'type-graphql' import { ArgsType, Field, Float, InputType, Int } from 'type-graphql'
@InputType()
@ArgsType() @ArgsType()
export default class CreatePendingCreationArgs { export default class CreatePendingCreationArgs {
@Field(() => String) @Field(() => String)

View File

@ -1,7 +1,7 @@
import { ArgsType, Field, Float, Int } from 'type-graphql' import { ArgsType, Field, Float, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class CreatePendingCreationArgs { export default class UpdatePendingCreationArgs {
@Field(() => Int) @Field(() => Int)
id: number id: number

View File

@ -0,0 +1,19 @@
import { ObjectType, Field } from 'type-graphql'
@ObjectType()
export class CreatePendingCreations {
constructor() {
this.success = false
this.successfulCreation = []
this.failedCreation = []
}
@Field(() => Boolean)
success: boolean
@Field(() => [String])
successfulCreation: string[]
@Field(() => [String])
failedCreation: string[]
}

View File

@ -2,6 +2,7 @@ import { Resolver, Query, Arg, Args, Authorized, Mutation, Ctx } from 'type-grap
import { getCustomRepository, Raw } from 'typeorm' import { getCustomRepository, Raw } from 'typeorm'
import { UserAdmin } from '../model/UserAdmin' import { UserAdmin } from '../model/UserAdmin'
import { PendingCreation } from '../model/PendingCreation' import { PendingCreation } from '../model/PendingCreation'
import { CreatePendingCreations } from '../model/CreatePendingCreations'
import { UpdatePendingCreation } from '../model/UpdatePendingCreation' import { UpdatePendingCreation } from '../model/UpdatePendingCreation'
import { RIGHTS } from '../../auth/RIGHTS' import { RIGHTS } from '../../auth/RIGHTS'
import { TransactionRepository } from '../../typeorm/repository/Transaction' import { TransactionRepository } from '../../typeorm/repository/Transaction'
@ -41,7 +42,7 @@ export class AdminResolver {
return adminUsers return adminUsers
} }
@Authorized([RIGHTS.SEARCH_USERS]) @Authorized([RIGHTS.CREATE_PENDING_CREATION])
@Mutation(() => [Number]) @Mutation(() => [Number])
async createPendingCreation( async createPendingCreation(
@Args() { email, amount, memo, creationDate, moderator }: CreatePendingCreationArgs, @Args() { email, amount, memo, creationDate, moderator }: CreatePendingCreationArgs,
@ -66,7 +67,33 @@ export class AdminResolver {
return await getUserCreations(user.id) return await getUserCreations(user.id)
} }
@Authorized([RIGHTS.SEARCH_USERS]) @Authorized([RIGHTS.CREATE_PENDING_CREATION])
@Mutation(() => CreatePendingCreations)
async createPendingCreations(
@Arg('pendingCreations', () => [CreatePendingCreationArgs])
pendingCreations: CreatePendingCreationArgs[],
): Promise<CreatePendingCreations> {
let success = false
const successfulCreation: string[] = []
const failedCreation: string[] = []
for (const pendingCreation of pendingCreations) {
await this.createPendingCreation(pendingCreation)
.then(() => {
successfulCreation.push(pendingCreation.email)
success = true
})
.catch(() => {
failedCreation.push(pendingCreation.email)
})
}
return {
success,
successfulCreation,
failedCreation,
}
}
@Authorized([RIGHTS.UPDATE_PENDING_CREATION])
@Mutation(() => UpdatePendingCreation) @Mutation(() => UpdatePendingCreation)
async updatePendingCreation( async updatePendingCreation(
@Args() { id, email, amount, memo, creationDate, moderator }: UpdatePendingCreationArgs, @Args() { id, email, amount, memo, creationDate, moderator }: UpdatePendingCreationArgs,
@ -96,7 +123,7 @@ export class AdminResolver {
return result return result
} }
@Authorized([RIGHTS.SEARCH_USERS]) @Authorized([RIGHTS.SEARCH_PENDING_CREATION])
@Query(() => [PendingCreation]) @Query(() => [PendingCreation])
async getPendingCreations(): Promise<PendingCreation[]> { async getPendingCreations(): Promise<PendingCreation[]> {
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository) const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
@ -124,7 +151,7 @@ export class AdminResolver {
return pendingCreationsPromise.reverse() return pendingCreationsPromise.reverse()
} }
@Authorized([RIGHTS.SEARCH_USERS]) @Authorized([RIGHTS.DELETE_PENDING_CREATION])
@Mutation(() => Boolean) @Mutation(() => Boolean)
async deletePendingCreation(@Arg('id') id: number): Promise<boolean> { async deletePendingCreation(@Arg('id') id: number): Promise<boolean> {
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository) const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
@ -133,7 +160,7 @@ export class AdminResolver {
return !!res return !!res
} }
@Authorized([RIGHTS.SEARCH_USERS]) @Authorized([RIGHTS.CONFIRM_PENDING_CREATION])
@Mutation(() => Boolean) @Mutation(() => Boolean)
async confirmPendingCreation(@Arg('id') id: number, @Ctx() context: any): Promise<boolean> { async confirmPendingCreation(@Arg('id') id: number, @Ctx() context: any): Promise<boolean> {
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository) const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
@ -310,6 +337,7 @@ function isCreationValid(creations: number[], amount: number, creationDate: Date
} }
return true return true
} }
async function hasActivatedEmail(email: string): Promise<boolean> { async function hasActivatedEmail(email: string): Promise<boolean> {
const repository = getCustomRepository(LoginUserRepository) const repository = getCustomRepository(LoginUserRepository)
const user = await repository.findByEmail(email) const user = await repository.findByEmail(email)