@@ -73,15 +73,25 @@ export default class TasksService {
7373 wbsElement : true ,
7474 workPackages : { include : { wbsElement : true } }
7575 }
76+ } ,
77+ workPackage : {
78+ include : {
79+ project : {
80+ include : {
81+ teams : getTeamQueryArgs ( organization . organizationId )
82+ }
83+ }
84+ }
7685 }
7786 }
7887 } ) ;
7988 if ( ! requestedWbsElement ) throw new NotFoundException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
8089 if ( requestedWbsElement . dateDeleted ) throw new DeletedException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
81- const { project } = requestedWbsElement ;
82- if ( ! project ) throw new HttpException ( 400 , "This task's wbs element is not linked to a project!" ) ;
8390
84- const { teams } = project ;
91+ if ( ! requestedWbsElement . project && ! requestedWbsElement . workPackage )
92+ throw new HttpException ( 400 , "This task's wbs element is not linked to a project or work package!" ) ;
93+
94+ const teams = requestedWbsElement . project ?. teams ?? requestedWbsElement . workPackage ?. project ?. teams ;
8595 if ( ! teams || teams . length === 0 )
8696 throw new HttpException ( 400 , 'This project needs to be assigned to a team to create a task!' ) ;
8797
@@ -136,7 +146,9 @@ export default class TasksService {
136146 * @param title the new title for the task
137147 * @param notes the new notes for the task
138148 * @param priority the new priority for the task
149+ * @param startDate the new start date for the task
139150 * @param deadline the new deadline for the task
151+ * @param wbsNum the new wbs element for the task
140152 * @returns the sucessfully edited task
141153 */
142154 static async editTask (
@@ -147,24 +159,56 @@ export default class TasksService {
147159 notes : string ,
148160 priority : Task_Priority ,
149161 startDate ?: Date ,
150- deadline ?: Date
162+ deadline ?: Date ,
163+ wbsNum ?: WbsNumber
151164 ) {
152165 const hasPermission = await userHasPermission ( user . userId , organizationId , notGuest ) ;
153166 if ( ! hasPermission ) throw new AccessDeniedException ( 'Guests cannot edit tasks' ) ;
154167
155168 const originalTask = await prisma . task . findUnique ( { where : { taskId } , include : { wbsElement : true } } ) ;
156169
170+ // error if there's a problem with the task
157171 if ( ! originalTask ) throw new NotFoundException ( 'Task' , taskId ) ;
158172 if ( originalTask . wbsElement . organizationId !== organizationId ) throw new InvalidOrganizationException ( 'Task' ) ;
159173 if ( originalTask . dateDeleted ) throw new DeletedException ( 'Task' , taskId ) ;
160174
161175 if ( ! isUnderWordCount ( title , 15 ) ) throw new HttpException ( 400 , 'Title must be less than 15 words' ) ;
162-
163176 if ( ! isUnderWordCount ( notes , 250 ) ) throw new HttpException ( 400 , 'Notes must be less than 250 words' ) ;
164177
178+ // if wbsNum passed, error if there's a problem with the wbs element
179+ if ( wbsNum ) {
180+ const newWbsElement = await prisma . wBS_Element . findUnique ( {
181+ where : {
182+ wbsNumber : {
183+ ...wbsNum ,
184+ organizationId
185+ }
186+ }
187+ } ) ;
188+ if ( ! newWbsElement ) throw new NotFoundException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
189+ if ( newWbsElement . dateDeleted ) throw new DeletedException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
190+ }
191+
165192 const updatedTask = await prisma . task . update ( {
166193 where : { taskId } ,
167- data : { title, notes, priority, startDate, deadline } ,
194+ data : {
195+ title,
196+ notes,
197+ priority,
198+ startDate,
199+ deadline,
200+ // if wbsNum passed, update prisma relation to connect task with wbs element
201+ ...( wbsNum && {
202+ wbsElement : {
203+ connect : {
204+ wbsNumber : {
205+ ...wbsNum ,
206+ organizationId
207+ }
208+ }
209+ }
210+ } )
211+ } ,
168212 ...getTaskQueryArgs ( originalTask . wbsElement . organizationId )
169213 } ) ;
170214 return taskTransformer ( updatedTask ) ;
@@ -173,13 +217,16 @@ export default class TasksService {
173217 /**
174218 * Edits the status of a task in the database
175219 * @param user the user editing the task
176- * @param organizationId the organizqtion Id
220+ * @param organizationId the organization Id
177221 * @param taskId the id of the task
178222 * @param status the new status
179223 * @returns the updated task
180224 * @throws if the task does not exist, the task is already deleted, or if the user does not have permissions
181225 */
182226 static async editTaskStatus ( user : User , organizationId : string , taskId : string , status : Task_Status ) {
227+ const hasPermission = await userHasPermission ( user . userId , organizationId , notGuest ) ;
228+ if ( ! hasPermission ) throw new AccessDeniedException ( 'Guests cannot edit tasks' ) ;
229+
183230 // Get the original task and check if it exists
184231 const originalTask = await prisma . task . findUnique ( { where : { taskId } , include : { assignees : true , wbsElement : true } } ) ;
185232 if ( ! originalTask ) throw new NotFoundException ( 'Task' , taskId ) ;
@@ -190,9 +237,6 @@ export default class TasksService {
190237 throw new HttpException ( 400 , 'A task in progress must have a deadline and assignees!' ) ;
191238 }
192239
193- const hasPermission = await userHasPermission ( user . userId , organizationId , notGuest ) ;
194- if ( ! hasPermission ) throw new AccessDeniedException ( 'Guests cannot edit tasks' ) ;
195-
196240 const updatedTask = await prisma . task . update ( {
197241 where : { taskId } ,
198242 data : { status } ,
@@ -216,6 +260,9 @@ export default class TasksService {
216260 assignees : string [ ] ,
217261 organization : Organization
218262 ) : Promise < Task > {
263+ const hasPermission = await userHasPermission ( user . userId , organization . organizationId , notGuest ) ;
264+ if ( ! hasPermission ) throw new AccessDeniedException ( 'Guests cannot edit tasks' ) ;
265+
219266 // Get the original task and check if it exists
220267 const originalTask = await prisma . task . findUnique ( {
221268 where : { taskId } ,
@@ -230,9 +277,6 @@ export default class TasksService {
230277 const originalAssigneeIds = originalTask . assignees . map ( ( assignee ) => assignee . userId ) ;
231278 const newAssigneeIds = assignees . filter ( ( userId ) => ! originalAssigneeIds . includes ( userId ) ) ;
232279
233- const hasPermission = await userHasPermission ( user . userId , organization . organizationId , notGuest ) ;
234- if ( ! hasPermission ) throw new AccessDeniedException ( 'Guests cannot edit tasks' ) ;
235-
236280 // this throws if any of the users aren't found
237281 const assigneeUsers = await getUsers ( assignees ) ;
238282
@@ -391,4 +435,60 @@ export default class TasksService {
391435
392436 return tasks . map ( taskCardPreviewTransformer ) ;
393437 }
438+
439+ /**
440+ * Gets all tasks associated with a wbs element
441+ * If the wbs number is a project (workPackageNumber === 0), returns the project's
442+ * own tasks merged with all of its work packages' tasks
443+ * If the wbs number is a work package, returns just that WP's tasks
444+ * @param wbsNum the wbs number to fetch tasks for
445+ * @param organization the organization that the user is currently in
446+ * @returns array of tasks
447+ */
448+ static async getTasksByWbsNum ( wbsNum : WbsNumber , organization : Organization ) : Promise < Task [ ] > {
449+ const wbsElement = await prisma . wBS_Element . findUnique ( {
450+ where : {
451+ wbsNumber : {
452+ ...wbsNum ,
453+ organizationId : organization . organizationId
454+ }
455+ }
456+ } ) ;
457+
458+ if ( ! wbsElement ) throw new NotFoundException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
459+ if ( wbsElement . dateDeleted ) throw new DeletedException ( 'WBS Element' , wbsPipe ( wbsNum ) ) ;
460+
461+ // project case, so return project's own tasks and all its wp's tasks
462+ if ( wbsNum . workPackageNumber === 0 ) {
463+ const project = await prisma . project . findUnique ( {
464+ where : { wbsElementId : wbsElement . wbsElementId } ,
465+ include : { workPackages : { include : { wbsElement : true } } }
466+ } ) ;
467+
468+ if ( ! project ) throw new NotFoundException ( 'Project' , wbsPipe ( wbsNum ) ) ;
469+
470+ const wpWbsElementIds = project . workPackages . map ( ( wp ) => wp . wbsElementId ) ;
471+
472+ const tasks = await prisma . task . findMany ( {
473+ where : {
474+ dateDeleted : null ,
475+ wbsElementId : { in : [ wbsElement . wbsElementId , ...wpWbsElementIds ] }
476+ } ,
477+ ...getTaskQueryArgs ( organization . organizationId )
478+ } ) ;
479+
480+ return tasks . map ( taskTransformer ) ;
481+ }
482+
483+ // work package case, so return just that wp's tasks
484+ const tasks = await prisma . task . findMany ( {
485+ where : {
486+ dateDeleted : null ,
487+ wbsElementId : wbsElement . wbsElementId
488+ } ,
489+ ...getTaskQueryArgs ( organization . organizationId )
490+ } ) ;
491+
492+ return tasks . map ( taskTransformer ) ;
493+ }
394494}
0 commit comments