Files
gridpilot.gg/core/identity/application/use-cases/CastAdminVoteUseCase.ts
2025-12-29 22:27:33 +01:00

100 lines
2.7 KiB
TypeScript

import { IAdminVoteSessionRepository } from '../../domain/repositories/IAdminVoteSessionRepository';
import { CastAdminVoteInput, CastAdminVoteOutput } from '../dtos/AdminVoteSessionDto';
/**
* Use Case: CastAdminVoteUseCase
*
* Casts a vote in an active admin vote session.
* Follows CQRS Light: command side operation.
*
* Per plans section 7.1.1
*/
export class CastAdminVoteUseCase {
constructor(
private readonly adminVoteSessionRepository: IAdminVoteSessionRepository,
) {}
async execute(input: CastAdminVoteInput): Promise<CastAdminVoteOutput> {
try {
// Validate input
const errors = this.validateInput(input);
if (errors.length > 0) {
return {
success: false,
voteSessionId: input.voteSessionId,
voterId: input.voterId,
errors,
};
}
// Load the vote session
const session = await this.adminVoteSessionRepository.findById(input.voteSessionId);
if (!session) {
return {
success: false,
voteSessionId: input.voteSessionId,
voterId: input.voterId,
errors: ['Vote session not found'],
};
}
// Check if session is open
const voteTime = input.votedAt ? new Date(input.votedAt) : new Date();
if (!session.isVotingWindowOpen(voteTime)) {
return {
success: false,
voteSessionId: input.voteSessionId,
voterId: input.voterId,
errors: ['Vote session is not open for voting'],
};
}
// Cast the vote
session.castVote(input.voterId, input.positive, voteTime);
// Save updated session
await this.adminVoteSessionRepository.save(session);
return {
success: true,
voteSessionId: input.voteSessionId,
voterId: input.voterId,
};
} catch (error) {
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
return {
success: false,
voteSessionId: input.voteSessionId,
voterId: input.voterId,
errors: [`Failed to cast vote: ${errorMsg}`],
};
}
}
private validateInput(input: CastAdminVoteInput): string[] {
const errors: string[] = [];
if (!input.voteSessionId || input.voteSessionId.trim().length === 0) {
errors.push('voteSessionId is required');
}
if (!input.voterId || input.voterId.trim().length === 0) {
errors.push('voterId is required');
}
if (typeof input.positive !== 'boolean') {
errors.push('positive must be a boolean value');
}
if (input.votedAt) {
const votedAt = new Date(input.votedAt);
if (isNaN(votedAt.getTime())) {
errors.push('votedAt must be a valid date if provided');
}
}
return errors;
}
}