Initial commit

This commit is contained in:
Lorenzo Sanesi
2026-03-26 22:46:03 +01:00
commit 18e0e04700
80 changed files with 13114 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
const { ValidationError } = require('../shared/errors');
const config = require('../config');
class BetsService {
constructor({ betsRepository, usersRepository, dataStitchingService }) {
this.betsRepository = betsRepository;
this.usersRepository = usersRepository;
this.dataStitchingService = dataStitchingService;
}
async getAllBets() {
const bets = await this.betsRepository.findAll();
return await this.dataStitchingService.populateBetsWithUsers(bets);
}
async getBetById(betId) {
const bet = await this.betsRepository.findById(betId);
const populated = await this.dataStitchingService.populateBetsWithUsers([bet]);
return populated[0];
}
async getUserBets(userId) {
const bets = await this.betsRepository.findByUser(userId);
return await this.dataStitchingService.populateBetsWithUsers(bets);
}
async getGroupBets(groupId) {
const bets = await this.betsRepository.findByGroup(groupId);
return await this.dataStitchingService.populateBetsWithUsers(bets);
}
async getPublicBetsExcludingUser(userId) {
const bets = await this.betsRepository.findPublicBetsExcludingUser(userId);
return await this.dataStitchingService.populateBetsWithUsers(bets);
}
async createBet(betData) {
const { title, description, stake, participants, isPublic, groupId } = betData;
if (!title || title.trim() === '') {
throw new ValidationError('Bet title is required');
}
if (!stake || stake.trim() === '') {
throw new ValidationError('Bet stake is required');
}
if (!participants || !Array.isArray(participants) || participants.length === 0) {
throw new ValidationError('At least one participant is required');
}
const normalizedParticipants = participants.map((p) => ({
...p,
user: parseInt(p.user, 10),
}));
const userIds = normalizedParticipants.map((p) => p.user);
for (const userId of userIds) {
await this.usersRepository.findById(userId);
}
const bet = await this.betsRepository.create({
title,
description,
stake,
participants: normalizedParticipants,
isPublic: isPublic || false,
groupId: groupId || null,
});
const populated = await this.dataStitchingService.populateBetsWithUsers([bet]);
return populated[0];
}
async updateBet(betId, updateData) {
if (updateData.title && updateData.title.trim() === '') {
throw new ValidationError('Bet title cannot be empty');
}
const bet = await this.betsRepository.update(betId, updateData);
const populated = await this.dataStitchingService.populateBetsWithUsers([bet]);
return populated[0];
}
async deleteBet(betId) {
return await this.betsRepository.delete(betId);
}
async declareWinner(betId, winnerId) {
await this.usersRepository.findById(winnerId);
const bet = await this.betsRepository.update(betId, {
winner: winnerId,
status: config.BET_STATUS.COMPLETED,
endDate: new Date(),
});
const populated = await this.dataStitchingService.populateBetsWithUsers([bet]);
return populated[0];
}
}
module.exports = BetsService;