@@ -86,8 +86,8 @@ export class PollService {
8686 // Custom sorting based on sortField and sortDirection
8787 const sortedPolls = filteredPolls . sort ( ( a , b ) => {
8888 const now = new Date ( ) ;
89- const aIsActive = ! a . deadline || new Date ( a . deadline ) > now ;
90- const bIsActive = ! b . deadline || new Date ( b . deadline ) > now ;
89+ const aIsActive = a . status === "active" || ( a . status !== "ended" && a . status !== "draft" && ( ! a . deadline || new Date ( a . deadline ) > now ) ) ;
90+ const bIsActive = b . status === "active" || ( b . status !== "ended" && b . status !== "draft" && ( ! b . deadline || new Date ( b . deadline ) > now ) ) ;
9191
9292 // Apply the user's chosen sorting
9393 let comparison = 0 ;
@@ -218,13 +218,15 @@ export class PollService {
218218 throw new Error ( "Blind voting (private visibility) cannot be combined with eReputation weighted voting." ) ;
219219 }
220220
221+ const hasDeadline = ! ! pollData . deadline ;
221222 const pollDataForEntity = {
222223 title : pollData . title ,
223224 mode : pollData . mode as "normal" | "point" | "rank" ,
224225 visibility : pollData . visibility as "public" | "private" ,
225226 votingWeight : votingWeight ,
226227 options : pollData . options ,
227- deadline : pollData . deadline ? new Date ( pollData . deadline ) : null ,
228+ status : hasDeadline ? "active" as const : "draft" as const ,
229+ deadline : hasDeadline ? new Date ( pollData . deadline ! ) : null ,
228230 creator,
229231 creatorId : pollData . creatorId ,
230232 groupId : pollData . groupId || null
@@ -237,8 +239,8 @@ export class PollService {
237239 const savedPoll = await this . pollRepository . save ( poll ) ;
238240 console . log ( '🔍 Poll saved to database:' , savedPoll ) ;
239241
240- // Create a system message about the new vote
241- if ( pollData . groupId ) {
242+ // Create a system message about the new vote (only for active polls, not drafts)
243+ if ( pollData . groupId && hasDeadline ) {
242244 await this . messageService . createVoteCreatedMessage ( pollData . groupId , pollData . title , savedPoll . id , creator . name , savedPoll . deadline ) ;
243245 }
244246
@@ -301,6 +303,67 @@ export class PollService {
301303
302304
303305
306+ /**
307+ * Manually start a poll (draft → active). Only creator can do this.
308+ */
309+ async startPoll ( id : string , userId : string ) : Promise < Poll > {
310+ const poll = await this . getPollById ( id ) ;
311+ if ( ! poll ) {
312+ throw new Error ( "Poll not found" ) ;
313+ }
314+ if ( poll . creatorId !== userId ) {
315+ throw new Error ( "Not authorized to start this poll" ) ;
316+ }
317+ if ( poll . status !== "draft" ) {
318+ throw new Error ( "Only draft polls can be started" ) ;
319+ }
320+
321+ await this . pollRepository . update ( id , { status : "active" } ) ;
322+
323+ // Send system message that voting is now open
324+ if ( poll . groupId ) {
325+ await this . messageService . createVoteCreatedMessage (
326+ poll . groupId ,
327+ poll . title ,
328+ poll . id ,
329+ poll . creator . name ,
330+ poll . deadline
331+ ) ;
332+ }
333+
334+ return ( await this . getPollById ( id ) ) ! ;
335+ }
336+
337+ /**
338+ * Manually end a poll (active → ended). Only creator can do this.
339+ */
340+ async endPoll ( id : string , userId : string ) : Promise < Poll > {
341+ const poll = await this . getPollById ( id ) ;
342+ if ( ! poll ) {
343+ throw new Error ( "Poll not found" ) ;
344+ }
345+ if ( poll . creatorId !== userId ) {
346+ throw new Error ( "Not authorized to end this poll" ) ;
347+ }
348+ if ( poll . status !== "active" ) {
349+ throw new Error ( "Only active polls can be ended" ) ;
350+ }
351+
352+ await this . pollRepository . update ( id , { status : "ended" , deadlineMessageSent : true } ) ;
353+
354+ // Send system message that voting has ended
355+ if ( poll . groupId ) {
356+ const voteUrl = `${ process . env . PUBLIC_EVOTING_URL || 'http://localhost:3000' } /${ poll . id } ` ;
357+ await this . messageService . createSystemMessage ( {
358+ text : `eVoting Platform: Vote has been manually closed!\n\n"${ poll . title } "\n\nVote ID: ${ poll . id } \n\nClosed by: ${ poll . creator . name } \n\n<a href="${ voteUrl } " target="_blank">View results here</a>` ,
359+ groupId : poll . groupId ,
360+ voteId : poll . id
361+ } ) ;
362+ }
363+
364+ return ( await this . getPollById ( id ) ) ! ;
365+ }
366+
304367 /**
305368 * Get polls by group ID
306369 */
0 commit comments