This commit is contained in:
2026-08-28 17:31:02 +02:00
commit 2b30e8bd39
694 changed files with 49243 additions and 0 deletions
@@ -0,0 +1,90 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import dayjs from '../../../plugins/dayjs';
import { EncryptionService } from '../../encryption/services/EncryptionService';
import { NotificationService } from '../../notifications/services/NotificationService';
import { Order } from '../entities/Order';
import { OrderMessage } from '../entities/OrderMessage';
import { OrderMessageSender } from '../types/OrderMessageSender';
@Injectable()
export class OrderChatService {
constructor(
@InjectRepository(Order)
private readonly orderRepo: Repository<Order>,
@InjectRepository(OrderMessage)
private readonly messageRepo: Repository<OrderMessage>,
private readonly encryptionService: EncryptionService,
private readonly notificationService: NotificationService
) {}
async listMessagesForOrder(orderId: string): Promise<OrderMessage[]> {
const messages = await this.messageRepo.find({
where: { order: { id: orderId } },
order: { createdAt: 'ASC' }
});
this.encryptionService.decryptPlaintextFieldInPlace(messages, 'body');
return messages;
}
countUnreadBuyerMessages(order: Pick<Order, 'staffChatLastReadAt' | 'messages'>): number {
const readAfter = order.staffChatLastReadAt ? dayjs(order.staffChatLastReadAt) : dayjs(0);
return (order.messages ?? []).filter(
message => message.sender === OrderMessageSender.Buyer && dayjs(message.createdAt).isAfter(readAfter)
).length;
}
async markChatRead(orderId: string): Promise<void> {
const orderExists = await this.orderRepo.exists({ where: { id: orderId } });
if (!orderExists) {
throw new NotFoundException('Order not found');
}
await this.orderRepo.update(orderId, { staffChatLastReadAt: new Date() });
}
async createMessage(orderId: string, sender: OrderMessageSender, body: string): Promise<OrderMessage[]> {
const orderExists = await this.orderRepo.exists({ where: { id: orderId } });
if (!orderExists) {
throw new NotFoundException('Order not found');
}
const entity = this.messageRepo.create({
order: { id: orderId },
sender,
body: this.encryptionService.encryptPlaintext(body)
});
await this.messageRepo.insert(entity);
if (sender === OrderMessageSender.Buyer) {
this.notificationService.sendNotification(orderId, 'newBuyerMessage');
}
return this.listMessagesForOrder(orderId);
}
async deleteMessage(orderId: string, messageId: string, sender: OrderMessageSender): Promise<OrderMessage[]> {
const message = await this.messageRepo.findOne({
where: {
id: messageId,
order: { id: orderId },
sender
}
});
if (!message) {
throw new NotFoundException('We could not find that message.');
}
await this.messageRepo.delete(message.id);
return this.listMessagesForOrder(orderId);
}
}