Skip to content

Commit 1cda6d7

Browse files
authored
Merge pull request #37 from GeneralMagicio/add-setVote()
add setVote and editVote endpoint
2 parents ca12e91 + 7a23a31 commit 1cda6d7

File tree

6 files changed

+148
-36
lines changed

6 files changed

+148
-36
lines changed

prisma/schema.prisma

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,58 +7,56 @@
77
generator client {
88
provider = "prisma-client-js"
99
}
10+
1011
datasource db {
1112
provider = "postgresql"
1213
url = env("DATABASE_URL")
1314
}
1415

15-
1616
model User {
17-
id Int @id @default(autoincrement())
18-
worldID String @unique
19-
name String
20-
profilePicture String?
21-
pollsCreatedCount Int @default(0)
22-
pollsParticipatedCount Int @default(0)
23-
createdPolls Poll[] @relation("PollAuthor")
24-
votes Vote[]
25-
actions UserAction[]
17+
id Int @id @default(autoincrement())
18+
worldID String @unique
19+
name String
20+
profilePicture String?
21+
pollsCreatedCount Int @default(0)
22+
pollsParticipatedCount Int @default(0)
23+
createdPolls Poll[] @relation("PollAuthor")
24+
votes Vote[]
25+
actions UserAction[]
2626
}
2727

2828
model UserAction {
29-
id Int @id @default(autoincrement())
30-
userId Int
31-
actionID String @unique
32-
pollId Int
33-
type ActionType
34-
user User @relation(fields: [userId], references: [id])
35-
poll Poll @relation(fields: [pollId], references: [pollId],onDelete: Cascade)
36-
29+
id Int @id @default(autoincrement())
30+
userId Int
31+
pollId Int
32+
type ActionType
33+
user User @relation(fields: [userId], references: [id])
34+
poll Poll @relation(fields: [pollId], references: [pollId],onDelete: Cascade)
3735
}
3836

3937
model Poll {
40-
pollId Int @id @default(autoincrement())
38+
pollId Int @id @default(autoincrement())
4139
authorUserId Int
4240
title String
4341
description String?
4442
options String[]
45-
creationDate DateTime @default(now())
43+
creationDate DateTime @default(now())
4644
startDate DateTime
47-
endDate DateTime
45+
endDate DateTime
4846
tags String[]
49-
isAnonymous Boolean @default(false)
50-
participantCount Int @default(0)
47+
isAnonymous Boolean @default(false)
48+
participantCount Int @default(0)
5149
voteResults Json
52-
author User @relation("PollAuthor", fields: [authorUserId], references: [id])
53-
votes Vote[]
50+
author User @relation("PollAuthor", fields: [authorUserId], references: [id])
51+
votes Vote[]
5452
userAction UserAction[]
5553
}
5654

