@@ -13,6 +13,7 @@ import { Prisma } from "@prisma/client";
1313import { hashPassword } from "src/auth/utils" ;
1414import { EmailService } from "src/email/email.service" ;
1515import logger from "vico-logger" ;
16+ import { endOfDay , parseDateSafe , safeDate , startOfDay } from "src/helpers/safeDate" ;
1617
1718const prisma = new PrismaClient ( ) ;
1819
@@ -312,13 +313,37 @@ export class ProjectManagementService {
312313 }
313314
314315 // Tasks
315- async getTasks ( projectId ?: string ) {
316+ async getTasks (
317+ projectId ?: string ,
318+ startDate ?: string ,
319+ endDate ?: string
320+ ) {
321+ await this . migrateSingleAssigneeToMulti ( ) ;
322+
323+ const now = new Date ( ) ;
324+
325+ // 🔥 DEFAULT RANGE: last 60 days
326+ const defaultStart = new Date ( ) ;
327+ defaultStart . setDate ( now . getDate ( ) - 60 ) ;
328+
329+ const start =
330+ startDate ? startOfDay ( new Date ( startDate ) ) : startOfDay ( defaultStart ) ;
331+
332+ const end =
333+ endDate ? endOfDay ( new Date ( endDate ) ) : endOfDay ( now ) ;
334+
335+ const where : any = {
336+ isTrash : false ,
337+ createdAt : {
338+ gte : start ,
339+ lte : end ,
340+ } ,
341+ } ;
316342
317- await this . migrateSingleAssigneeToMulti ( )
343+ if ( projectId ) {
344+ where . projectId = projectId ;
345+ }
318346
319- const where = projectId
320- ? { projectId, isTrash : false }
321- : { isTrash : false } ;
322347 const tasks = await prisma . task . findMany ( {
323348 where,
324349 orderBy : { createdAt : "desc" } ,
@@ -344,13 +369,204 @@ export class ProjectManagementService {
344369 createdAt : c . createdAt ?. toISOString ( ) ,
345370 updatedAt : c . updatedAt ?. toISOString ( ) ,
346371 } ) ) ,
347- taskAssignees : t . taskAssignees . map ( a => ( {
372+ taskAssignees : t . taskAssignees . map ( ( a ) => ( {
373+ id : a . member . id ,
374+ name : a . member . name ,
375+ photo : a . member . photo ,
376+ phone : a . member . phone ,
377+ role : a . member . role ,
378+ } ) ) ,
379+ } ) ) ;
380+ }
381+
382+
383+ // Tasks
384+ async getMyTasks (
385+ memberId ?: string ,
386+ workspaceId ?: string ,
387+ startDate ?: string ,
388+ endDate ?: string
389+ ) {
390+ const now = new Date ( )
391+
392+ // default: 60 hari terakhir
393+ const defaultStart = new Date ( )
394+ defaultStart . setDate ( now . getDate ( ) - 60 )
395+
396+ const start = safeDate ( startDate )
397+ const end = safeDate ( endDate )
398+
399+ const createdAtFilter =
400+ start || end
401+ ? {
402+ ...( start && { gte : start } ) ,
403+ ...( end && { lte : end } ) ,
404+ }
405+ : {
406+ gte : defaultStart ,
407+ }
408+
409+ const where = {
410+ isTrash : false ,
411+ createdAt : createdAtFilter ,
412+
413+ ...( workspaceId && {
414+ project : {
415+ workspaceId,
416+ } ,
417+ } ) ,
418+
419+ ...( memberId && {
420+ taskAssignees : {
421+ some : { memberId } ,
422+ } ,
423+ } ) ,
424+ }
425+
426+ const tasks = await prisma . task . findMany ( {
427+ where,
428+ orderBy : [
429+ {
430+ project : {
431+ name : "asc" , // urutkan berdasarkan nama project
432+ } ,
433+ } ,
434+ {
435+ createdAt : "desc" , // lalu task terbaru
436+ } ,
437+ ] ,
438+ include : {
439+ comments : {
440+ where : { isTrash : false } ,
441+ orderBy : { createdAt : "desc" } ,
442+ } ,
443+ taskAssignees : {
444+ include : { member : true } ,
445+ } ,
446+ project : {
447+ select : { id : true , name : true } ,
448+ } ,
449+ } ,
450+ } )
451+
452+ return tasks . map ( ( t ) => ( {
453+ ...t ,
454+ createdAt : t . createdAt ?. toISOString ( ) ,
455+ updatedAt : t . updatedAt ?. toISOString ( ) ,
456+ comments : ( t . comments || [ ] ) . map ( ( c ) => ( {
457+ ...c ,
458+ createdAt : c . createdAt ?. toISOString ( ) ,
459+ updatedAt : c . updatedAt ?. toISOString ( ) ,
460+ } ) ) ,
461+ project : t . project
462+ ? {
463+ id : t . project . id ,
464+ name : t . project . name ,
465+ }
466+ : null ,
467+ taskAssignees : t . taskAssignees . map ( ( a ) => ( {
468+ id : a . member . id ,
469+ name : a . member . name ,
470+ photo : a . member . photo ,
471+ phone : a . member . phone ,
472+ role : a . member . role ,
473+ } ) ) ,
474+ } ) )
475+ }
476+
477+
478+
479+ // Tasks Workspace
480+ async getTasksWorkspace (
481+ workspaceId ?: string ,
482+ memberId ?: string ,
483+ startDate ?: string ,
484+ endDate ?: string
485+ ) {
486+
487+ const now = new Date ( ) ;
488+
489+ // default 60 days
490+ const defaultStart = new Date ( ) ;
491+ defaultStart . setDate ( now . getDate ( ) - 60 ) ;
492+
493+ const parsedStart = parseDateSafe ( startDate ) ;
494+ const parsedEnd = parseDateSafe ( endDate ) ;
495+
496+ const start = parsedStart
497+ ? startOfDay ( parsedStart )
498+ : startOfDay ( defaultStart ) ;
499+
500+ const end = parsedEnd
501+ ? endOfDay ( parsedEnd )
502+ : endOfDay ( now ) ;
503+
504+ const safeMemberId =
505+ memberId && memberId !== "undefined" && memberId !== "null"
506+ ? memberId
507+ : undefined ;
508+
509+
510+ const where : any = {
511+ isTrash : false ,
512+ createdAt : {
513+ gte : start ,
514+ lte : end ,
515+ } ,
516+ project : {
517+ workspaceId,
518+ } ,
519+ ...( safeMemberId && {
520+ taskAssignees : {
521+ some : { memberId : safeMemberId } ,
522+ } ,
523+ } ) ,
524+ } ;
525+
526+
527+ const tasks = await prisma . task . findMany ( {
528+ where,
529+ orderBy : [
530+ {
531+ project : {
532+ name : "asc" , // urutkan berdasarkan nama project
533+ } ,
534+ } ,
535+ {
536+ createdAt : "desc" , // lalu task terbaru
537+ } ,
538+ ] ,
539+ include : {
540+ comments : {
541+ where : { isTrash : false } ,
542+ orderBy : { createdAt : "desc" } ,
543+ } ,
544+ taskAssignees : {
545+ include : {
546+ member : true ,
547+ } ,
548+ } ,
549+ project : true ,
550+ } ,
551+ } ) ;
552+
553+
554+ return tasks . map ( ( t ) => ( {
555+ ...t ,
556+ createdAt : t . createdAt ?. toISOString ( ) ,
557+ updatedAt : t . updatedAt ?. toISOString ( ) ,
558+ comments : ( t . comments || [ ] ) . map ( ( c ) => ( {
559+ ...c ,
560+ createdAt : c . createdAt ?. toISOString ( ) ,
561+ updatedAt : c . updatedAt ?. toISOString ( ) ,
562+ } ) ) ,
563+ taskAssignees : t . taskAssignees . map ( ( a ) => ( {
348564 id : a . member . id ,
349565 name : a . member . name ,
350566 photo : a . member . photo ,
351567 phone : a . member . phone ,
352- role : a . member . role
353- } ) )
568+ role : a . member . role ,
569+ } ) ) ,
354570 } ) ) ;
355571 }
356572
@@ -360,9 +576,6 @@ export class ProjectManagementService {
360576 const existingCount = await prisma . taskAssignee . count ( )
361577
362578 if ( existingCount > 0 ) {
363- console . log (
364- "[MIGRATION] TaskAssignee already has data. Migration skipped."
365- )
366579 return { skipped : true , reason : "already_migrated" }
367580 }
368581
@@ -568,6 +781,20 @@ export class ProjectManagementService {
568781 }
569782 }
570783
784+ let finishDateUpdate : Date | null | undefined = undefined ;
785+ const nextStatus = payload . status ?? existing . status ;
786+
787+ if ( nextStatus === "done" && existing . status !== "done" ) {
788+ // baru saja selesai
789+ finishDateUpdate = new Date ( ) ;
790+ }
791+
792+ if ( nextStatus !== "done" && existing . status === "done" ) {
793+ // batal selesai
794+ finishDateUpdate = null ;
795+ }
796+
797+
571798 // -----------------------------
572799 // UPDATE TASK CORE FIELDS
573800 // -----------------------------
@@ -576,21 +803,32 @@ export class ProjectManagementService {
576803 data : {
577804 title : payload . title ?? existing . title ,
578805 description : payload . description ?? existing . description ,
806+
579807 projectId :
580808 payload . projectId !== undefined
581809 ? payload . projectId
582810 : existing . projectId ,
583- status : payload . status ?? existing . status ,
811+
812+ status : nextStatus ,
813+
814+ finishDate : finishDateUpdate ,
815+
584816 priority : payload . priority ?? existing . priority ,
817+
585818 startDate :
586819 payload . startDate !== undefined
587820 ? payload . startDate
588821 : existing . startDate ,
822+
589823 dueDate :
590- payload . dueDate !== undefined ? payload . dueDate : existing . dueDate ,
824+ payload . dueDate !== undefined
825+ ? payload . dueDate
826+ : existing . dueDate ,
827+
591828 updatedAt : new Date ( ) ,
592829 } ,
593- } )
830+ } ) ;
831+
594832
595833 // -----------------------------
596834 // SYNC TASK ASSIGNEES (REPLACE)
0 commit comments