mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge pull request #1203 from gradido/adminCreateMultiplePendingCreations
Admin create multiple pending creations
This commit is contained in:
commit
0e203a313f
@ -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', () => {
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
11
admin/src/graphql/createPendingCreations.js
Normal file
11
admin/src/graphql/createPendingCreations.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const createPendingCreations = gql`
|
||||||
|
mutation ($pendingCreations: [CreatePendingCreationArgs!]!) {
|
||||||
|
createPendingCreations(pendingCreations: $pendingCreations) {
|
||||||
|
success
|
||||||
|
successfulCreation
|
||||||
|
failedCreation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
@ -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',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
19
backend/src/graphql/model/CreatePendingCreations.ts
Normal file
19
backend/src/graphql/model/CreatePendingCreations.ts
Normal 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[]
|
||||||
|
}
|
||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user