feat: enhance OKR management by adding permission checks for editing and deleting, and updating OKR forms to handle key results more effectively
Some checks failed
Deploy with Docker Compose / deploy (push) Failing after 4m44s
Some checks failed
Deploy with Docker Compose / deploy (push) Failing after 4m44s
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { prisma } from '@/services/database';
|
||||
import type { CreateOKRInput, UpdateOKRInput, UpdateKeyResultInput, OKRStatus, KeyResultStatus } from '@/lib/types';
|
||||
import type { UpdateOKRInput, OKRStatus, KeyResultStatus } from '@/lib/types';
|
||||
|
||||
export async function createOKR(
|
||||
teamMemberId: string,
|
||||
@@ -183,30 +183,105 @@ export async function getUserOKRs(userId: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateOKR(okrId: string, data: UpdateOKRInput) {
|
||||
const okr = await prisma.oKR.update({
|
||||
where: { id: okrId },
|
||||
data: {
|
||||
...(data.objective !== undefined && { objective: data.objective }),
|
||||
...(data.description !== undefined && { description: data.description || null }),
|
||||
...(data.period !== undefined && { period: data.period }),
|
||||
...(data.startDate !== undefined && { startDate: data.startDate }),
|
||||
...(data.endDate !== undefined && { endDate: data.endDate }),
|
||||
...(data.status !== undefined && { status: data.status }),
|
||||
},
|
||||
include: {
|
||||
keyResults: {
|
||||
orderBy: {
|
||||
order: 'asc',
|
||||
export async function updateOKR(
|
||||
okrId: string,
|
||||
data: UpdateOKRInput,
|
||||
keyResultsUpdates?: {
|
||||
create?: Array<{ title: string; targetValue: number; unit: string; order: number }>;
|
||||
update?: Array<{
|
||||
id: string;
|
||||
title?: string;
|
||||
targetValue?: number;
|
||||
unit?: string;
|
||||
order?: number;
|
||||
}>;
|
||||
delete?: string[];
|
||||
}
|
||||
) {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
// Update OKR
|
||||
await tx.oKR.update({
|
||||
where: { id: okrId },
|
||||
data: {
|
||||
...(data.objective !== undefined && { objective: data.objective }),
|
||||
...(data.description !== undefined && { description: data.description || null }),
|
||||
...(data.period !== undefined && { period: data.period }),
|
||||
...(data.startDate !== undefined && { startDate: data.startDate }),
|
||||
...(data.endDate !== undefined && { endDate: data.endDate }),
|
||||
...(data.status !== undefined && { status: data.status }),
|
||||
},
|
||||
});
|
||||
|
||||
// Handle Key Results updates if provided
|
||||
if (keyResultsUpdates) {
|
||||
// Delete Key Results
|
||||
if (keyResultsUpdates.delete && keyResultsUpdates.delete.length > 0) {
|
||||
await tx.keyResult.deleteMany({
|
||||
where: {
|
||||
id: { in: keyResultsUpdates.delete },
|
||||
okrId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Create new Key Results
|
||||
if (keyResultsUpdates.create && keyResultsUpdates.create.length > 0) {
|
||||
await Promise.all(
|
||||
keyResultsUpdates.create.map((kr) =>
|
||||
tx.keyResult.create({
|
||||
data: {
|
||||
okrId,
|
||||
title: kr.title,
|
||||
targetValue: kr.targetValue,
|
||||
currentValue: 0,
|
||||
unit: kr.unit || '%',
|
||||
status: 'NOT_STARTED',
|
||||
order: kr.order,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Update existing Key Results
|
||||
if (keyResultsUpdates.update && keyResultsUpdates.update.length > 0) {
|
||||
await Promise.all(
|
||||
keyResultsUpdates.update.map((kr) =>
|
||||
tx.keyResult.update({
|
||||
where: { id: kr.id },
|
||||
data: {
|
||||
...(kr.title !== undefined && { title: kr.title }),
|
||||
...(kr.targetValue !== undefined && { targetValue: kr.targetValue }),
|
||||
...(kr.unit !== undefined && { unit: kr.unit }),
|
||||
...(kr.order !== undefined && { order: kr.order }),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch updated OKR with Key Results
|
||||
const updatedOkr = await tx.oKR.findUnique({
|
||||
where: { id: okrId },
|
||||
include: {
|
||||
keyResults: {
|
||||
orderBy: {
|
||||
order: 'asc',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
...okr,
|
||||
progress: calculateOKRProgressFromKeyResults(okr.keyResults),
|
||||
};
|
||||
if (!updatedOkr) {
|
||||
throw new Error('OKR not found after update');
|
||||
}
|
||||
|
||||
return {
|
||||
...updatedOkr,
|
||||
progress: calculateOKRProgressFromKeyResults(updatedOkr.keyResults),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteOKR(okrId: string) {
|
||||
@@ -216,6 +291,47 @@ export async function deleteOKR(okrId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function createKeyResult(
|
||||
okrId: string,
|
||||
title: string,
|
||||
targetValue: number,
|
||||
unit: string,
|
||||
order: number
|
||||
) {
|
||||
return prisma.keyResult.create({
|
||||
data: {
|
||||
okrId,
|
||||
title,
|
||||
targetValue,
|
||||
currentValue: 0,
|
||||
unit: unit || '%',
|
||||
status: 'NOT_STARTED',
|
||||
order,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateKeyResultMetadata(
|
||||
krId: string,
|
||||
data: { title?: string; targetValue?: number; unit?: string; order?: number }
|
||||
) {
|
||||
return prisma.keyResult.update({
|
||||
where: { id: krId },
|
||||
data: {
|
||||
...(data.title !== undefined && { title: data.title }),
|
||||
...(data.targetValue !== undefined && { targetValue: data.targetValue }),
|
||||
...(data.unit !== undefined && { unit: data.unit }),
|
||||
...(data.order !== undefined && { order: data.order }),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteKeyResult(krId: string) {
|
||||
return prisma.keyResult.delete({
|
||||
where: { id: krId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateKeyResult(krId: string, currentValue: number, notes: string | null) {
|
||||
// Auto-update status based on progress
|
||||
const kr = await prisma.keyResult.findUnique({
|
||||
@@ -293,7 +409,9 @@ export function calculateOKRProgress(okrId: string): Promise<number> {
|
||||
});
|
||||
}
|
||||
|
||||
function calculateOKRProgressFromKeyResults(keyResults: Array<{ currentValue: number; targetValue: number }>): number {
|
||||
function calculateOKRProgressFromKeyResults(
|
||||
keyResults: Array<{ currentValue: number; targetValue: number }>
|
||||
): number {
|
||||
if (keyResults.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -305,4 +423,3 @@ function calculateOKRProgressFromKeyResults(keyResults: Array<{ currentValue: nu
|
||||
|
||||
return Math.round(totalProgress / keyResults.length);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user