diff --git a/src/app/api/admin/CustomersController.ts b/src/app/api/admin/CustomersController.ts index e1badb0d..5f9ed4ec 100644 --- a/src/app/api/admin/CustomersController.ts +++ b/src/app/api/admin/CustomersController.ts @@ -31,9 +31,9 @@ export default class CustomersController extends ApiController { } const officeId: string = req.body.user.office_Id; - if(query.where?.office_folders?.some?.office_uid) delete query.where.office_folders.some.office_uid; - if(query.where?.office_folders?.some?.office?.uid) delete query.where?.office_folders?.some?.office?.uid; - const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }}; + if (query.where?.office_folders?.some?.office_uid) delete query.where.office_folders.some.office_uid; + if (query.where?.office_folders?.some?.office?.uid) delete query.where?.office_folders?.some?.office?.uid; + const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } } }; query.where = customerWhereInput; //call service to get prisma entity @@ -79,7 +79,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler]) + @Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -95,22 +95,32 @@ export default class CustomersController extends ApiController { return; } + req.body.contact.uid = userFound.contact_uid; + //init IUser resource with request body values const customerEntity = Customer.hydrate(req.body); - //validate user - await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); - + try { + await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); + } catch (error) { + this.httpValidationError(response, error); + return; + } //call service to get prisma entity - const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + try { + const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + //Hydrate ressource with prisma entity + const customer = Customer.hydrate(customerEntityUpdated, { + strategy: "excludeAll", + }); - //Hydrate ressource with prisma entity - const customer = Customer.hydrate(customerEntityUpdated, { - strategy: "excludeAll", - }); - - //success - this.httpSuccess(response, customer); + //success + this.httpSuccess(response, customer); + } catch (error) { + console.log(error); + this.httpValidationError(response, error); + return; + } } catch (error) { this.httpInternalError(response, error); return; diff --git a/src/app/api/notary/CustomersController.ts b/src/app/api/notary/CustomersController.ts index 4415fd34..69b6bb7f 100644 --- a/src/app/api/notary/CustomersController.ts +++ b/src/app/api/notary/CustomersController.ts @@ -30,8 +30,8 @@ export default class CustomersController extends ApiController { } const officeId: string = req.body.user.office_Id; - if(query.where?.office_folders) delete query.where.office_folders; - const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }}; + if (query.where?.office_folders) delete query.where.office_folders; + const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } } }; query.where = customerWhereInput; //call service to get prisma entity @@ -57,8 +57,12 @@ export default class CustomersController extends ApiController { //init IUser resource with request body values const customerEntity = Customer.hydrate(req.body); //validate user - await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false }); - + try { + await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false }); + } catch (error) { + this.httpValidationError(response, error); + return; + } //call service to get prisma entity const customerEntityCreated = await this.customersService.create(customerEntity); //Hydrate ressource with prisma entity @@ -93,22 +97,32 @@ export default class CustomersController extends ApiController { return; } + req.body.contact.uid = userFound.contact_uid; + //init IUser resource with request body values const customerEntity = Customer.hydrate(req.body); - //validate user - await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); - + try { + await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); + } catch (error) { + this.httpValidationError(response, error); + return; + } //call service to get prisma entity - const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + try { + const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + //Hydrate ressource with prisma entity + const customer = Customer.hydrate(customerEntityUpdated, { + strategy: "excludeAll", + }); - //Hydrate ressource with prisma entity - const customer = Customer.hydrate(customerEntityUpdated, { - strategy: "excludeAll", - }); - - //success - this.httpSuccess(response, customer); + //success + this.httpSuccess(response, customer); + } catch (error) { + console.log(error); + this.httpValidationError(response, error); + return; + } } catch (error) { this.httpInternalError(response, error); return; diff --git a/src/app/api/super-admin/CustomersController.ts b/src/app/api/super-admin/CustomersController.ts index 628fa4ed..b3402942 100644 --- a/src/app/api/super-admin/CustomersController.ts +++ b/src/app/api/super-admin/CustomersController.ts @@ -79,7 +79,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler]) + @Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -94,23 +94,33 @@ export default class CustomersController extends ApiController { this.httpNotFoundRequest(response, "user not found"); return; } - + + req.body.contact.uid = userFound.contact_uid; + //init IUser resource with request body values const customerEntity = Customer.hydrate(req.body); - //validate user - await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); - + try { + await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); + } catch (error) { + this.httpValidationError(response, error); + return; + } //call service to get prisma entity - const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + try { + const customerEntityUpdated = await this.customersService.update(uid, customerEntity); + //Hydrate ressource with prisma entity + const customer = Customer.hydrate(customerEntityUpdated, { + strategy: "excludeAll", + }); - //Hydrate ressource with prisma entity - const customer = Customer.hydrate(customerEntityUpdated, { - strategy: "excludeAll", - }); - - //success - this.httpSuccess(response, customer); + //success + this.httpSuccess(response, customer); + } catch (error) { + console.log(error); + this.httpValidationError(response, error); + return; + } } catch (error) { this.httpInternalError(response, error); return; diff --git a/src/common/repositories/ContactRepository.ts b/src/common/repositories/ContactRepository.ts index 8a3861ee..da12d0aa 100644 --- a/src/common/repositories/ContactRepository.ts +++ b/src/common/repositories/ContactRepository.ts @@ -26,4 +26,16 @@ export default class ContactRepository extends BaseRepository { include: { customers: true } }); } + + /** + * @description : Find unique customer by email + */ + public async findOneByPhoneNumber(cell_phone_number: string): Promise<(Contacts & {customers: Customers | null}) | null> { + return this.model.findUnique({ + where: { + cell_phone_number: cell_phone_number, + }, + include: { customers: true } + }); + } } diff --git a/src/common/system/controller-pattern/BaseController.ts b/src/common/system/controller-pattern/BaseController.ts index b13d997a..7baa9c02 100644 --- a/src/common/system/controller-pattern/BaseController.ts +++ b/src/common/system/controller-pattern/BaseController.ts @@ -45,7 +45,6 @@ export default abstract class BaseController { } protected httpResponse(response: Response, httpCode: HttpCodes, responseData: IResponseData = {}) { - console.log("httpResponse", httpCode, responseData); if (responseData instanceof Error) { throw responseData; } diff --git a/src/services/admin/CustomersService/CustomersService.ts b/src/services/admin/CustomersService/CustomersService.ts index 7656bed2..b4878d7d 100644 --- a/src/services/admin/CustomersService/CustomersService.ts +++ b/src/services/admin/CustomersService/CustomersService.ts @@ -1,12 +1,13 @@ import { Customers, Prisma } from "@prisma/client"; import CustomersRepository from "@Repositories/CustomersRepository"; import BaseService from "@Services/BaseService"; +import ContactsService from "@Services/common/ContactService/ContactService"; import { Customer } from "le-coffre-resources/dist/Admin"; import { Service } from "typedi"; @Service() export default class CustomersService extends BaseService { - constructor(private customerRepository: CustomersRepository) { + constructor(private customerRepository: CustomersRepository, private contactService: ContactsService) { super(); } @@ -23,6 +24,14 @@ export default class CustomersService extends BaseService { * @throws {Error} If customer cannot be created */ public async create(customerEntity: Customer): Promise { + const customers = await this.get({ + where: { + contact: { + OR: [{ email: customerEntity.contact?.email }, { cell_phone_number: customerEntity.contact?.cell_phone_number }], + }, + }, + }); + if(customers[0]) return customers[0]; return this.customerRepository.create(customerEntity); } @@ -31,6 +40,16 @@ export default class CustomersService extends BaseService { * @throws {Error} If customer cannot be modified */ public async update(uid: string, customerEntity: Customer): Promise { + let errors = []; + if(customerEntity.contact?.email) { + const contactWithSameEmail = await this.contactService.getByEmail(customerEntity.contact.email); + if(contactWithSameEmail && contactWithSameEmail.uid != customerEntity.contact.uid) errors.push({property: "email", constraints: {email: "Email déjà utilisé"}}); + } + if(customerEntity.contact?.cell_phone_number) { + const contactWithSamePhoneNumber = await this.contactService.getByPhone(customerEntity.contact.cell_phone_number); + if(contactWithSamePhoneNumber && contactWithSamePhoneNumber.uid != customerEntity.contact.uid) errors.push({property: "cell_phone_number", constraints: {phone: "numéro de téléphone déjà utilisé"}}); + } + if(errors.length != 0) throw errors; return this.customerRepository.update(uid, customerEntity); } diff --git a/src/services/common/ContactService/ContactService.ts b/src/services/common/ContactService/ContactService.ts new file mode 100644 index 00000000..f56f1b83 --- /dev/null +++ b/src/services/common/ContactService/ContactService.ts @@ -0,0 +1,27 @@ +import { Contacts, Customers } from "@prisma/client"; +import ContactsRepository from "@Repositories/ContactRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; + +@Service() +export default class ContactsService extends BaseService { + constructor(private customerRepository: ContactsRepository) { + super(); + } + + /** + * @description : Get all Contacts + * @throws {Error} If Contacts cannot be get + */ + public async getByEmail(email: string): Promise<(Contacts & {customers: Customers | null}) | null> { + return this.customerRepository.findOneByEmail(email); + } + + /** + * @description : Create a new customer + * @throws {Error} If customer cannot be created + */ + public async getByPhone(cell_phone_number: string): Promise<(Contacts & {customers: Customers | null}) | null> { + return this.customerRepository.findOneByPhoneNumber(cell_phone_number); + } +} diff --git a/src/services/notary/CustomersService/CustomersService.ts b/src/services/notary/CustomersService/CustomersService.ts index 3202d143..721affd9 100644 --- a/src/services/notary/CustomersService/CustomersService.ts +++ b/src/services/notary/CustomersService/CustomersService.ts @@ -1,12 +1,13 @@ import { Customers, Prisma } from "@prisma/client"; import CustomersRepository from "@Repositories/CustomersRepository"; import BaseService from "@Services/BaseService"; +import ContactsService from "@Services/common/ContactService/ContactService"; import { Customer } from "le-coffre-resources/dist/Notary"; import { Service } from "typedi"; @Service() export default class CustomersService extends BaseService { - constructor(private customerRepository: CustomersRepository) { + constructor(private customerRepository: CustomersRepository, private contactService: ContactsService) { super(); } @@ -39,6 +40,16 @@ export default class CustomersService extends BaseService { * @throws {Error} If customer cannot be modified */ public async update(uid: string, customerEntity: Customer): Promise { + let errors = []; + if(customerEntity.contact?.email) { + const contactWithSameEmail = await this.contactService.getByEmail(customerEntity.contact.email); + if(contactWithSameEmail && contactWithSameEmail.uid != customerEntity.contact.uid) errors.push({property: "email", constraints: {email: "mail déjà utilisé"}}); + } + if(customerEntity.contact?.cell_phone_number) { + const contactWithSamePhoneNumber = await this.contactService.getByPhone(customerEntity.contact.cell_phone_number); + if(contactWithSamePhoneNumber && contactWithSamePhoneNumber.uid != customerEntity.contact.uid) errors.push({property: "cell_phone_number", constraints: {phone: "numéro de téléphone déjà utilisé"}}); + } + if(errors.length != 0) throw errors; return this.customerRepository.update(uid, customerEntity); } diff --git a/src/services/super-admin/CustomersService/CustomersService.ts b/src/services/super-admin/CustomersService/CustomersService.ts index 5501e1cb..5b8165ee 100644 --- a/src/services/super-admin/CustomersService/CustomersService.ts +++ b/src/services/super-admin/CustomersService/CustomersService.ts @@ -1,12 +1,13 @@ import { Customers, Prisma } from "@prisma/client"; import CustomersRepository from "@Repositories/CustomersRepository"; import BaseService from "@Services/BaseService"; +import ContactsService from "@Services/common/ContactService/ContactService"; import { Customer } from "le-coffre-resources/dist/SuperAdmin"; import { Service } from "typedi"; @Service() export default class CustomersService extends BaseService { - constructor(private customerRepository: CustomersRepository) { + constructor(private customerRepository: CustomersRepository, private contactService: ContactsService) { super(); } @@ -23,6 +24,14 @@ export default class CustomersService extends BaseService { * @throws {Error} If customer cannot be created */ public async create(customerEntity: Customer): Promise { + const customers = await this.get({ + where: { + contact: { + OR: [{ email: customerEntity.contact?.email }, { cell_phone_number: customerEntity.contact?.cell_phone_number }], + }, + }, + }); + if(customers[0]) return customers[0]; return this.customerRepository.create(customerEntity); } @@ -31,6 +40,16 @@ export default class CustomersService extends BaseService { * @throws {Error} If customer cannot be modified */ public async update(uid: string, customerEntity: Customer): Promise { + let errors = []; + if(customerEntity.contact?.email) { + const contactWithSameEmail = await this.contactService.getByEmail(customerEntity.contact.email); + if(contactWithSameEmail && contactWithSameEmail.uid != customerEntity.contact.uid) errors.push({property: "email", constraints: {email: "mail déjà utilisé"}}); + } + if(customerEntity.contact?.cell_phone_number) { + const contactWithSamePhoneNumber = await this.contactService.getByPhone(customerEntity.contact.cell_phone_number); + if(contactWithSamePhoneNumber && contactWithSamePhoneNumber.uid != customerEntity.contact.uid) errors.push({property: "cell_phone_number", constraints: {phone: "numéro de téléphone déjà utilisé"}}); + } + if(errors.length != 0) throw errors; return this.customerRepository.update(uid, customerEntity); } diff --git a/src/test/services/super-admin/CustomersService.test.ts b/src/test/services/super-admin/CustomersService.test.ts index 4b3f383e..01a540cd 100644 --- a/src/test/services/super-admin/CustomersService.test.ts +++ b/src/test/services/super-admin/CustomersService.test.ts @@ -6,10 +6,11 @@ import { PrismaClient } from "@prisma/client"; import { customer, customerContact, customerContact_, customer_ } from "@Test/config/MockedData"; import Container from "typedi"; import CustomersRepository from "@Repositories/CustomersRepository"; +import ContactService from "@Services/common/ContactService/ContactService"; const prisma = new PrismaClient(); -const CustomersServiceTest = new CustomersService(Container.get(CustomersRepository)); +const CustomersServiceTest = new CustomersService(Container.get(CustomersRepository), Container.get(ContactService)); afterAll(async () => { /*