Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/chats business entity #110

Draft
wants to merge 71 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b21e56b
feat: Cоздаёт базовую фаловую структуру для сущности бизнес-логики 'Ч…
aleksr777 Jul 3, 2024
3579716
feat: удалил лишний код, реализовал сущность бизнес-логики Chats, ско…
aleksr777 Jul 6, 2024
ee7c761
fix: удалил лишний импорт контроллера
aleksr777 Jul 6, 2024
41bd68d
fix: удалил лишний файл репозитория из entities, подключился к репози…
aleksr777 Jul 13, 2024
82edbca
feat: Cоздаёт базовую фаловую структуру для сущности бизнес-логики 'Ч…
aleksr777 Jul 14, 2024
185dbf6
feat: удалил лишний код, реализовал сущность бизнес-логики Chats, ско…
aleksr777 Jul 14, 2024
49657ca
fix: удалил лишний импорт контроллера
aleksr777 Jul 14, 2024
d0cdafa
fix: удалил лишний файл репозитория из entities, подключился к репози…
aleksr777 Jul 14, 2024
3b2ab25
Merge branch 'feature/chats-business-entity' of github.com:ya-pomogau…
aleksr777 Jul 14, 2024
0183b3b
refactor: вернулся к исходному коду
aleksr777 Jul 14, 2024
14087f0
refactor: вернулся к исходному коду
aleksr777 Jul 14, 2024
73fded0
fix: обновил код сущности, запросы к базе данных идёт теперь напрямую…
aleksr777 Jul 14, 2024
2e14c7a
fix: поправки по замечаниям
aleksr777 Jul 19, 2024
235905f
fix: поправка в типизации
aleksr777 Jul 19, 2024
5beb219
fix: упростил код поиска сообщений чата
aleksr777 Jul 19, 2024
38bc45d
fix: незначительные поправки
aleksr777 Jul 23, 2024
9f7ef5e
Merge branch 'development' into feature/chats-business-entity
aleksr777 Jul 23, 2024
1e9af4c
fix: поправки в сущности, создал тест
aleksr777 Jul 25, 2024
ef92513
Merge branch 'development' of github.com:ya-pomogau/backend into deve…
aleksr777 Jul 25, 2024
fb7a238
Merge branch 'development' into feature/chats-business-entity
aleksr777 Jul 25, 2024
95e6c49
fix: временно удалил подключение к app.module, чтобы не возникало ошибок
aleksr777 Jul 25, 2024
28ad4f4
fix: внёс необходимые поправки, создал новые чаты, исправил тест для …
aleksr777 Jul 28, 2024
34815a0
Merge branch 'development' into feature/chats-business-entity
aleksr777 Jul 29, 2024
4b59952
Merge branch 'development' into feature/chats-business-entity
aleksr777 Jul 30, 2024
55aabe5
Merge branch 'development' into feature/chats-business-entity
aleksr777 Aug 1, 2024
c9fe5fd
fix: добавлены тесты
aleksr777 Aug 1, 2024
632637a
Merge branch 'development' into feature/chats-business-entity
aleksr777 Aug 2, 2024
9b25b61
fix: поправки в тестах
aleksr777 Aug 2, 2024
9c7a943
feat: добавил недостающие методы в сущности
aleksr777 Aug 8, 2024
b69869b
Merge branch 'development' into feature/chats-business-entity
aleksr777 Aug 8, 2024
5d3bf1d
fix: поправки в типизации
aleksr777 Aug 8, 2024
6cd68db
fix: незначительные поправки в коде, добавлен геттер для получения со…
aleksr777 Aug 9, 2024
0432685
feat: написал каркас для общего chat.entity
aleksr777 Aug 9, 2024
bb7f530
feat: создан метод createChat, поправки типизации, создан метод loadM…
aleksr777 Aug 11, 2024
019c57d
feat: Добавлен метод findChatByParams для поиска чата по параметрам
aleksr777 Aug 11, 2024
cd4b278
feat: добавлен метод addMessage, небольшие поправки в остальном коде
aleksr777 Aug 12, 2024
7be02f2
feat: добавлен метод closeChat, дополнительные правки по всему коду.
aleksr777 Aug 12, 2024
5bfc846
feat: добавил интерфейс и тест, удалил лишние файлы
aleksr777 Aug 12, 2024
51caeb0
Merge branch 'development' into feature/chats-business-entity
aleksr777 Aug 12, 2024
1c247a5
feat: написан тест создания чатов для разных типов
aleksr777 Aug 17, 2024
24bf152
Merge branch 'development' into feature/chats-business-entity
aleksr777 Aug 17, 2024
33d9d51
feat: добавлены тесты закрытия чата, поправки в основном коде
aleksr777 Aug 17, 2024
c5d77c7
feat: добавлен тест загрузки сообщений, поправки в entity
aleksr777 Aug 17, 2024
6c6cca3
feat: добавлен тест добавления сообщения и тест поиска чата по параме…
aleksr777 Aug 17, 2024
21b1828
fix: Исправил возвращаемый тип данных при создании чата и поиска чата…
aleksr777 Aug 18, 2024
6082b4e
fix: переименовал интерфейс
aleksr777 Aug 18, 2024
a5a0d9f
fix: внёс поправки в описании геттеров в интерфейсе.
aleksr777 Aug 18, 2024
4c87ebd
fix: удалён декоратор Injectable
aleksr777 Aug 26, 2024
e6847c2
fix: поправка в тестах
aleksr777 Aug 26, 2024
a56d7f8
fix: добавлен общий тип для конфликтных чатов
aleksr777 Aug 26, 2024
a371b3e
fix: поправка в методе createChat
aleksr777 Aug 26, 2024
271fe3f
fix: поправка в типизации dto
aleksr777 Aug 26, 2024
90f1de2
fix: данные вносятся теперь только после получения ответа от БД, уточ…
aleksr777 Aug 26, 2024
aea6ff6
refactor: изменения в типизации
aleksr777 Aug 27, 2024
bfdb894
fix: добавлен поиск сообщений чатов по нескольким id, поправки в тестах.
aleksr777 Aug 27, 2024
fd90134
feat: вынес константы теста в отдельный файл
aleksr777 Aug 27, 2024
5f99c13
feat: добавил проверки для геттеров
aleksr777 Aug 28, 2024
ce9f525
fix: подправил loadMessages()
aleksr777 Aug 28, 2024
175ad4b
Merge branch 'development' into feature/chats-business-entity
kspshnik Nov 27, 2024
8d0e9f3
[Merge] Merged `development` into `feature/business-chat-entity` / Te…
kspshnik Nov 27, 2024
73ed128
[Merge] Merged `development` into `feature/business-chat-entity` / Te…
kspshnik Nov 27, 2024
eca4093
Merge branch 'feature/chats-business-entity' of github.com:ya-pomogau…
kspshnik Nov 27, 2024
7b551da
[Refactor] Allowed `null` for `chatId` in `MessageInterface` as sign …
kspshnik Nov 28, 2024
665757f
[Interim/ReviewRequest] Created Chat Entity
kspshnik Dec 12, 2024
e04a429
[Interim/ReviewRequest] Created Chat Entity
kspshnik Dec 12, 2024
5e531ad
Merge remote-tracking branch 'origin/feature/chats-business-entity' i…
kspshnik Dec 12, 2024
3f88f72
Merge branch 'development' into feature/chats-business-entity
kspshnik Dec 13, 2024
5febb88
[Fix] Fixed typing to avoid circular deps
kspshnik Dec 14, 2024
2354ac0
[New] Chat Entity interface
kspshnik Dec 14, 2024
c27de25
[Fix] Fix typings & direct model injection
kspshnik Dec 17, 2024
da60ff8
[Fix] No generics in entity + fixes
kspshnik Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { ContactsModule } from './core/contacts/contacts.module';
import { TasksModule } from './core/tasks/tasks.module';
import { PolicyModule } from './core/policy/policy.module';
import { SystemApiModule } from './api/system-api/system-api.module';
import { ChatEntity } from './entities/chats/chat.entity';

