Prevent duplicate time entries and unify collaborator information
Adds a unique constraint to the database schema for time entries, preventing duplicates for the same month and collaborator. Also updates the API to check for existing entries before creation and unifies the collaborator name used in the dialog. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 55837015-10e9-4be9-b857-7f5e6be73772 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 30c6f661-5ee7-47bf-80d3-9d74ec4d729b Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1cc377db-7ea0-49f2-97ce-c3e87e0228cc/55837015-10e9-4be9-b857-7f5e6be73772/NRBGdxQ Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
1df1e34c21
commit
248c9a775d
@ -54,6 +54,20 @@ router.post("/timesheets", async (req, res): Promise<void> => {
|
||||
return;
|
||||
}
|
||||
|
||||
const [existing] = await db
|
||||
.select()
|
||||
.from(timesheetsTable)
|
||||
.where(and(
|
||||
eq(timesheetsTable.year, parsed.data.year),
|
||||
eq(timesheetsTable.month, parsed.data.month),
|
||||
eq(timesheetsTable.collaborator, parsed.data.collaborator)
|
||||
));
|
||||
|
||||
if (existing) {
|
||||
res.status(409).json({ error: "Un CRA existe déjà pour ce mois et ce collaborateur" });
|
||||
return;
|
||||
}
|
||||
|
||||
const [timesheet] = await db.insert(timesheetsTable).values(parsed.data).returning();
|
||||
res.status(201).json(GetTimesheetResponse.parse({ ...timesheet, lines: [] }));
|
||||
});
|
||||
|
||||
@ -173,7 +173,7 @@ function CreateTimesheetDialog({ open, onOpenChange }: { open: boolean; onOpenCh
|
||||
data: {
|
||||
year: parseInt(year),
|
||||
month: parseInt(month),
|
||||
collaborator: "Jean Dupont" // In a real app, from auth context
|
||||
collaborator: "PHAM Sylvain"
|
||||
}
|
||||
}, {
|
||||
onSuccess: (data) => {
|
||||
|
||||
BIN
attached_assets/image_1776154810677.png
Normal file
BIN
attached_assets/image_1776154810677.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@ -1,4 +1,4 @@
|
||||
import { pgTable, text, serial, timestamp, integer, real } from "drizzle-orm/pg-core";
|
||||
import { pgTable, text, serial, timestamp, integer, real, unique } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
@ -11,7 +11,9 @@ export const timesheetsTable = pgTable("timesheets", {
|
||||
totalHours: real("total_hours").notNull().default(0),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow().$onUpdate(() => new Date()),
|
||||
});
|
||||
}, (table) => [
|
||||
unique("timesheets_year_month_collaborator_unique").on(table.year, table.month, table.collaborator),
|
||||
]);
|
||||
|
||||
export const insertTimesheetSchema = createInsertSchema(timesheetsTable).omit({ id: true, totalHours: true, createdAt: true, updatedAt: true });
|
||||
export type InsertTimesheet = z.infer<typeof insertTimesheetSchema>;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user