Skip to content

Commit 81871fd

Browse files
committed
#1528 Allow unassigning material from assembly
1 parent 719babc commit 81871fd

2 files changed

Lines changed: 34 additions & 14 deletions

File tree

src/backend/src/services/projects.services.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -816,27 +816,37 @@ export default class ProjectsService {
816816
* Assign a material on a project to a different assembly
817817
* @param submitter the submitter
818818
* @param materialId the material that will be moved
819-
* @param assemblyId the assembly to change the material to
819+
* @param assemblyId the assembly to change the material to, or undefined to unassign the material
820820
* @throws if the submitter does not have the relevant positions
821821
* @returns the updated material
822822
*/
823-
static async assignMaterialAssembly(submitter: User, materialId: string, assemblyId: string) {
823+
static async assignMaterialAssembly(submitter: User, materialId: string, assemblyId: undefined | string) {
824824
const material = await prisma.material.findUnique({ where: { materialId } });
825825
if (!material) throw new NotFoundException('Material', materialId);
826826

827-
const assembly = await prisma.assembly.findUnique({
828-
where: { assemblyId },
829-
include: { wbsElement: true }
830-
});
831-
if (!assembly) throw new NotFoundException('Assembly', assemblyId);
832-
833827
const project = await prisma.project.findFirst({
834828
where: {
835-
wbsElement: assembly.wbsElement
829+
wbsElementId: material.wbsElementId
836830
},
837831
...projectQueryArgs
838832
});
839-
if (!project) throw new NotFoundException('Project', assembly.wbsElementId);
833+
if (!project) throw new NotFoundException('Project', material.wbsElementId);
834+
835+
// Permission: leadership and up, anyone on project team
836+
if (!(isLeadership(submitter.role) || isUserPartOfTeams(project.teams, submitter)))
837+
throw new AccessDeniedException('Only leadership or above can create a material type');
838+
839+
if (assemblyId === undefined) {
840+
// Unassign material from current assembly if assembly id is undefined
841+
const updatedMaterial = await prisma.material.update({ where: { materialId }, data: { assemblyId: undefined } });
842+
return updatedMaterial;
843+
}
844+
845+
const assembly = await prisma.assembly.findUnique({
846+
where: { assemblyId },
847+
include: { wbsElement: true }
848+
});
849+
if (!assembly) throw new NotFoundException('Assembly', assemblyId);
840850

841851
// Confirm that the assembly's wbsElement is the same as the material's wbsElement
842852
if (material.wbsElementId !== assembly.wbsElementId)
@@ -845,10 +855,6 @@ export default class ProjectsService {
845855
`The WBS element of the material (${material.wbsElementId}) and assembly (${assembly.wbsElementId}) do not match`
846856
);
847857

848-
// Permission: leadership and up, anyone on project team
849-
if (!(isLeadership(submitter.role) || isUserPartOfTeams(project.teams, submitter)))
850-
throw new AccessDeniedException('Only leadership or above can create a material type');
851-
852858
// Assign a material on a project to a different assembly
853859
const updatedMaterial = await prisma.material.update({ where: { materialId }, data: { assemblyId } });
854860
return updatedMaterial;

src/backend/tests/projects.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,5 +717,19 @@ describe('Projects', () => {
717717
const updatedMaterial = await ProjectsService.assignMaterialAssembly(aquaman, 'mid', 'updated-aid');
718718
expect(updatedMaterial).toBe(expectedUpdatedToolMaterial);
719719
});
720+
721+
test('unassigning material from assebly works', async () => {
722+
vi.spyOn(prisma.material, 'findUnique').mockResolvedValue(prismaMaterial1);
723+
vi.spyOn(prisma.project, 'findFirst').mockResolvedValue(prismaProject1);
724+
725+
const expectedUpdatedToolMaterial: Material = {
726+
...prismaMaterial1,
727+
assemblyId: null
728+
};
729+
vi.spyOn(prisma.material, 'update').mockResolvedValue(expectedUpdatedToolMaterial);
730+
731+
const updatedMaterial = await ProjectsService.assignMaterialAssembly(aquaman, 'mid', undefined);
732+
expect(updatedMaterial).toBe(expectedUpdatedToolMaterial);
733+
});
720734
});
721735
});

0 commit comments

Comments
 (0)