@Module({
imports: [
Expand Down Expand Up @@ -59,6 +60,7 @@ import { SystemApiModule } from './api/system-api/system-api.module';
provide: APP_GUARD,
useClass: JwtAuthGuard,
},
ChatEntity,
],
})
export class AppModule {}
1 change: 1 addition & 0 deletions src/common/types/chat.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface MessageInterface {
author: ObjectId;
}
export interface ChatInterface {
_id: string;
users: [ObjectId, ObjectId | null];
messages: MessageInterface[];
isOpen: boolean;
Expand Down
3 changes: 3 additions & 0 deletions src/datalake/users/schemas/volunteer.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export class Volunteer extends Document implements VolunteerUserModelInterface {

@Prop({ required: false, default: false, type: SchemaTypes.Boolean })
keys: boolean;

@Prop({ type: SchemaTypes.Number, default: 0 })
tasksCompleted: number;
}

export const VolunteerUserSchema =
Expand Down
100 changes: 100 additions & 0 deletions src/entities/chats/chat.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Injectable, Scope } from '@nestjs/common';
import { ChatsRepository } from '../../datalake/chats/chats.repository';
import { MessagesRepository } from '../../datalake/messages/messages.repository';
import { ChatInterface } from '../../common/types/chat.types';
import { MessageInterface } from '../../common/types/chats.types';
import { Types } from 'mongoose';

@Injectable({ scope: Scope.TRANSIENT })
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А точно не REQUEST? Можешь обосновать выбор?
(Это не предложение поменять, тут надо подумать)

