* chore(docker): add healthcheck to service in docker-compose.yml and update deploy workflow to include docker compose down * refactor(orders): add useOrdersInfiniteQuery for improved pagination and add load more button in orders list components * refactor(graphql): remove NotifyService and related notification logic from orders and API, clean up unused dependencies * refactor(api): streamline customer, order, service, and slot actions by wrapping server functions with client action utility to rethrow error messages to client
137 lines
4.4 KiB
TypeScript
137 lines
4.4 KiB
TypeScript
import { getClientWithToken } from '../apollo/client';
|
|
import * as GQL from '../types';
|
|
import { BaseService } from './base';
|
|
import { CustomersService } from './customers';
|
|
import { ServicesService } from './services';
|
|
import { type VariablesOf } from '@graphql-typed-document-node/core';
|
|
import { isCustomerMaster } from '@repo/utils/customer';
|
|
import { getMinutes } from '@repo/utils/datetime-format';
|
|
import dayjs from 'dayjs';
|
|
|
|
const ERRORS = {
|
|
INVALID_SERVICE_DURATION: 'Invalid service duration',
|
|
MISSING_CLIENT: 'Missing client',
|
|
MISSING_ORDER: 'Order not found',
|
|
MISSING_SERVICE_ID: 'Missing service id',
|
|
MISSING_SERVICES: 'Missing services',
|
|
MISSING_SLOT: 'Missing slot id',
|
|
MISSING_START_TIME: 'Missing time start',
|
|
MISSING_USER: 'User not found',
|
|
NO_PERMISSION: 'No permission',
|
|
};
|
|
|
|
export class OrdersService extends BaseService {
|
|
async createOrder(variables: VariablesOf<typeof GQL.CreateOrderDocument>) {
|
|
// Проверки на существование обязательных полей для предотвращения ошибок типов
|
|
if (!variables.input.slot) throw new Error(ERRORS.MISSING_SLOT);
|
|
if (!variables.input.services?.length) throw new Error(ERRORS.MISSING_SERVICES);
|
|
if (!variables.input.services[0]) throw new Error(ERRORS.MISSING_SERVICE_ID);
|
|
if (!variables.input.datetime_start) throw new Error(ERRORS.MISSING_START_TIME);
|
|
if (!variables.input.client) throw new Error(ERRORS.MISSING_CLIENT);
|
|
|
|
const customersService = new CustomersService(this.customer);
|
|
const servicesService = new ServicesService(this.customer);
|
|
|
|
const { customer } = await customersService.getCustomer(this.customer);
|
|
if (!customer) throw new Error(ERRORS.MISSING_USER);
|
|
|
|
const { service } = await servicesService.getService({
|
|
documentId: variables.input.services[0],
|
|
});
|
|
if (!service?.duration) throw new Error(ERRORS.INVALID_SERVICE_DURATION);
|
|
|
|
const datetimeEnd = dayjs(variables.input.datetime_start)
|
|
.add(getMinutes(service.duration), 'minute')
|
|
.toISOString();
|
|
|
|
const { mutate } = await getClientWithToken();
|
|
|
|
const mutationResult = await mutate({
|
|
mutation: GQL.CreateOrderDocument,
|
|
variables: {
|
|
...variables,
|
|
input: {
|
|
...variables.input,
|
|
datetime_end: datetimeEnd,
|
|
state: isCustomerMaster(customer)
|
|
? GQL.Enum_Order_State.Approved
|
|
: GQL.Enum_Order_State.Created,
|
|
},
|
|
},
|
|
});
|
|
|
|
const error = mutationResult.errors?.at(0);
|
|
if (error) throw new Error(error.message);
|
|
|
|
return mutationResult.data;
|
|
}
|
|
|
|
async getOrder(variables: VariablesOf<typeof GQL.GetOrderDocument>) {
|
|
const { query } = await getClientWithToken();
|
|
|
|
const result = await query({
|
|
query: GQL.GetOrderDocument,
|
|
variables,
|
|
});
|
|
|
|
return result.data;
|
|
}
|
|
|
|
async getOrders(variables: VariablesOf<typeof GQL.GetOrdersDocument>) {
|
|
const { query } = await getClientWithToken();
|
|
|
|
const result = await query({
|
|
query: GQL.GetOrdersDocument,
|
|
variables,
|
|
});
|
|
|
|
return result.data;
|
|
}
|
|
|
|
async updateOrder(variables: VariablesOf<typeof GQL.UpdateOrderDocument>) {
|
|
const customersService = new CustomersService(this.customer);
|
|
const { customer } = await customersService.getCustomer(this.customer);
|
|
|
|
if (!customer) throw new Error(ERRORS.MISSING_USER);
|
|
|
|
const { query } = await getClientWithToken();
|
|
|
|
const {
|
|
data: { order },
|
|
} = await query({
|
|
query: GQL.GetOrderDocument,
|
|
variables: { documentId: variables.documentId },
|
|
});
|
|
|
|
if (!order) throw new Error(ERRORS.MISSING_ORDER);
|
|
|
|
const isOrderClient = order.client?.documentId === customer.documentId;
|
|
const isOrderMaster = order.slot?.master?.documentId === customer.documentId;
|
|
|
|
if (!isOrderClient && !isOrderMaster) throw new Error(ERRORS.NO_PERMISSION);
|
|
|
|
if (isOrderClient && Object.keys(variables.data).length > 1)
|
|
throw new Error(ERRORS.NO_PERMISSION);
|
|
|
|
if (
|
|
isOrderClient &&
|
|
variables.data.state &&
|
|
variables.data.state !== GQL.Enum_Order_State.Cancelling
|
|
) {
|
|
throw new Error(ERRORS.NO_PERMISSION);
|
|
}
|
|
|
|
const { mutate } = await getClientWithToken();
|
|
|
|
const mutationResult = await mutate({
|
|
mutation: GQL.UpdateOrderDocument,
|
|
variables,
|
|
});
|
|
|
|
const error = mutationResult.errors?.at(0);
|
|
if (error) throw new Error(error.message);
|
|
|
|
return mutationResult.data;
|
|
}
|
|
}
|