91 lines
3.2 KiB
TypeScript
91 lines
3.2 KiB
TypeScript
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);
|
|
}
|
|
}
|