export class ChatEntity {
private metadata: ChatInterface[];
private messages: { [chatId: string]: MessageInterface[] };

constructor(
private readonly chatsRepository: ChatsRepository,
private readonly messagesRepository: MessagesRepository
) {
this.metadata = [];
this.messages = {};
}

async createChat(
metadata: Partial<ChatInterface>,
messages: Partial<MessageInterface>[]
): Promise<ChatEntity> {
const chat = await this.chatsRepository.create(metadata as any) as ChatInterface;
this.metadata.push(chat);
if (messages.length > 0) {
const savedMessages = await Promise.all(
messages.map((message) =>
this.messagesRepository.create({ ...message, chatId: chat._id } as any)
)
);
this.messages[chat._id.toString()] = savedMessages as MessageInterface[];
} else {
this.messages[chat._id.toString()] = [];
}
return this;
}

async findChatByParams(params: Partial<ChatInterface>): Promise<ChatEntity> {
const chats = await this.chatsRepository.find(params) as ChatInterface[];
this.metadata = chats;
this.messages = {}; // Сброс сообщений при новом поиске
for (const chat of chats) {
const chatMessages = await this.messagesRepository.find({ chatId: chat._id }) as MessageInterface[];
this.messages[chat._id.toString()] = chatMessages;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В одном экземпляре - данные только одного чата

}
return this;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А если там уже есть сообщения? Их тоже надо найти :)

}

async findConflictingChats(params: Partial<ChatInterface>): Promise<ChatEntity> {
// Поиск чатов по типу
const primaryChats = await this.findChatByParams(params);
const conflictingChats: ChatInterface[] = [];
this.metadata = primaryChats.metadata;
this.messages = primaryChats.messages;
// Поиск конфликтных чатов, которые указывают друг на друга
for (const primaryChat of this.metadata) {
const conflictChats = await this.chatsRepository.find({
taskId: primaryChat.taskId,
ownerId: { $ne: primaryChat.ownerId },
}) as ChatInterface[];
if (conflictChats.length > 0) {
conflictingChats.push(...conflictChats);
}
Copy link
Contributor

@IvannaBalanyuk IvannaBalanyuk Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Привет! Кажется тут потеряны сообщения админа 🙈
Ожидается, что для конфликтного чата метод вернёт данные типа ConflictChatContentTuple:

image

Вот этот интерфейс:

image

VolunteerChatContent и RecipientChatContent - это, по-хорошему, ВЕСЬ контент чата, т.е. и сообщения админа тоже.
Вопрос в том, как их вычленить.
@kspshnik мне чёт кажется, что при текущем интерфейсе сообщения мы не сможем разделить сообщения админа по нужным кучкам:

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. А зачем их вычленять-то?
  2. Поле author в MessageInterface нам зачем? :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. А зачем их вычленять-то?
  2. Поле author в MessageInterface нам зачем? :)
  1. Чтобы часть положить в чат с волонтером, а часть - в чат с реципиентом;
  2. По значению в поле author мы получим все сообщения админа - и те, что волонтеру, и те, что реципиенту.

По chatId не выделить - судя по коду метода createChat(...) идентификатор создается на общий CONFLICT_CHAT. В методе addMessage(...), кстати, не вижу сохранения сообщений администратора для конфликтного чата.

В любом случае сейчас для конфликта метод loadMessages(...) возвращает только сообщения волонтера и реципиента. Так задумано?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. А зачем их вычленять-то?
  2. Поле author в MessageInterface нам зачем? :)
  1. Чтобы часть положить в чат с волонтером, а часть - в чат с реципиентом;

Это должно делаться по chatId. В кортеже метаинформации - оба идентификатора, обоих чатов.

  1. По значению в поле author мы получим все сообщения админа - и те, что волонтеру, и те, что реципиенту.

Но они будут в разных элементах кортежа ConflictChatContentTuple ;o)

По chatId не выделить - судя по коду метода createChat(...) идентификатор создается на общий CONFLICT_CHAT. В методе addMessage(...), кстати, не вижу сохранения сообщений администратора для конфликтного чата.
В любом случае сейчас для конфликта метод loadMessages(...) возвращает только сообщения волонтера и реципиента. Так задумано?

С идентификаторами там чуть-чуть поменяется, вспомни начало прошлого QA.
А в массивах хранятся сообщения всего чата, например в массиве с чатом с волонтёром сообщения и волонтёра и администратора.

}
// Объединение найденных чатов и сообщений
for (const conflictChat of conflictingChats) {
const conflictMessages = await this.messagesRepository.find({ chatId: conflictChat._id }) as MessageInterface[];
this.metadata.push(conflictChat);
this.messages[conflictChat._id.toString()] = conflictMessages;
}
return this;
}

async addMessage(chatId: string, message: Partial<MessageInterface>): Promise<ChatEntity> {
const newMessage = await this.messagesRepository.create({
...message,
chatId: new Types.ObjectId(chatId),
} as any);
if (!this.messages[chatId]) {
this.messages[chatId] = [];
}
this.messages[chatId].push(newMessage as MessageInterface);
return this;
}

async closeChat(chatId: string): Promise<ChatEntity> {
const objectId = new Types.ObjectId(chatId);
const chats = await this.chatsRepository.find({ _id: objectId }) as ChatInterface[];
if (chats.length > 0) {
await this.chatsRepository['model'].updateOne({ _id: objectId }, { isOpen: false }).exec();
const chatIndex = this.metadata.findIndex((c) => c._id.toString() === chatId);
if (chatIndex !== -1) {
this.metadata[chatIndex].isOpen = false;
}
}
return this;
}
}