refactor(api): replace CustomerProfile with UserProfile and streamline user retrieval across services

This commit is contained in:
vchikalkin 2025-08-02 18:37:08 +03:00
parent 25fb9269fc
commit 6c4e6113f6
5 changed files with 71 additions and 37 deletions

View File

@ -1,15 +1,39 @@
type CustomerProfile = {
/* eslint-disable canonical/id-match */
import { getClientWithToken } from '../apollo/client';
import * as GQL from '../types';
const ERRORS = {
MISSING_TELEGRAM_ID: 'Missing telegram id',
NOT_FOUND_CUSTOMER: 'Customer not found',
};
type UserProfile = {
telegramId: number;
};
export class BaseService {
protected customer: CustomerProfile;
protected _user: UserProfile;
constructor(customer: CustomerProfile) {
if (!customer?.telegramId) {
throw new Error('Invalid customer profile: telegramId required');
constructor(user: UserProfile) {
if (!user?.telegramId) {
throw new Error(ERRORS.MISSING_TELEGRAM_ID);
}
this.customer = customer;
this._user = user;
}
protected async _getUser() {
const { query } = await getClientWithToken();
const result = await query({
query: GQL.GetCustomerDocument,
variables: this._user,
});
const customer = result.data.customers.at(0);
if (!customer) throw new Error(ERRORS.NOT_FOUND_CUSTOMER);
return { customer };
}
}

View File

@ -39,7 +39,7 @@ export class CustomersService extends BaseService {
const result = await query({
query: GQL.GetClientsDocument,
variables: {
telegramId: variables?.telegramId || this.customer.telegramId,
telegramId: variables?.telegramId || this._user.telegramId,
},
});
@ -65,7 +65,7 @@ export class CustomersService extends BaseService {
const result = await query({
query: GQL.GetMastersDocument,
variables: {
telegramId: variables?.telegramId || this.customer.telegramId,
telegramId: variables?.telegramId || this._user.telegramId,
},
});
@ -75,9 +75,8 @@ export class CustomersService extends BaseService {
async updateCustomer(
variables: Omit<VariablesOf<typeof GQL.UpdateCustomerDocument>, 'documentId'>,
) {
const { customer } = await this.getCustomer(this.customer);
const { customer } = await this._getUser();
if (!customer) throw new Error('Customer not found');
const { mutate } = await getClientWithToken();
const mutationResult = await mutate({

View File

@ -1,7 +1,6 @@
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';
@ -16,12 +15,13 @@ const ERRORS = {
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>) {
const { customer } = await this._getUser();
// Проверки на существование обязательных полей для предотвращения ошибок типов
if (!variables.input.slot) throw new Error(ERRORS.MISSING_SLOT);
if (!variables.input.services?.length) throw new Error(ERRORS.MISSING_SERVICES);
@ -29,15 +29,12 @@ export class OrdersService extends BaseService {
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 servicesService = new ServicesService(this._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)
@ -89,10 +86,7 @@ export class OrdersService extends BaseService {
}
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 { customer } = await this._getUser();
const { query } = await getClientWithToken();

View File

@ -1,14 +1,15 @@
import { getClientWithToken } from '../apollo/client';
import * as GQL from '../types';
import { BaseService } from './base';
import { CustomersService } from './customers';
import { type VariablesOf } from '@graphql-typed-document-node/core';
const ERRORS = {
NO_PERMISSION: 'No permission',
};
export class ServicesService extends BaseService {
async createService(variables: VariablesOf<typeof GQL.CreateServiceDocument>) {
const customerService = new CustomersService(this.customer);
const { customer } = await customerService.getCustomer(this.customer);
const { customer } = await this._getUser();
const { mutate } = await getClientWithToken();
@ -70,12 +71,10 @@ export class ServicesService extends BaseService {
private async checkPermission(
variables: Pick<VariablesOf<typeof GQL.GetServiceDocument>, 'documentId'>,
) {
const customerService = new CustomersService(this.customer);
const { customer } = await customerService.getCustomer(this.customer);
const { customer } = await this._getUser();
const { service } = await this.getService({ documentId: variables.documentId });
if (service?.master?.documentId !== customer?.documentId) throw new Error('No permission');
if (service?.master?.documentId !== customer?.documentId) throw new Error(ERRORS.NO_PERMISSION);
}
}

View File

@ -1,17 +1,21 @@
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 { getMinutes } from '@repo/utils/datetime-format';
import dayjs from 'dayjs';
const ERRORS = {
MISSING_DATE: 'Missing date',
MISSING_SERVICE: 'Missing service',
MISSING_SERVICE_ID: 'Missing service id',
NO_PERMISSION: 'No permission',
};
export class SlotsService extends BaseService {
async createSlot(variables: VariablesOf<typeof GQL.CreateSlotDocument>) {
const customerService = new CustomersService(this.customer);
const { customer } = await customerService.getCustomer(this.customer);
const { customer } = await this._getUser();
const { mutate } = await getClientWithToken();
@ -33,6 +37,8 @@ export class SlotsService extends BaseService {
}
async deleteSlot(variables: VariablesOf<typeof GQL.DeleteSlotDocument>) {
await this.checkPermission(variables);
const { mutate } = await getClientWithToken();
const mutationResult = await mutate({
@ -50,8 +56,8 @@ export class SlotsService extends BaseService {
variables: VariablesOf<typeof GQL.GetSlotsDocument>,
context: { service: GQL.ServiceFiltersInput },
) {
if (!variables.filters?.datetime_start) throw new Error('Missing date');
if (!context?.service?.documentId?.eq) throw new Error('Missing service id');
if (!variables.filters?.datetime_start) throw new Error(ERRORS.MISSING_DATE);
if (!context?.service?.documentId?.eq) throw new Error(ERRORS.MISSING_SERVICE_ID);
const { query } = await getClientWithToken();
@ -67,13 +73,13 @@ export class SlotsService extends BaseService {
if (getSlotsResult.error) throw new Error(getSlotsResult.error.message);
const servicesService = new ServicesService(this.customer);
const servicesService = new ServicesService(this._user);
const { service } = await servicesService.getService({
documentId: context.service.documentId.eq,
});
if (!service) throw new Error('Service not found');
if (!service) throw new Error(ERRORS.MISSING_SERVICE);
const serviceDuration = getMinutes(service.duration);
@ -135,6 +141,8 @@ export class SlotsService extends BaseService {
}
async updateSlot(variables: VariablesOf<typeof GQL.UpdateSlotDocument>) {
await this.checkPermission(variables);
const { mutate } = await getClientWithToken();
const mutationResult = await mutate({
@ -147,4 +155,14 @@ export class SlotsService extends BaseService {
return mutationResult.data;
}
private async checkPermission(
variables: Pick<VariablesOf<typeof GQL.GetSlotDocument>, 'documentId'>,
) {
const { customer } = await this._getUser();
const { slot } = await this.getSlot({ documentId: variables.documentId });
if (slot?.master?.documentId !== customer?.documentId) throw new Error(ERRORS.NO_PERMISSION);
}
}