Skip to content

Commit f5ec46e

Browse files
committed
Refactor inetOrgPerson.dto.ts to add departmentNumber field
1 parent 0fd5e02 commit f5ec46e

File tree

11 files changed

+109
-95
lines changed

11 files changed

+109
-95
lines changed

src/_common/abstracts/abstract.service.schema.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
110110
}
111111
if (!data) {
112112
this.logger.debug(['findById', JSON.stringify(Object.values(arguments))].join(' '))
113-
throw new NotFoundException()}
113+
throw new NotFoundException()
114+
}
114115
return data
115116
}
116117

@@ -135,7 +136,8 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
135136
let data = await this._model.findOne<Query<T | null, T, any, T>>(filter, projection, options).exec()
136137
if (!data) {
137138
this.logger.debug(['findById', JSON.stringify(Object.values(arguments))].join(' '))
138-
throw new NotFoundException()}
139+
throw new NotFoundException()
140+
}
139141
if (this.eventEmitter) {
140142
const afterEvents = await this.eventEmitter?.emitAsync(
141143
[this.moduleName.toLowerCase(), this.serviceName.toLowerCase(), 'service', 'afterFindOne'].join(EventEmitterSeparator),
@@ -238,7 +240,8 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
238240
.exec()
239241
if (!updated) {
240242
this.logger.debug(['findById', JSON.stringify(Object.values(arguments))].join(' '))
241-
throw new NotFoundException()}
243+
throw new NotFoundException()
244+
}
242245
if (this.eventEmitter) {
243246
const afterEvents = await this.eventEmitter?.emitAsync(
244247
[this.moduleName.toLowerCase(), this.serviceName.toLowerCase(), 'service', 'afterFindAndCount'].join(EventEmitterSeparator),
@@ -252,9 +255,9 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
252255
}
253256

254257
public async upsert<T extends AbstractSchema | Document>(
255-
filter: FilterQuery<T>,
256-
update: UpdateQuery<T>,
257-
options?: QueryOptions<T>
258+
filter: FilterQuery<T>,
259+
update: UpdateQuery<T>,
260+
options?: QueryOptions<T>
258261
): Promise<ModifyResult<Query<T, T, any, T>>> {
259262
this.logger.debug(['upsert', JSON.stringify(Object.values(arguments))].join(' '));
260263
if (this.eventEmitter) {
@@ -275,6 +278,7 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
275278
{
276279
...update,
277280
$setOnInsert: {
281+
...(update?.$setOnInsert || {}),
278282
'metadata.createdBy': this.request?.user?.username || 'anonymous',
279283
'metadata.createdAt': new Date(),
280284
},
@@ -326,7 +330,8 @@ export abstract class AbstractServiceSchema extends AbstractService implements S
326330
let deleted = await this._model.findByIdAndDelete<Query<T | null, T, any, T>>({ _id }, options).exec()
327331
if (!deleted) {
328332
this.logger.debug(['findById', JSON.stringify(Object.values(arguments))].join(' '))
329-
throw new NotFoundException()}
333+
throw new NotFoundException()
334+
}
330335
if (this.eventEmitter) {
331336
const afterEvents = await this.eventEmitter?.emitAsync(
332337
[this.moduleName.toLowerCase(), this.serviceName.toLowerCase(), 'service', 'afterFindAndCount'].join(EventEmitterSeparator),

src/core/backends/backends.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export class BackendsService extends AbstractQueueProcessor {
115115
},
116116
{ upsert: true, new: true },
117117
);
118-
console.log('completedJob', completedJob);
118+
// console.log('completedJob', completedJob);
119119
await this.identitiesService.model.findByIdAndUpdate(completedJob.concernedTo.id, {
120120
$set: {
121121
state: IdentityState.SYNCED,

src/management/identities/_dto/_parts/inetOrgPerson.dto.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export class inetOrgPersonCreateDto {
1818
@ApiProperty()
1919
employeeType: string;
2020

21+
@IsString()
22+
@ApiProperty()
23+
@IsOptional()
24+
departmentNumber: string;
25+
2126
@IsString()
2227
@ApiProperty()
2328
@IsOptional()

src/management/identities/_dto/identities.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ export class IdentitiesDto extends IdentitiesCreateDto { }
4949
export class IdentitiesUpdateDto extends PartialType(IdentitiesCreateDto) { }
5050

5151
export class IdentitiesUpsertDto extends PartialType(IdentitiesUpdateDto) {
52-
$addToSet?: Partial<IdentitiesUpdateDto>;
52+
$setOnInsert?: Partial<IdentitiesUpdateDto>;
5353
}

src/management/identities/_schemas/_parts/inetOrgPerson.part.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class inetOrgPerson {
3838
@Prop()
3939
title?: string;
4040

41-
@Prop({ required: true, unique: true })
41+
@Prop({ required: true })
4242
uid: string;
4343

4444
@Prop({ required: true })
@@ -47,6 +47,9 @@ export class inetOrgPerson {
4747
@Prop({ required: true })
4848
employeeType: string;
4949

50+
@Prop()
51+
departmentNumber: string;
52+
5053
@Prop()
5154
userCertificate?: string;
5255

src/management/identities/_stubs/_parts/inetOrgPerson.dto.stub.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const inetOrgPersonDtoStub = (): inetOrgPersonDto => {
77
uid: 'uid',
88
employeeNumber: 'employeeNumber',
99
employeeType: 'employeeType',
10+
departmentNumber: 'departmentNumber',
1011
displayName: 'displayName',
1112
facsimileTelephoneNumber: 'facsimileTelephoneNumber',
1213
givenName: 'givenName',

src/management/identities/identities.controller.ts

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { FilterOptions, FilterSchema, SearchFilterOptions, SearchFilterSchema }
2929
import { IdentitiesValidationService } from './validations/identities.validation.service';
3030
import { MixedValue } from '~/_common/types/mixed-value.type';
3131
import { Identities } from './_schemas/identities.schema';
32-
import { Types, Document } from 'mongoose';
32+
import { Types, Document, isValidObjectId } from 'mongoose';
3333
import { IdentityState } from './_enums/states.enum';
3434
// import { IdentitiesValidationFilter } from '~/_common/filters/identities-validation.filter';
3535

@@ -89,53 +89,48 @@ export class IdentitiesController extends AbstractController {
8989
@Res()
9090
res: Response,
9191
@Body() body: IdentitiesUpsertDto,
92+
@Query('filters')
93+
filtersQuery: {
94+
[key: string]: string;
95+
}[] = [],
9296
@Query('errorOnNotFound') errorOnNotFound: string = 'false',
93-
): Promise<Response<any>> {
94-
const data = await this._service.upsert<Identities>(body, {
97+
): Promise<
98+
Response<{
99+
statusCode: number;
100+
data?: Document<Identities, any, Identities>;
101+
message?: string;
102+
validations?: MixedValue;
103+
}>
104+
> {
105+
const filters = {};
106+
if (filtersQuery.length === 0) {
107+
throw new BadRequestException('Missing filters array');
108+
}
109+
for (const [key, filter] of Object.entries(filtersQuery)) {
110+
filters[key] = isValidObjectId(filter) ? new Types.ObjectId(`${filter}`) : filter;
111+
}
112+
113+
const data = await this._service.upsert<Identities>(filters, body, {
95114
errorOnNotFound: /true|on|yes|1/i.test(errorOnNotFound),
96115
});
97-
return res.status(200).json({
116+
117+
// If the state is TO_COMPLETE, the identity is created but additional fields are missing or invalid
118+
// Else the state is TO_VALIDATE, we return a 201 status code
119+
if ((data as unknown as Identities).state === IdentityState.TO_COMPLETE) {
120+
return res.status(HttpStatus.ACCEPTED).json({
121+
statusCode: HttpStatus.ACCEPTED,
122+
message: 'Identitée créée avec succès, mais des champs additionnels sont manquants ou invalides.',
123+
data,
124+
});
125+
}
126+
127+
return res.status(HttpStatus.CREATED).json({
128+
statusCode: HttpStatus.CREATED,
129+
message: 'Identitée créée avec succès.',
98130
data,
99131
});
100132
}
101133

102-
// @Post('upsert')
103-
// @ApiCreateDecorator(IdentitiesCreateDto, IdentitiesDto)
104-
// public async upsertV1(
105-
// @Res()
106-
// res: Response,
107-
// @Body() body: IdentitiesCreateDto,
108-
// @Query('errorOnNotFound') errorOnNotFound: string = 'false',
109-
// ): Promise<
110-
// Response<
111-
// {
112-
// statusCode: number;
113-
// data?: Document<Identities, any, Identities>;
114-
// message?: string;
115-
// validations?: MixedValue;
116-
// },
117-
// any
118-
// >
119-
// > {
120-
// let statusCode = HttpStatus.CREATED;
121-
// let message = null;
122-
// const data = await this._service.upsert<Identities>(body, {
123-
// errorOnNotFound: errorOnNotFound.toLowerCase() === 'true',
124-
// });
125-
// // If the state is TO_COMPLETE, the identity is created but additional fields are missing or invalid
126-
// // Else the state is TO_VALIDATE, we return a 201 status code
127-
// if ((data as unknown as Identities).state === IdentityState.TO_COMPLETE) {
128-
// statusCode = HttpStatus.ACCEPTED;
129-
// message = 'Identitée créée avec succès, mais des champs additionnels sont manquants ou invalides.';
130-
// }
131-
132-
// return res.status(statusCode).json({
133-
// statusCode,
134-
// data,
135-
// message,
136-
// });
137-
// }
138-
139134
@Get()
140135
@ApiPaginatedDecorator(PickProjectionHelper(IdentitiesDto, IdentitiesController.projection))
141136
public async search(

src/management/identities/identities.service.ts

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
import { HttpException, Injectable, Logger } from '@nestjs/common';
22
import { InjectModel } from '@nestjs/mongoose';
33
import { Identities } from './_schemas/identities.schema';
4-
import { Document, Model, ModifyResult, Query, QueryOptions, SaveOptions, Types, UpdateQuery } from 'mongoose';
4+
import {
5+
Document,
6+
FilterQuery,
7+
Model,
8+
ModifyResult,
9+
Query,
10+
QueryOptions,
11+
SaveOptions,
12+
Types,
13+
UpdateQuery,
14+
} from 'mongoose';
515
import { AbstractServiceSchema } from '~/_common/abstracts/abstract.service.schema';
616
import { AbstractSchema } from '~/_common/abstracts/schemas/abstract.schema';
717
import { IdentitiesValidationService } from './validations/identities.validation.service';
818
import { ValidationConfigException, ValidationSchemaException } from '~/_common/errors/ValidationException';
919
import { IdentityState } from './_enums/states.enum';
20+
import { construct, crush, omit } from 'radash';
21+
import { IdentitiesUpsertDto } from './_dto/identities.dto';
1022

1123
@Injectable()
1224
export class IdentitiesService extends AbstractServiceSchema {
@@ -27,56 +39,41 @@ export class IdentitiesService extends AbstractServiceSchema {
2739
}
2840

2941
public async upsert<T extends AbstractSchema | Document>(
30-
data?: any,
42+
filters: FilterQuery<T>,
43+
data?: IdentitiesUpsertDto,
3144
options?: QueryOptions<T>,
3245
): Promise<ModifyResult<Query<T, T, any, T>>> {
33-
Logger.log(`Upserting identity: ${JSON.stringify(data)}`);
34-
const logPrefix = `Validation [${data.inetOrgPerson.cn}]:`;
35-
// console.log(options);
36-
const identity = await this._model.findOne({
37-
'inetOrgPerson.employeeNumber': data.inetOrgPerson.employeeNumber,
38-
'inetOrgPerson.employeeType': data.inetOrgPerson.employeeType,
46+
this.logger.log(`Upserting identity with filters ${JSON.stringify(filters)}`);
47+
const crushedUpdate = crush(JSON.parse(JSON.stringify(omit(data || {}, ['$setOnInsert']))));
48+
const crushedSetOnInsert = crush(JSON.parse(JSON.stringify(data.$setOnInsert || {})));
49+
50+
data = construct({
51+
...crushedUpdate,
52+
...crushedSetOnInsert,
3953
});
40-
// console.log(identity);
41-
if (!identity && options.errorOnNotFound) {
42-
this.logger.error(`${logPrefix} Identity not found.`);
43-
throw new HttpException('Identity not found.', 404);
44-
}
4554
data.additionalFields.validations = {};
55+
const logPrefix = `Validation [${data.inetOrgPerson.cn}]:`;
56+
4657
try {
4758
this.logger.log(`${logPrefix} Starting additionalFields validation.`);
4859
const validations = await this._validation.validate(data.additionalFields);
4960
this.logger.log(`${logPrefix} AdditionalFields validation successful.`);
50-
this.logger.log(`Validations : ${validations}`);
51-
data.state = IdentityState.TO_VALIDATE;
61+
this.logger.log(`Validations : ${JSON.stringify(validations)}`);
62+
crushedUpdate['state'] = IdentityState.TO_VALIDATE;
5263
} catch (error) {
5364
data = this.handleValidationError(error, data, logPrefix);
65+
crushedUpdate['state'] = data.state;
66+
crushedUpdate['additionalFields.validations'] = data.additionalFields.validations;
5467
}
5568

56-
//TODO: ameliorer la logique d'upsert
57-
if (identity) {
58-
this.logger.log(`${logPrefix} Identity already exists. Updating.`);
59-
data.inetOrgPerson = {
60-
...identity.inetOrgPerson,
61-
...data.inetOrgPerson,
62-
};
63-
data.additionalFields.objectClasses = [
64-
...new Set([...identity.additionalFields.objectClasses, ...data.additionalFields.objectClasses]),
65-
];
66-
data.additionalFields.attributes = {
67-
...identity.additionalFields.attributes,
68-
...data.additionalFields.attributes,
69-
};
70-
data.additionalFields.validations = {
71-
...identity.additionalFields.validations,
72-
...data.additionalFields.validations,
73-
};
74-
}
75-
76-
//TODO: rechercher par uid ou employeeNumber + employeeType ?
77-
const upsert = await super.upsert({ 'inetOrgPerson.uid': data.inetOrgPerson.uid }, data, options);
78-
return upsert;
79-
//TODO: add backends service logic here
69+
return await super.upsert(
70+
filters,
71+
{
72+
$set: crushedUpdate,
73+
$setOnInsert: crushedSetOnInsert,
74+
},
75+
options,
76+
);
8077
}
8178

8279
// public async upsert<T extends AbstractSchema | Document>(
@@ -191,15 +188,19 @@ export class IdentitiesService extends AbstractServiceSchema {
191188
return deleted;
192189
}
193190

194-
private handleValidationError(error: Error | HttpException, identity: Identities, logPrefix: string) {
191+
private handleValidationError(
192+
error: Error | HttpException,
193+
identity: Identities | IdentitiesUpsertDto,
194+
logPrefix: string,
195+
): any {
195196
if (error instanceof ValidationConfigException) {
196197
this.logger.error(`${logPrefix} Validation config error. ${JSON.stringify(error.getValidations())}`);
197198
throw new ValidationConfigException(error.getPayload());
198199
}
199200

200201
if (error instanceof ValidationSchemaException) {
201202
this.logger.warn(`${logPrefix} Validation schema error. ${JSON.stringify(error.getValidations())}`);
202-
identity.additionalFields.validations = error.getValidations();
203+
identity.additionalFields.validations = error.getValidations() as any;
203204
if (identity.state === IdentityState.TO_CREATE) {
204205
this.logger.warn(`${logPrefix} State set to TO_COMPLETE.`);
205206
identity.state = IdentityState.TO_COMPLETE;

src/management/identities/jsonforms/_config/supann.ui.yml renamed to src/management/identities/jsonforms/_config/supannPerson.ui.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
type: Group
2-
label: supann
2+
label: supannPerson
33
elements:
44
- type: HorizontalLayout
55
elements:

src/management/identities/validations/_config/supann.yml renamed to src/management/identities/validations/_config/supannPerson.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ properties:
5252
supannEmpDateFin:
5353
type: string
5454
description: Field corresponding to supannEmpDateFin
55+
supannEtablissement:
56+
type: string
57+
description: etablissement
5558
required:
5659
- supanncivilite
5760
- supannAutreMail
@@ -61,7 +64,7 @@ required:
6164
# - supannCodeINSEEVilleDeNaissance
6265
# - supannMailPerso
6366
# - supannEntiteAffectationPrincipale
64-
- supannCodeINSEEPaysDeNaissance
67+
#- supannCodeINSEEPaysDeNaissance
6568
- supannRefId
6669
- supannPrenomsEtatCivil
6770
# - mailForwardingAddress

0 commit comments

Comments
 (0)