import { BadRequestException, HttpStatus, Injectable, NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { plainToClass } from 'class-transformer'; import AppResponse from 'src/response/app-response'; import { Repository } from 'typeorm'; import { BidHistory } from '../entities/bid-history.entity'; import { Bid } from '../entities/bid.entity'; import { CreateBidHistoryDto } from '../dto/bid-history/create-bid-history.dto'; import { BotTelegramApi } from '../apis/bot-telegram.api'; import { SendMessageHistoriesService } from './send-message-histories.service'; import { NotificationService } from '@/modules/notification/notification.service'; import { isTimeReached } from '@/ultils'; import { BidsService } from './bids.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { Event } from '../utils/events'; @Injectable() export class BidHistoriesService { constructor( @InjectRepository(BidHistory) readonly bidHistoriesRepo: Repository, // @InjectRepository(Bid) // readonly bidsRepo: Repository, private readonly botTelegramApi: BotTelegramApi, readonly sendMessageHistoriesService: SendMessageHistoriesService, private readonly notificationService: NotificationService, private readonly bidsService: BidsService, private eventEmitter: EventEmitter2, ) {} async index() { return this.bidHistoriesRepo.find(); } async create({ price, bid_id }: CreateBidHistoryDto) { // Tìm thông tin bid từ database const bid = await this.bidsService.bidsRepo.findOne({ where: { id: bid_id }, relations: { web_bid: true }, }); // Nếu không tìm thấy bid, trả về lỗi 404 if (!bid) throw new NotFoundException( AppResponse.toResponse(null, { message: 'Not found bid', status_code: HttpStatus.NOT_FOUND, }), ); // Lấy lịch sử đặt giá cao nhất trước đó của bid hiện tại const lastHistory = await this.bidHistoriesRepo.findOne({ where: { bid: { id: bid_id } }, order: { price: 'desc' }, }); // Nếu đã có lịch sử và giá mới giống với giá cao nhất hiện tại if (lastHistory && lastHistory.price === price) { // Nếu đã hết thời gian đấu giá, cập nhật trạng thái là 'win-bid' if (isTimeReached(bid.close_time)) { this.bidsService.bidsRepo.update(bid_id, { status: 'win-bid' }); } // Ném lỗi không cho đặt giá trùng lặp throw new BadRequestException( AppResponse.toResponse(null, { message: 'Duplicate place bid' }), ); } // Nếu tổng giá vượt quá mức tối đa cho phép if (price + bid.plus_price > bid.max_price) { // Cập nhật trạng thái bid là 'out-bid' this.bidsService.bidsRepo.update(bid_id, { status: 'out-bid' }); // Gửi thông báo trạng thái mới qua service thông báo this.notificationService.emitBidStatus({ ...bid, status: 'out-bid' }); // Ném lỗi không cho đặt giá vượt mức throw new BadRequestException( AppResponse.toResponse(null, { message: 'Price is more than Max price ' + bid.max_price, }), ); } // Lưu lịch sử đặt giá mới await this.bidHistoriesRepo.save({ bid, price }); // Lấy danh sách tất cả lịch sử đặt giá theo thứ tự mới nhất const response = await this.bidHistoriesRepo.find({ where: { bid: { id: bid_id } }, order: { created_at: 'DESC', }, }); // Nếu đây là lần đặt giá đầu tiên, cập nhật cờ `first_bid` thành false if (response.length === 1) { this.bidsService.bidsRepo.update(bid_id, { first_bid: false }); } // Gửi thông tin bid đến bot telegram const botData = { ...bid, histories: response }; // this.botTelegramApi.sendBidInfo(botData); // Send event thống place bid this.eventEmitter.emit(Event.BID_SUBMITED, botData); // Lưu message đã gửi để theo dõi this.sendMessageHistoriesService.sendMessageRepo.save({ message: this.botTelegramApi.formatBidMessage(botData), bid, }); // Kiểm tra nếu trạng thái bid thay đổi sau khi lưu, phát sự kiện cập nhật tất cả bid const bidUpdated = await this.bidsService.bidsRepo.findOne({ where: { id: bid_id }, }); this.bidsService.emitAllBidEvent(); // Trả về danh sách lịch sử đặt giá đã cập nhật return AppResponse.toResponse(plainToClass(BidHistory, response)); } }