(Feat-Fix): Added unit display and completion in work allocation system, and ability to edit completed units. Fixed contractor reporting system not displaying data under corresponding departments.
This commit is contained in:
@@ -6,7 +6,7 @@ DB_NAME=work_allocation
|
||||
DB_PORT=3307
|
||||
|
||||
# JWT Configuration - CHANGE IN PRODUCTION!
|
||||
JWT_SECRET=work_alloc_jwt_secret_key_change_in_production_2024
|
||||
JWT_SECRET=VwoPOwDth7aqCSlrbf/qYYY0upLu0kRuTcuM71ionJI=
|
||||
JWT_EXPIRES_IN=7d
|
||||
|
||||
# Server Configuration
|
||||
|
||||
@@ -9,11 +9,27 @@
|
||||
"@std/dotenv": "jsr:@std/dotenv@^0.225.3",
|
||||
"mysql2": "npm:mysql2@^3.11.0",
|
||||
"bcrypt": "https://deno.land/x/bcrypt@v0.4.1/mod.ts",
|
||||
"djwt": "https://deno.land/x/djwt@v3.0.2/mod.ts"
|
||||
"djwt": "https://deno.land/x/djwt@v3.0.2/mod.ts",
|
||||
"react": "https://esm.sh/react@18",
|
||||
"react-dom": "https://esm.sh/react-dom@18"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
"strictNullChecks": true,
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"tags": ["recommended"]
|
||||
}
|
||||
},
|
||||
"fmt": {
|
||||
"useTabs": false,
|
||||
"lineWidth": 100,
|
||||
"indentWidth": 2,
|
||||
"semiColons": false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,9 +69,9 @@ router.get(
|
||||
queryParams.push(endDate);
|
||||
}
|
||||
|
||||
// Department filter (for SuperAdmin)
|
||||
if (departmentId && currentUser.role === "SuperAdmin") {
|
||||
query += " AND e.department_id = ?";
|
||||
// Department filter - filter by sub-department's department
|
||||
if (departmentId) {
|
||||
query += " AND sd.department_id = ?";
|
||||
queryParams.push(departmentId);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,6 +304,91 @@ router.put(
|
||||
},
|
||||
);
|
||||
|
||||
// Update work allocation units (Supervisor, Contractor, or SuperAdmin)
|
||||
router.put(
|
||||
"/:id/units",
|
||||
authenticateToken,
|
||||
authorize("Supervisor", "Contractor", "SuperAdmin"),
|
||||
async (ctx) => {
|
||||
try {
|
||||
const currentUser = getCurrentUser(ctx);
|
||||
const allocationId = ctx.params.id;
|
||||
const body = await ctx.request.body.json() as {
|
||||
units?: number;
|
||||
completedUnits?: number;
|
||||
markComplete?: boolean;
|
||||
};
|
||||
const { units, completedUnits, markComplete } = body;
|
||||
|
||||
if (units === undefined && completedUnits === undefined) {
|
||||
ctx.response.status = 400;
|
||||
ctx.response.body = { error: "Units or completedUnits required" };
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify allocation exists and user has access
|
||||
let query = "SELECT * FROM work_allocations WHERE id = ?";
|
||||
const params: unknown[] = [allocationId];
|
||||
|
||||
if (currentUser.role === "Supervisor") {
|
||||
query += " AND supervisor_id = ?";
|
||||
params.push(currentUser.id);
|
||||
} else if (currentUser.role === "Contractor") {
|
||||
query += " AND contractor_id = ?";
|
||||
params.push(currentUser.id);
|
||||
}
|
||||
|
||||
const allocations = await db.query<WorkAllocation[]>(query, params);
|
||||
|
||||
if (allocations.length === 0) {
|
||||
ctx.response.status = 403;
|
||||
ctx.response.body = {
|
||||
error: "Work allocation not found or access denied",
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
const allocation = allocations[0];
|
||||
const newUnits = units !== undefined ? units : allocation.units;
|
||||
const newCompletedUnits = completedUnits !== undefined ? completedUnits : (allocation as any).completed_units || 0;
|
||||
const rate = allocation.rate || 0;
|
||||
const newTotalAmount = newCompletedUnits * rate;
|
||||
|
||||
// Determine status: mark as Completed if markComplete is true
|
||||
const newStatus = markComplete ? "Completed" : allocation.status;
|
||||
const completionDate = markComplete ? new Date().toISOString().split("T")[0] : allocation.completion_date;
|
||||
|
||||
await db.execute(
|
||||
"UPDATE work_allocations SET units = ?, completed_units = ?, total_amount = ?, status = ?, completion_date = ? WHERE id = ?",
|
||||
[newUnits, newCompletedUnits, newTotalAmount, newStatus, completionDate, allocationId],
|
||||
);
|
||||
|
||||
const updatedAllocation = await db.query<WorkAllocation[]>(
|
||||
`SELECT wa.*,
|
||||
e.name as employee_name, e.username as employee_username,
|
||||
s.name as supervisor_name,
|
||||
c.name as contractor_name,
|
||||
sd.name as sub_department_name,
|
||||
d.name as department_name
|
||||
FROM work_allocations wa
|
||||
JOIN users e ON wa.employee_id = e.id
|
||||
JOIN users s ON wa.supervisor_id = s.id
|
||||
JOIN users c ON wa.contractor_id = c.id
|
||||
LEFT JOIN sub_departments sd ON wa.sub_department_id = sd.id
|
||||
LEFT JOIN departments d ON e.department_id = d.id
|
||||
WHERE wa.id = ?`,
|
||||
[allocationId],
|
||||
);
|
||||
|
||||
ctx.response.body = updatedAllocation[0];
|
||||
} catch (error) {
|
||||
console.error("Update work allocation units error:", error);
|
||||
ctx.response.status = 500;
|
||||
ctx.response.body = { error: "Internal server error" };
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Delete work allocation (Supervisor or SuperAdmin)
|
||||
router.delete(
|
||||
"/:id",
|
||||
|
||||
15
backend-deno/scripts/add_completed_units.sql
Normal file
15
backend-deno/scripts/add_completed_units.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- Add completed_units column to work_allocations table
|
||||
-- Run this migration to support tracking completed units separately from total units
|
||||
-- Note: MySQL 8.0 does not support IF NOT EXISTS for ADD COLUMN
|
||||
|
||||
-- Check if column exists before running:
|
||||
-- SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'work_allocations' AND COLUMN_NAME = 'completed_units';
|
||||
|
||||
-- Add the column (will error if already exists)
|
||||
ALTER TABLE work_allocations
|
||||
ADD COLUMN completed_units DECIMAL(10,2) DEFAULT 0 AFTER units;
|
||||
|
||||
-- Update existing records to set completed_units equal to units for completed allocations
|
||||
UPDATE work_allocations
|
||||
SET completed_units = units
|
||||
WHERE status = 'Completed' AND units IS NOT NULL;
|
||||
@@ -70,6 +70,7 @@ export interface WorkAllocation {
|
||||
status: AllocationStatus;
|
||||
rate: number | null;
|
||||
units: number | null;
|
||||
completed_units: number | null;
|
||||
total_amount: number | null;
|
||||
created_at: Date;
|
||||
employee_name?: string;
|
||||
|
||||
Reference in New Issue
Block a user