feat: Add support for project cancellation status across the application
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
deleteProject,
|
||||
} from "@/lib/queries/projects";
|
||||
import { logFieldChange } from "@/lib/queries/fieldHistory";
|
||||
import { addNoteToProject } from "@/lib/queries/notes";
|
||||
import initializeDatabase from "@/lib/init-db";
|
||||
import { NextResponse } from "next/server";
|
||||
import { withReadAuth, withUserAuth } from "@/lib/middleware/auth";
|
||||
@@ -42,57 +43,85 @@ async function getProjectHandler(req, { params }) {
|
||||
}
|
||||
|
||||
async function updateProjectHandler(req, { params }) {
|
||||
const { id } = await params;
|
||||
const data = await req.json();
|
||||
try {
|
||||
const { id } = await params;
|
||||
const data = await req.json();
|
||||
|
||||
// Get user ID from authenticated request
|
||||
const userId = req.user?.id;
|
||||
// Get user ID from authenticated request
|
||||
const userId = req.user?.id;
|
||||
|
||||
// Get original project data for audit log and field tracking
|
||||
const originalProject = getProjectById(parseInt(id));
|
||||
// Get original project data for audit log and field tracking
|
||||
const originalProject = getProjectById(parseInt(id));
|
||||
|
||||
if (!originalProject) {
|
||||
return NextResponse.json({ error: "Project not found" }, { status: 404 });
|
||||
}
|
||||
if (!originalProject) {
|
||||
return NextResponse.json({ error: "Project not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// Track field changes for specific fields we want to monitor
|
||||
const fieldsToTrack = ['finish_date', 'project_status', 'assigned_to', 'contract_id'];
|
||||
|
||||
for (const fieldName of fieldsToTrack) {
|
||||
if (data.hasOwnProperty(fieldName)) {
|
||||
const oldValue = originalProject[fieldName];
|
||||
const newValue = data[fieldName];
|
||||
|
||||
if (oldValue !== newValue) {
|
||||
try {
|
||||
logFieldChange('projects', parseInt(id), fieldName, oldValue, newValue, userId);
|
||||
} catch (error) {
|
||||
console.error(`Failed to log field change for ${fieldName}:`, error);
|
||||
// Track field changes for specific fields we want to monitor
|
||||
const fieldsToTrack = ['finish_date', 'project_status', 'assigned_to', 'contract_id'];
|
||||
|
||||
for (const fieldName of fieldsToTrack) {
|
||||
if (data.hasOwnProperty(fieldName)) {
|
||||
const oldValue = originalProject[fieldName];
|
||||
const newValue = data[fieldName];
|
||||
|
||||
if (oldValue !== newValue) {
|
||||
try {
|
||||
logFieldChange('projects', parseInt(id), fieldName, oldValue, newValue, userId);
|
||||
} catch (error) {
|
||||
console.error(`Failed to log field change for ${fieldName}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateProject(parseInt(id), data, userId);
|
||||
|
||||
// Get updated project
|
||||
const updatedProject = getProjectById(parseInt(id));
|
||||
|
||||
// Log project update
|
||||
await logApiActionSafe(
|
||||
req,
|
||||
AUDIT_ACTIONS.PROJECT_UPDATE,
|
||||
RESOURCE_TYPES.PROJECT,
|
||||
id,
|
||||
req.auth, // Use req.auth instead of req.session
|
||||
{
|
||||
originalData: originalProject,
|
||||
updatedData: data,
|
||||
changedFields: Object.keys(data),
|
||||
// Special handling for project cancellation
|
||||
if (data.project_status === 'cancelled' && originalProject.project_status !== 'cancelled') {
|
||||
const now = new Date();
|
||||
const cancellationDate = now.toLocaleDateString('pl-PL', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
|
||||
const cancellationNote = `Projekt został wycofany w dniu ${cancellationDate}`;
|
||||
|
||||
try {
|
||||
addNoteToProject(parseInt(id), cancellationNote, userId, true); // true for is_system
|
||||
} catch (error) {
|
||||
console.error('Failed to log project cancellation:', error);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return NextResponse.json(updatedProject);
|
||||
updateProject(parseInt(id), data, userId);
|
||||
|
||||
// Get updated project
|
||||
const updatedProject = getProjectById(parseInt(id));
|
||||
|
||||
// Log project update
|
||||
await logApiActionSafe(
|
||||
req,
|
||||
AUDIT_ACTIONS.PROJECT_UPDATE,
|
||||
RESOURCE_TYPES.PROJECT,
|
||||
id,
|
||||
req.auth, // Use req.auth instead of req.session
|
||||
{
|
||||
originalData: originalProject,
|
||||
updatedData: data,
|
||||
changedFields: Object.keys(data),
|
||||
}
|
||||
);
|
||||
|
||||
return NextResponse.json(updatedProject);
|
||||
} catch (error) {
|
||||
console.error("Error in updateProjectHandler:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Internal server error", details: error.message },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteProjectHandler(req, { params }) {
|
||||
|
||||
@@ -29,6 +29,7 @@ function ProjectsMapPageContent() {
|
||||
in_progress_design: true,
|
||||
in_progress_construction: true,
|
||||
fulfilled: true,
|
||||
cancelled: true,
|
||||
});
|
||||
const [activeBaseLayer, setActiveBaseLayer] = useState("OpenStreetMap");
|
||||
const [activeOverlays, setActiveOverlays] = useState([]);
|
||||
@@ -57,6 +58,11 @@ function ProjectsMapPageContent() {
|
||||
label: "Completed",
|
||||
shortLabel: "Zakończony",
|
||||
},
|
||||
cancelled: {
|
||||
color: "#EF4444",
|
||||
label: "Cancelled",
|
||||
shortLabel: "Wycofany",
|
||||
},
|
||||
};
|
||||
|
||||
// Toggle all status filters
|
||||
|
||||
@@ -119,6 +119,7 @@ export default function ProjectListPage() {
|
||||
case "in_progress_design": return t('projectStatus.in_progress_design');
|
||||
case "in_progress_construction": return t('projectStatus.in_progress_construction');
|
||||
case "fulfilled": return t('projectStatus.fulfilled');
|
||||
case "cancelled": return t('projectStatus.cancelled');
|
||||
default: return "-";
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user