5755
model Vote {
58-
voteID String @id @default(uuid())
59-
userId Int
60-
pollId Int
61-
votingPower Int
56+
voteID String @id @default(uuid())
57+
userId Int
58+
pollId Int
59+
votingPower Int
6260
weightDistribution Json
6361
proof String
6462
user User @relation(fields: [userId], references: [id])

src/poll/poll.controller.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ import {
44
Post,
55
Body,
66
Param,
7-
Delete,
87
Req,
98
Query,
109
Res,
1110
} from '@nestjs/common';
1211
import { Response } from 'express';
1312
import { PollService } from './poll.service';
14-
import { Prisma } from '@prisma/client';
1513
import { CreatePollDto, GetPollsDto } from './Poll.dto';
1614

1715
@Controller('poll')

src/poll/poll.service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ export class PollService {
4646
await tx.userAction.create({
4747
data: {
4848
userId,
49-
actionID: `created-${newPoll.pollId}-${userId}-${Date.now()}`,
5049
pollId: newPoll.pollId,
5150
type: ActionType.CREATED,
5251
},

src/user/user.controller.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
22
import { UserService } from './user.service';
33
import {
4+
EditVoteDto,
5+
EditVoteResponseDto,
46
GetUserActivitiesDto,
57
GetUserDataDto,
68
GetUserVotesDto,
9+
SetVoteDto,
10+
SetVoteResponseDto,
711
UserActivitiesResponseDto,
812
UserDataResponseDto,
913
UserVotesResponseDto,
@@ -33,4 +37,14 @@ export class UserController {
3337
): Promise<UserVotesResponseDto> {
3438
return this.userService.getUserVotes(body);
3539
}
40+
41+
@Post('setVote')
42+
async setVote(@Body() dto: SetVoteDto): Promise<SetVoteResponseDto> {
43+
return this.userService.setVote(dto);
44+
}
45+
46+
@Post('editVote')
47+
async editVote(@Body() dto: EditVoteDto): Promise<EditVoteResponseDto> {
48+
return this.userService.editVote(dto);
49+
}
3650
}

src/user/user.dto.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class GetUserActivitiesDto {
1414
}
1515

1616
export class UserActionDto {
17-
actionID: string;
17+
id: number;
1818
type: 'created' | 'voted';
1919
pollId: number;
2020
pollTitle: string;
@@ -38,3 +38,23 @@ export class UserVotesResponseDto {
3838
votingPower: number;
3939
weightDistribution?: Record<string, number>;
4040
}
41+
42+
export class SetVoteDto {
43+
pollId: number;
44+
worldID: string;
45+
weightDistribution: Record<string, number>;
46+
}
47+
48+
export class SetVoteResponseDto {
49+
voteID: string;
50+
actionId: number;
51+
}
52+
53+
export class EditVoteDto {
54+
voteID: string;
55+
weightDistribution: Record<string, number>;
56+
}
57+
58+
export class EditVoteResponseDto {
59+
actionId: number;
60+
}

src/user/user.service.ts

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// src/user/user.service.ts
21
import { Injectable } from '@nestjs/common';
32
import { DatabaseService } from '../database/database.service';
43
import {
@@ -9,7 +8,14 @@ import {
98
UserActionDto,
109
GetUserVotesDto,
1110
UserVotesResponseDto,
11+
SetVoteDto,
12+
SetVoteResponseDto,
13+
EditVoteDto,
14+
EditVoteResponseDto,
1215
} from './user.dto';
16+
import { ActionType } from '@prisma/client';
17+
18+
const votingPower = 100; // Set as a constant for now
1319

1420
type UserActionFilters = {
1521
userId: number;
@@ -70,7 +76,7 @@ export class UserService {
7076
where: filters,
7177
orderBy: { poll: { endDate: 'desc' } },
7278
select: {
73-
actionID: true,
79+
id: true,
7480
type: true,
7581
poll: {
7682
select: {
@@ -85,7 +91,7 @@ export class UserService {
8591
},
8692
});
8793
const actions: UserActionDto[] = userActions.map((action) => ({
88-
actionID: action.actionID,
94+
id: action.id,
8995
type: action.type.toLowerCase() as 'created' | 'voted',
9096
pollId: action.poll.pollId,
9197
pollTitle: action.poll.title,
@@ -130,4 +136,81 @@ export class UserService {
130136
weightDistribution: vote.weightDistribution as Record<string, number>,
131137
};
132138
}
139+
140+
async setVote(dto: SetVoteDto): Promise<SetVoteResponseDto> {
141+
const user = await this.databaseService.user.findUnique({
142+
where: { worldID: dto.worldID },
143+
select: { id: true },
144+
});
145+
if (!user) {
146+
throw new Error('User not found');
147+
}
148+
149+
const poll = await this.databaseService.poll.findUnique({
150+
where: { pollId: dto.pollId },
151+
select: { endDate: true, options: true },
152+
});
153+
if (!poll || poll.endDate < new Date()) {
154+
throw new Error('Poll is not active or does not exist');
155+
}
156+
157+
const vote = await this.databaseService.vote.create({
158+
data: {
159+
userId: user.id,
160+
pollId: dto.pollId,
161+
votingPower,
162+
weightDistribution: dto.weightDistribution,
163+
proof: '', // TODO implement Bandada proof later
164+
},
165+
});
166+
const action = await this.databaseService.userAction.create({
167+
data: {
168+
userId: user.id,
169+
pollId: dto.pollId,
170+
type: ActionType.VOTED,
171+
},
172+
});
173+
return {
174+
voteID: vote.voteID,
175+
actionId: action.id,
176+
};
177+
}
178+
179+
async editVote(dto: EditVoteDto): Promise<EditVoteResponseDto> {
180+
const vote = await this.databaseService.vote.findUnique({
181+
where: { voteID: dto.voteID },
182+
select: {
183+
userId: true,
184+
poll: {
185+
select: { endDate: true },
186+
},
187+
},
188+
});
189+
if (!vote) {
190+
throw new Error('Vote not found');
191+
}
192+
if (vote.poll.endDate < new Date()) {
193+
throw new Error('Cannot edit vote for an inactive poll');
194+
}
195+
const updatedVote = await this.databaseService.vote.update({
196+
where: { voteID: dto.voteID },
197+
data: {
198+
weightDistribution: dto.weightDistribution,
199+
},
200+
});
201+
const userAction = await this.databaseService.userAction.findFirst({
202+
where: {
203+
userId: vote.userId,
204+
pollId: updatedVote.pollId,
205+
type: ActionType.VOTED,
206+
},
207+
select: { id: true },
208+
});
209+
if (!userAction) {
210+
throw new Error('User action not found');
211+
}
212+
return {
213+
actionId: userAction.id,
214+
};
215+
}
133216
}

0 commit comments

Comments
 (0)