habits.andr33v.ru/server/api/village/objects/[id].delete.ts

74 lines
2.8 KiB
TypeScript

import { getUserIdFromSession } from '../../../utils/auth';
import { OBSTACLE_CLEAR_COST } from '../../../utils/village';
export default defineEventHandler(async (event) => {
// 1. Get objectId from params
const objectId = parseInt(event.context.params?.id || '', 10);
if (isNaN(objectId)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid object ID.' });
}
const userId = await getUserIdFromSession(event);
// 2. Find village + objects
const village = await prisma.village.findUnique({
where: { userId },
include: { objects: true }
});
if (!village) {
// This case is unlikely if user has ever fetched their village, but is a good safeguard.
throw createError({ statusCode: 404, statusMessage: 'Village not found.' });
}
// 3. Find the object
const objectToDelete = village.objects.find(o => o.id === objectId);
// 4. If not found -> 404
if (!objectToDelete) {
throw createError({ statusCode: 404, statusMessage: 'Object not found.' });
}
// 5. If OBSTACLE
if (objectToDelete.type === 'OBSTACLE') {
const cost = OBSTACLE_CLEAR_COST[objectToDelete.obstacleMetadata || 'DEFAULT'] ?? OBSTACLE_CLEAR_COST.DEFAULT;
try {
// Atomically check coins, deduct, and delete
await prisma.$transaction([
prisma.user.update({
where: { id: userId, coins: { gte: cost } },
data: { coins: { decrement: cost } },
}),
prisma.villageObject.delete({ where: { id: objectId } }),
]);
} catch (e) {
// The transaction fails if the user update fails due to insufficient coins
throw createError({ statusCode: 402, statusMessage: 'Insufficient coins to clear obstacle.' });
}
// 6. If HOUSE
} else if (objectToDelete.type === 'HOUSE') {
const houseCount = village.objects.filter(o => o.type === 'HOUSE').length;
const fieldCount = village.objects.filter(o => o.type === 'FIELD').length;
// Check if removing this house violates the worker rule
if (fieldCount > (houseCount - 1)) {
throw createError({
statusCode: 400,
statusMessage: `Cannot remove house. You have ${fieldCount} fields and need at least ${fieldCount} workers.`
});
}
// Delete the house (no cost)
await prisma.villageObject.delete({ where: { id: objectId } });
// 7. Otherwise (FIELD, ROAD, FENCE)
} else {
// Delete the object (no cost)
await prisma.villageObject.delete({ where: { id: objectId } });
}
// 8. Return success message
return { message: "Object removed successfully" };
});