feat: enhance order creation validation with additional checks for client, slot, and service
This commit is contained in:
parent
4ff50e42b9
commit
2686249cc9
@ -2,6 +2,12 @@ const ERR_INVALID_TIME = 'Некорректное время';
|
|||||||
const ERR_OVERLAPPING_TIME = 'Время пересекается с другими заказами';
|
const ERR_OVERLAPPING_TIME = 'Время пересекается с другими заказами';
|
||||||
const ERR_INACTIVE_CLIENT = 'Клиент не активен';
|
const ERR_INACTIVE_CLIENT = 'Клиент не активен';
|
||||||
const ERR_INACTIVE_MASTER = 'Мастер не активен';
|
const ERR_INACTIVE_MASTER = 'Мастер не активен';
|
||||||
|
const ERR_SLOT_CLOSED = 'Слот закрыт';
|
||||||
|
const ERR_INVALID_CLIENT = 'Некорректный клиент';
|
||||||
|
const ERR_INVALID_MASTER = 'Некорректный мастер';
|
||||||
|
const ERR_MISSING_CLIENT = 'Не указан клиент';
|
||||||
|
const ERR_MISSING_SLOT = 'Не указан слот';
|
||||||
|
const ERR_MISSING_SERVICE = 'Не указан сервис';
|
||||||
|
|
||||||
function timeToDate(time: string) {
|
function timeToDate(time: string) {
|
||||||
return new Date(`1970-01-01T${time}Z`);
|
return new Date(`1970-01-01T${time}Z`);
|
||||||
@ -26,47 +32,79 @@ function extractId(input: any): number | null {
|
|||||||
export default {
|
export default {
|
||||||
async beforeCreate(event) {
|
async beforeCreate(event) {
|
||||||
const { data } = event.params;
|
const { data } = event.params;
|
||||||
const { time_start, time_end, client } = data;
|
const { time_start, time_end, client, services } = data;
|
||||||
const clientId = extractId(client);
|
const clientId = extractId(client);
|
||||||
|
|
||||||
const slotId = extractId(data.slot);
|
const slotId = extractId(data.slot);
|
||||||
|
|
||||||
|
// Проверка наличия обязательных полей
|
||||||
|
if (!slotId) throw new Error(ERR_MISSING_SLOT);
|
||||||
|
if (!clientId) throw new Error(ERR_MISSING_CLIENT);
|
||||||
|
if (!extractId(services)) throw new Error(ERR_MISSING_SERVICE);
|
||||||
|
|
||||||
|
// Проверка корректности времени заказа.
|
||||||
if (!time_start || !time_end) {
|
if (!time_start || !time_end) {
|
||||||
throw new Error(ERR_INVALID_TIME);
|
throw new Error(ERR_INVALID_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeToDate(time_start) >= timeToDate(time_end)) {
|
if (timeToDate(time_start) >= timeToDate(time_end)) {
|
||||||
throw new Error(ERR_INVALID_TIME);
|
throw new Error(ERR_INVALID_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isClientActive = await strapi.db
|
// Получаем слот
|
||||||
|
const slot = await strapi.db.query('api::slot.slot').findOne({
|
||||||
|
where: { id: slotId },
|
||||||
|
populate: ['master'],
|
||||||
|
});
|
||||||
|
if (!slot) throw new Error(ERR_MISSING_SLOT);
|
||||||
|
|
||||||
|
// 1. Слот не должен быть закрыт
|
||||||
|
if (slot.state === 'closed') {
|
||||||
|
throw new Error(ERR_SLOT_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем клиента
|
||||||
|
const clientEntity = await strapi.db
|
||||||
.query('api::customer.customer')
|
.query('api::customer.customer')
|
||||||
.findOne({
|
.findOne({
|
||||||
where: {
|
where: { id: clientId },
|
||||||
id: clientId,
|
populate: { masters: true },
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
console.log('🚀 ~ clientEntity ~ clientEntity:', clientEntity);
|
||||||
|
if (!clientEntity) throw new Error(ERR_MISSING_CLIENT);
|
||||||
|
|
||||||
if (!isClientActive) {
|
// Проверка активности клиента
|
||||||
|
if (!clientEntity.active) {
|
||||||
throw new Error(ERR_INACTIVE_CLIENT);
|
throw new Error(ERR_INACTIVE_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
const slot = await strapi.db.query('api::slot.slot').findOne({
|
// Получаем мастера слота
|
||||||
where: {
|
const slotMaster = slot.master;
|
||||||
id: slotId,
|
if (!slotMaster) throw new Error(ERR_INVALID_MASTER);
|
||||||
},
|
if (!slotMaster.active || slotMaster.role !== 'master') {
|
||||||
populate: ['master'],
|
|
||||||
});
|
|
||||||
|
|
||||||
const master = slot.master;
|
|
||||||
|
|
||||||
const isMasterActive = master.active && master.role === 'master';
|
|
||||||
|
|
||||||
if (!isMasterActive) {
|
|
||||||
throw new Error(ERR_INACTIVE_MASTER);
|
throw new Error(ERR_INACTIVE_MASTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Проверка ролей и связей
|
||||||
|
const isClientMaster = clientEntity.role === 'master';
|
||||||
|
const slotMasterId = slotMaster.id;
|
||||||
|
|
||||||
|
if (!isClientMaster) {
|
||||||
|
// Клиент не должен быть мастером слота
|
||||||
|
if (clientEntity.id === slotMasterId) {
|
||||||
|
throw new Error(ERR_INVALID_CLIENT);
|
||||||
|
}
|
||||||
|
// Клиент должен быть в списке клиентов мастера
|
||||||
|
const masters = clientEntity.masters?.map(m => m.id) || [];
|
||||||
|
if (!masters.includes(slotMasterId)) {
|
||||||
|
throw new Error(ERR_INVALID_MASTER);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Мастер не может записать другого мастера
|
||||||
|
if (slotMasterId !== clientEntity.id) {
|
||||||
|
throw new Error(ERR_INVALID_MASTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка пересечений заказов по времени.
|
||||||
const overlappingEntities = await strapi.db
|
const overlappingEntities = await strapi.db
|
||||||
.query('api::order.order')
|
.query('api::order.order')
|
||||||
.findMany({
|
.findMany({
|
||||||
@ -83,7 +121,6 @@ export default {
|
|||||||
},
|
},
|
||||||
populate: ['slot'],
|
populate: ['slot'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (overlappingEntities.length > 0) {
|
if (overlappingEntities.length > 0) {
|
||||||
throw new Error(ERR_OVERLAPPING_TIME);
|
throw new Error(ERR_OVERLAPPING_TIME);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user