feat(database-schema): добавляет ссылку на активный чат в схему профиля пользователя

 feat(likes.service): обновляет логику создания лайков с учетом активного чата

 feat(likes.module): импортирует модуль Gateways для работы с чатами

 feat(feed.service): добавляет условие для фильтрации профилей без активного чата

 feat(storage.service): устанавливает политику доступа к бакету S3 для получения объектов

 feat(likes-response.dto): добавляет поле чата в ответ на лайк

 feat(media.controller): добавляет описание для загрузки медиафайлов

 feat(chat.service): добавляет возможность закрытия чата с отчетом или сообщением

 feat(chat.controller): обновляет метод закрытия чата для обработки отчетов

 feat(app.module): добавляет модуль Dev для разработки в не продакшн среде
This commit is contained in:
Oscar
2026-06-09 15:39:38 +03:00
parent 97f8891861
commit cd98f04987
14 changed files with 251 additions and 36 deletions

View File

@@ -6,9 +6,10 @@ import {
} from '@nestjs/common';
import { and, eq, or } from 'drizzle-orm';
import { DrizzleService } from '../../database/drizzle.service';
import { chat, match, message, profile, user } from '../../database/schema';
import { chat, match, message, profile, report, user } from '../../database/schema';
import { NotificationsService } from '../../notifications/notifications.service';
import { CreateChatDto } from './dto/create-chat.dto';
import { CloseChatDto, CloseChatType } from './dto/close-chat.dto';
import { SendMessageDto } from './dto/send-message.dto';
@Injectable()
@@ -76,7 +77,7 @@ export class ChatService {
return newChat;
}
async closeChat(userId: string, profileId: string, chatId: string) {
async closeChat(userId: string, profileId: string, chatId: string, dto: CloseChatDto) {
await this.assertProfileOwnership(userId, profileId);
const [foundChat] = await this.drizzleService.db
@@ -90,6 +91,39 @@ export class ChatService {
throw new ForbiddenException('Not a chat participant');
}
const otherProfileId = foundChat.profile1Id === profileId
? foundChat.profile2Id
: foundChat.profile1Id;
let messageText: string;
if (dto.type === CloseChatType.Report) {
if (!dto.reportReason) throw new BadRequestException('reportReason is required for type=report');
messageText = dto.reportDescription
? `Жалоба: ${dto.reportReason}. ${dto.reportDescription}`
: `Жалоба: ${dto.reportReason}`;
await this.drizzleService.db
.insert(report)
.values({
sourceProfileId: profileId,
entityId: otherProfileId,
entityType: 'profile',
description: messageText,
} as any);
} else {
messageText = dto.cancelMessage?.trim() || 'Диалог завершён';
}
await this.drizzleService.db
.insert(message)
.values({
chatId,
profileId,
text: messageText,
mediaUrl: null,
mediaType: null,
} as any);
await this.drizzleService.db
.update(chat)
.set({ status: 'closed' } as any)
@@ -108,12 +142,7 @@ export class ChatService {
return this.drizzleService.db
.select()
.from(chat)
.where(
and(
or(eq(chat.profile1Id, profileId), eq(chat.profile2Id, profileId)),
eq(chat.status, 'active'),
),
);
.where(or(eq(chat.profile1Id, profileId), eq(chat.profile2Id, profileId)));
}
async getChatMessages(userId: string, profileId: string, chatId: string, page = 1, limit = 50) {