Skip to content
Snippets Groups Projects
Commit 91e73238 authored by Augustin LECONTE's avatar Augustin LECONTE
Browse files

Merge branch 'feat/US12-see-incomplete-structures' into 'dev'

feat/US12-see-incomplete-structures

See merge request web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server!94
parents 79f55d01 9bff0dd8
No related branches found
No related tags found
3 merge requests!97release V1.10.0,!96release V1.10.0,!94feat/US12-see-incomplete-structures
......@@ -190,4 +190,11 @@ describe('AdminController', () => {
}
});
});
it('should get pending structure list for admin', async () => {
expect((await controller.getAdminStructuresList()).inClaim.length).toBe(2);
expect((await controller.getAdminStructuresList()).toClaim.length).toEqual(2);
expect((await controller.getAdminStructuresList()).claimed.length).toEqual(0);
expect((await controller.getAdminStructuresList()).incomplete.length).toEqual(2);
});
});
import { ApiOperation, ApiParam } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { Body, Delete, Param, Controller, Get, Post, UseGuards, HttpStatus, HttpException } from '@nestjs/common';
import {
Body,
Delete,
Param,
Controller,
Get,
Post,
UseGuards,
HttpStatus,
HttpException,
Logger,
} from '@nestjs/common';
import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema';
import { NewsletterService } from '../newsletter/newsletter.service';
import { StructuresService } from '../structures/services/structures.service';
......@@ -8,9 +19,12 @@ import { Roles } from '../users/decorators/roles.decorator';
import { RolesGuard } from '../users/guards/roles.guard';
import { UsersService } from '../users/users.service';
import { PendingStructureDto } from './dto/pending-structure.dto';
import { validate } from 'class-validator';
import { Structure } from '../structures/schemas/structure.schema';
@Controller('admin')
export class AdminController {
private readonly logger = new Logger(AdminController.name);
constructor(
private usersService: UsersService,
private structuresService: StructuresService,
......@@ -36,12 +50,13 @@ export class AdminController {
@Get('adminStructuresList')
@ApiOperation({ description: 'Get pending structre for validation' })
public async getAdminStructuresList(): Promise<any> {
const structuresList = { claimed: [], inClaim: [], toClaim: [] };
const structuresList = { claimed: [], inClaim: [], toClaim: [], incomplete: [] };
structuresList.inClaim = await this.getPendingAttachments();
structuresList.toClaim = (await this.structuresService.findAllUnclaimed()).filter(
(demand) => !structuresList.inClaim.find((elem) => elem.structureId == demand.structureId)
);
structuresList.claimed = (await this.structuresService.findAll())
const allStructures = await this.structuresService.findAll();
structuresList.claimed = allStructures
.filter(
(demand) =>
!structuresList.inClaim.find((elem) => elem.structureId == demand.id) &&
......@@ -50,9 +65,23 @@ export class AdminController {
.map((structure) => {
return { structureId: structure.id, structureName: structure.structureName };
});
structuresList.incomplete = await Promise.all(
allStructures.map(async (struct) => {
const validity = await validate(new Structure(struct));
if (validity.length > 0) {
this.logger.debug(`getAdminStructuresList - validation failed. errors: ${validity.toString()}`);
return { structureId: struct.id, structureName: struct.structureName };
} else {
this.logger.debug('getAdminStructuresList - validation succeed');
return null;
}
})
);
structuresList.incomplete = structuresList.incomplete.filter((structure) => structure);
structuresList.claimed.sort((a, b) => a.structureName.localeCompare(b.structureName));
structuresList.inClaim.sort((a, b) => a.structureName.localeCompare(b.structureName));
structuresList.toClaim.sort((a, b) => a.structureName.localeCompare(b.structureName));
structuresList.incomplete.sort((a, b) => a.structureName.localeCompare(b.structureName));
return structuresList;
}
......
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsNotEmpty, ValidateNested } from 'class-validator';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { Week } from './week.schema';
......@@ -7,6 +9,50 @@ export type StructureDocument = Structure & Document;
@Schema({ timestamps: true })
export class Structure {
constructor(data: Partial<Structure> = {}) {
this.structureName = data.structureName;
this.createdAt = data.createdAt;
this.updatedAt = data.updatedAt;
this.numero = data.numero;
this.structureType = data.structureType;
this.description = data.description;
this.lockdownActivity = data.lockdownActivity;
this.address = data.address;
this.contactPhone = data.contactPhone;
this.contactMail = data.contactMail;
this.website = data.website;
this.facebook = data.facebook;
this.twitter = data.twitter;
this.instagram = data.instagram;
this.linkedin = data.linkedin;
this.pmrAccess = data.pmrAccess;
this.accessModality = data.accessModality;
this.otherDescription = data.otherDescription;
this.labelsQualifications = data.labelsQualifications;
this.publics = data.publics;
this.exceptionalClosures = data.exceptionalClosures;
this.publicsAccompaniment = data.publicsAccompaniment;
this.proceduresAccompaniment = data.proceduresAccompaniment;
this.remoteAccompaniment = data.remoteAccompaniment;
this.baseSkills = data.baseSkills;
this.accessRight = data.accessRight;
this.socialAndProfessional = data.socialAndProfessional;
this.parentingHelp = data.parentingHelp;
this.exceptionalClosures = data.exceptionalClosures;
this.digitalCultureSecurity = data.digitalCultureSecurity;
this.equipmentsAndServices = data.equipmentsAndServices;
this.freeWorkShop = data.freeWorkShop;
this.nbTablets = data.nbTablets;
this.nbPrinters = data.nbPrinters;
this.nbComputers = data.nbComputers;
this.nbNumericTerminal = data.nbNumericTerminal;
this.nbScanners = data.nbScanners;
this.hours = data.hours;
this.coord = data.coord;
this.deletedAt = data.deletedAt;
this.accountVerified = data.accountVerified;
}
@Prop()
numero: string;
......@@ -17,9 +63,11 @@ export class Structure {
updatedAt: string;
@Prop()
@IsNotEmpty()
structureName: string;
@Prop()
@IsNotEmpty()
structureType: string;
@Prop()
......@@ -29,13 +77,18 @@ export class Structure {
lockdownActivity: string;
@Prop()
@ValidateNested({ each: true })
@Type(() => Address)
address: Address;
@Prop()
@IsNotEmpty()
contactPhone: string;
@Prop()
@IsNotEmpty()
contactMail: string;
@Prop()
website: string;
......@@ -52,9 +105,11 @@ export class Structure {
linkedin: string;
@Prop()
@IsNotEmpty()
pmrAccess: boolean;
@Prop()
@ArrayNotEmpty()
accessModality: string[];
@Prop()
......@@ -64,6 +119,7 @@ export class Structure {
labelsQualifications: string[];
@Prop()
@ArrayNotEmpty()
publics: string[];
@Prop()
......@@ -76,6 +132,7 @@ export class Structure {
proceduresAccompaniment: string[];
@Prop()
@IsNotEmpty()
remoteAccompaniment: boolean;
@Prop()
......@@ -97,21 +154,26 @@ export class Structure {
equipmentsAndServices: string[];
@Prop()
@IsNotEmpty()
freeWorkShop: boolean;
@Prop()
nbComputers: number;
@Prop()
@IsNotEmpty()
nbPrinters: number;
@Prop()
@IsNotEmpty()
nbTablets: number;
@Prop()
@IsNotEmpty()
nbNumericTerminal: number;
@Prop()
@IsNotEmpty()
nbScanners: number;
@Prop()
......
......@@ -329,4 +329,310 @@ export class StructuresServiceMock {
throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
}
findAll() {
return [
{
_id: '6093ba0e2ab5775cfc01abce',
coord: [4.8498155, 45.7514817],
equipmentsAndServices: ['wifiEnAccesLibre'],
digitalCultureSecurity: [],
parentingHelp: [],
socialAndProfessional: [],
accessRight: [],
baseSkills: [],
proceduresAccompaniment: [],
publicsAccompaniment: [],
publics: ['adultes'],
labelsQualifications: [],
accessModality: ['telephoneVisio'],
structureType: null,
structureName: 'a',
description: null,
lockdownActivity: null,
address: {
numero: null,
street: 'Rue Alphonse Daudet',
commune: 'Lyon 7ème Arrondissement',
},
contactMail: '',
contactPhone: '',
website: '',
facebook: null,
twitter: null,
instagram: null,
linkedin: null,
hours: {
monday: {
open: false,
time: [],
},
tuesday: {
open: false,
time: [],
},
wednesday: {
open: false,
time: [],
},
thursday: {
open: false,
time: [],
},
friday: {
open: false,
time: [],
},
saturday: {
open: false,
time: [],
},
sunday: {
open: false,
time: [],
},
},
pmrAccess: false,
exceptionalClosures: null,
otherDescription: null,
nbComputers: 1,
nbPrinters: 1,
nbTablets: 1,
nbNumericTerminal: 1,
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
},
{
_id: '6093ba0e2ab5775cfc01fffe',
coord: [4.8498155, 45.7514817],
equipmentsAndServices: ['wifiEnAccesLibre'],
digitalCultureSecurity: [],
parentingHelp: [],
socialAndProfessional: [],
accessRight: [],
baseSkills: [],
proceduresAccompaniment: [],
publicsAccompaniment: [],
publics: ['adultes'],
labelsQualifications: [],
accessModality: ['telephoneVisio'],
structureType: null,
structureName: 'a',
description: null,
lockdownActivity: null,
address: {
numero: null,
street: 'Rue Alphonse Daudet',
commune: 'Lyon 7ème Arrondissement',
},
contactMail: '',
contactPhone: '',
website: '',
facebook: null,
twitter: null,
instagram: null,
linkedin: null,
hours: {
monday: {
open: false,
time: [],
},
tuesday: {
open: false,
time: [],
},
wednesday: {
open: false,
time: [],
},
thursday: {
open: false,
time: [],
},
friday: {
open: false,
time: [],
},
saturday: {
open: false,
time: [],
},
sunday: {
open: false,
time: [],
},
},
pmrAccess: false,
exceptionalClosures: null,
otherDescription: null,
nbComputers: 1,
nbPrinters: 1,
nbTablets: 1,
nbNumericTerminal: 1,
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
},
];
}
findAllUnclaimed() {
return [
{
_id: '6093ba0e2ab5775cfc01abcd',
coord: [4.8498155, 45.7514817],
equipmentsAndServices: ['wifiEnAccesLibre'],
digitalCultureSecurity: [],
parentingHelp: [],
socialAndProfessional: [],
accessRight: [],
baseSkills: [],
proceduresAccompaniment: [],
publicsAccompaniment: [],
publics: ['adultes'],
labelsQualifications: [],
accessModality: ['telephoneVisio'],
structureType: null,
structureName: 'a',
description: null,
lockdownActivity: null,
address: {
numero: null,
street: 'Rue Alphonse Daudet',
commune: 'Lyon 7ème Arrondissement',
},
contactMail: '',
contactPhone: '',
website: '',
facebook: null,
twitter: null,
instagram: null,
linkedin: null,
hours: {
monday: {
open: false,
time: [],
},
tuesday: {
open: false,
time: [],
},
wednesday: {
open: false,
time: [],
},
thursday: {
open: false,
time: [],
},
friday: {
open: false,
time: [],
},
saturday: {
open: false,
time: [],
},
sunday: {
open: false,
time: [],
},
},
pmrAccess: false,
exceptionalClosures: null,
otherDescription: null,
nbComputers: 1,
nbPrinters: 1,
nbTablets: 1,
nbNumericTerminal: 1,
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
},
{
_id: '6093ba0e2ab5775cfc01ffff',
coord: [4.8498155, 45.7514817],
equipmentsAndServices: ['wifiEnAccesLibre'],
digitalCultureSecurity: [],
parentingHelp: [],
socialAndProfessional: [],
accessRight: [],
baseSkills: [],
proceduresAccompaniment: [],
publicsAccompaniment: [],
publics: ['adultes'],
labelsQualifications: [],
accessModality: ['telephoneVisio'],
structureType: null,
structureName: 'a',
description: null,
lockdownActivity: null,
address: {
numero: null,
street: 'Rue Alphonse Daudet',
commune: 'Lyon 7ème Arrondissement',
},
contactMail: '',
contactPhone: '',
website: '',
facebook: null,
twitter: null,
instagram: null,
linkedin: null,
hours: {
monday: {
open: false,
time: [],
},
tuesday: {
open: false,
time: [],
},
wednesday: {
open: false,
time: [],
},
thursday: {
open: false,
time: [],
},
friday: {
open: false,
time: [],
},
saturday: {
open: false,
time: [],
},
sunday: {
open: false,
time: [],
},
},
pmrAccess: false,
exceptionalClosures: null,
otherDescription: null,
nbComputers: 1,
nbPrinters: 1,
nbTablets: 1,
nbNumericTerminal: 1,
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
},
];
}
}
......@@ -110,7 +110,7 @@ export class UsersServiceMock {
role: 0,
name: 'DUPONT',
surname: 'Pauline',
structuresLink: ['abcdefgh', '18sfqfq'],
structuresLink: ['abcdefgh', '18sfqfq', '6093ba0e2ab5775cfc01fffe'],
});
});
}
......@@ -124,8 +124,8 @@ export class UsersServiceMock {
return [
{
structureOutdatedMailSent: [],
pendingStructuresLink: ['6001a48e16b08100062e4180'],
structuresLink: [],
pendingStructuresLink: ['6001a48e16b08100062e4180', '6093ba0e2ab5775cfc01fffe'],
structuresLink: ['6093ba0e2ab5775cfc01fffe'],
newEmail: null,
changeEmailToken: null,
role: 0,
......@@ -150,8 +150,8 @@ export class UsersServiceMock {
return [
{
structureOutdatedMailSent: [],
pendingStructuresLink: ['6001a48e16b08100062e4180'],
structuresLink: [],
pendingStructuresLink: ['6001a48e16b08100062e4180', '6093ba0e2ab5775cfc01fffe'],
structuresLink: ['6093ba0e2ab5775cfc01fffe'],
newEmail: null,
changeEmailToken: null,
role: 0,
......@@ -169,8 +169,8 @@ export class UsersServiceMock {
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: ['6001a3c216b08100062e4169', '601d6aa2c94cf895c4e23860'],
structuresLink: ['6037aa17d8189c0014f62421'],
pendingStructuresLink: ['6001a3c216b08100062e4169', '601d6aa2c94cf895c4e23860', '6093ba0e2ab5775cfc01fffe'],
structuresLink: ['6037aa17d8189c0014f62421', '6093ba0e2ab5775cfc01fffe'],
newEmail: null,
changeEmailToken: null,
role: 0,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment