@open-mercato/core 0.6.6-develop.6153.1.b4c555b820 → 0.6.6-develop.6159.1.82dfc232ca
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +32 -0
- package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/archive/route.js +63 -0
- package/dist/modules/messages/api/[id]/archive/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/attachments/route.js +63 -0
- package/dist/modules/messages/api/[id]/attachments/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/archive/route.js +32 -0
- package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/read/route.js +32 -0
- package/dist/modules/messages/api/[id]/conversation/read/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/route.js +32 -0
- package/dist/modules/messages/api/[id]/conversation/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/forward/route.js +32 -0
- package/dist/modules/messages/api/[id]/forward/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/read/route.js +63 -0
- package/dist/modules/messages/api/[id]/read/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/reply/route.js +32 -0
- package/dist/modules/messages/api/[id]/reply/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +63 -0
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/guards.js +31 -0
- package/dist/modules/messages/api/guards.js.map +7 -0
- package/dist/modules/messages/api/route.js +32 -0
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +107 -0
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-entries.js +142 -1
- package/dist/modules/staff/commands/timesheets-entries.js.map +3 -3
- package/dist/modules/staff/data/validators.js +8 -0
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +8 -22
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/startTimer.js +22 -0
- package/dist/modules/staff/lib/timesheets-ui/startTimer.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +6 -16
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +34 -0
- package/src/modules/messages/api/[id]/archive/route.ts +63 -0
- package/src/modules/messages/api/[id]/attachments/route.ts +63 -0
- package/src/modules/messages/api/[id]/conversation/archive/route.ts +33 -0
- package/src/modules/messages/api/[id]/conversation/read/route.ts +33 -0
- package/src/modules/messages/api/[id]/conversation/route.ts +33 -0
- package/src/modules/messages/api/[id]/forward/route.ts +33 -0
- package/src/modules/messages/api/[id]/read/route.ts +63 -0
- package/src/modules/messages/api/[id]/reply/route.ts +33 -0
- package/src/modules/messages/api/[id]/route.ts +65 -0
- package/src/modules/messages/api/guards.ts +59 -0
- package/src/modules/messages/api/route.ts +33 -0
- package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +110 -0
- package/src/modules/staff/commands/timesheets-entries.ts +166 -1
- package/src/modules/staff/data/validators.ts +9 -0
- package/src/modules/staff/i18n/de.json +1 -0
- package/src/modules/staff/i18n/en.json +1 -0
- package/src/modules/staff/i18n/es.json +1 -0
- package/src/modules/staff/i18n/pl.json +1 -0
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +9 -25
- package/src/modules/staff/lib/timesheets-ui/startTimer.ts +40 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +9 -18
|
@@ -4,12 +4,14 @@ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
|
4
4
|
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
5
5
|
import { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from "@open-mercato/shared/lib/commands/helpers";
|
|
6
6
|
import { makeCreateRedo } from "@open-mercato/shared/lib/commands/redo";
|
|
7
|
-
import { StaffTimeEntry, StaffTimeProject } from "../data/entities.js";
|
|
7
|
+
import { StaffTimeEntry, StaffTimeEntrySegment, StaffTimeProject } from "../data/entities.js";
|
|
8
|
+
import { emitStaffEvent } from "../events.js";
|
|
8
9
|
const timeEntryCrudIndexer = {
|
|
9
10
|
entityType: "staff:staff_time_entry"
|
|
10
11
|
};
|
|
11
12
|
import {
|
|
12
13
|
staffTimeEntryCreateSchema,
|
|
14
|
+
staffTimeEntryStartTimerSchema,
|
|
13
15
|
staffTimeEntryUpdateSchema
|
|
14
16
|
} from "../data/validators.js";
|
|
15
17
|
import { staffTimeEntryCrudEvents } from "../lib/crud.js";
|
|
@@ -202,6 +204,144 @@ const createTimeEntryCommand = {
|
|
|
202
204
|
indexer: timeEntryCrudIndexer
|
|
203
205
|
})
|
|
204
206
|
};
|
|
207
|
+
const startTimerCommand = {
|
|
208
|
+
id: "staff.timesheets.time_entries.start_timer",
|
|
209
|
+
async execute(rawInput, ctx) {
|
|
210
|
+
const parsed = staffTimeEntryStartTimerSchema.parse(rawInput);
|
|
211
|
+
ensureTenantScope(ctx, parsed.tenantId);
|
|
212
|
+
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
213
|
+
const em = ctx.container.resolve("em").fork();
|
|
214
|
+
let effectiveStaffMemberId = parsed.staffMemberId;
|
|
215
|
+
if (!await callerHasManageAll(ctx)) {
|
|
216
|
+
const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx);
|
|
217
|
+
if (!callerStaffMemberId) {
|
|
218
|
+
const { translate } = await resolveTranslations();
|
|
219
|
+
throw new CrudHttpError(403, {
|
|
220
|
+
error: translate("staff.timesheets.errors.noStaffMember", "No staff member linked to your account.")
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
effectiveStaffMemberId = callerStaffMemberId;
|
|
224
|
+
}
|
|
225
|
+
await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId);
|
|
226
|
+
const scopeCtx = { tenantId: parsed.tenantId, organizationId: parsed.organizationId };
|
|
227
|
+
const { entry, startedAt } = await em.transactional(async (trx) => {
|
|
228
|
+
const otherRunningEntry = await findOneWithDecryption(
|
|
229
|
+
trx,
|
|
230
|
+
StaffTimeEntry,
|
|
231
|
+
{
|
|
232
|
+
tenantId: parsed.tenantId,
|
|
233
|
+
organizationId: parsed.organizationId,
|
|
234
|
+
staffMemberId: effectiveStaffMemberId,
|
|
235
|
+
startedAt: { $ne: null },
|
|
236
|
+
endedAt: null,
|
|
237
|
+
deletedAt: null
|
|
238
|
+
},
|
|
239
|
+
{},
|
|
240
|
+
scopeCtx
|
|
241
|
+
);
|
|
242
|
+
if (otherRunningEntry) {
|
|
243
|
+
const { translate } = await resolveTranslations();
|
|
244
|
+
throw new CrudHttpError(409, {
|
|
245
|
+
error: translate(
|
|
246
|
+
"staff.timesheets.errors.timerAlreadyRunning",
|
|
247
|
+
"Another timer is already running. Stop it before starting a new one."
|
|
248
|
+
)
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
const startedAt2 = /* @__PURE__ */ new Date();
|
|
252
|
+
const entry2 = trx.create(StaffTimeEntry, {
|
|
253
|
+
tenantId: parsed.tenantId,
|
|
254
|
+
organizationId: parsed.organizationId,
|
|
255
|
+
staffMemberId: effectiveStaffMemberId,
|
|
256
|
+
date: parsed.date,
|
|
257
|
+
durationMinutes: 0,
|
|
258
|
+
startedAt: startedAt2,
|
|
259
|
+
endedAt: null,
|
|
260
|
+
notes: parsed.notes ?? null,
|
|
261
|
+
timeProjectId: parsed.timeProjectId ?? null,
|
|
262
|
+
customerId: null,
|
|
263
|
+
dealId: null,
|
|
264
|
+
orderId: null,
|
|
265
|
+
source: "timer",
|
|
266
|
+
createdAt: startedAt2,
|
|
267
|
+
updatedAt: startedAt2,
|
|
268
|
+
deletedAt: null
|
|
269
|
+
});
|
|
270
|
+
await trx.flush();
|
|
271
|
+
const segmentData = {
|
|
272
|
+
tenantId: parsed.tenantId,
|
|
273
|
+
organizationId: parsed.organizationId,
|
|
274
|
+
timeEntryId: entry2.id,
|
|
275
|
+
startedAt: startedAt2,
|
|
276
|
+
segmentType: "work"
|
|
277
|
+
};
|
|
278
|
+
trx.create(StaffTimeEntrySegment, segmentData);
|
|
279
|
+
await trx.flush();
|
|
280
|
+
return { entry: entry2, startedAt: startedAt2 };
|
|
281
|
+
});
|
|
282
|
+
await emitCrudSideEffects({
|
|
283
|
+
dataEngine: ctx.container.resolve("dataEngine"),
|
|
284
|
+
action: "created",
|
|
285
|
+
entity: entry,
|
|
286
|
+
identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },
|
|
287
|
+
events: staffTimeEntryCrudEvents,
|
|
288
|
+
indexer: timeEntryCrudIndexer
|
|
289
|
+
});
|
|
290
|
+
void emitStaffEvent("staff.timesheets.time_entry.timer_started", {
|
|
291
|
+
id: entry.id,
|
|
292
|
+
staffMemberId: effectiveStaffMemberId,
|
|
293
|
+
tenantId: parsed.tenantId,
|
|
294
|
+
organizationId: parsed.organizationId,
|
|
295
|
+
startedAt: startedAt.toISOString()
|
|
296
|
+
}, { persistent: true }).catch((err) => {
|
|
297
|
+
console.error("[staff.timesheets] emit timer_started failed", err);
|
|
298
|
+
});
|
|
299
|
+
return { timeEntryId: entry.id };
|
|
300
|
+
},
|
|
301
|
+
captureAfter: async (_input, result, ctx) => {
|
|
302
|
+
const em = ctx.container.resolve("em").fork();
|
|
303
|
+
const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId);
|
|
304
|
+
if (!snapshot) return null;
|
|
305
|
+
return { snapshot };
|
|
306
|
+
},
|
|
307
|
+
buildLog: async ({ result, ctx }) => {
|
|
308
|
+
const em = ctx.container.resolve("em").fork();
|
|
309
|
+
const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId);
|
|
310
|
+
if (!snapshot) return null;
|
|
311
|
+
const { translate } = await resolveTranslations();
|
|
312
|
+
return {
|
|
313
|
+
actionLabel: translate("staff.audit.timesheets.time_entries.startTimer", "Start timer"),
|
|
314
|
+
resourceKind: "staff.timesheets.time_entry",
|
|
315
|
+
resourceId: snapshot.id,
|
|
316
|
+
tenantId: snapshot.tenantId,
|
|
317
|
+
organizationId: snapshot.organizationId,
|
|
318
|
+
snapshotAfter: snapshot,
|
|
319
|
+
payload: {
|
|
320
|
+
undo: {
|
|
321
|
+
after: snapshot
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
},
|
|
326
|
+
undo: async ({ logEntry, ctx }) => {
|
|
327
|
+
const payload = extractUndoPayload(logEntry);
|
|
328
|
+
const after = payload?.after;
|
|
329
|
+
if (!after) return;
|
|
330
|
+
const em = ctx.container.resolve("em").fork();
|
|
331
|
+
const entry = await em.findOne(StaffTimeEntry, { id: after.id });
|
|
332
|
+
if (entry) {
|
|
333
|
+
entry.deletedAt = /* @__PURE__ */ new Date();
|
|
334
|
+
await em.flush();
|
|
335
|
+
await emitCrudUndoSideEffects({
|
|
336
|
+
dataEngine: ctx.container.resolve("dataEngine"),
|
|
337
|
+
action: "deleted",
|
|
338
|
+
entity: entry,
|
|
339
|
+
identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },
|
|
340
|
+
events: staffTimeEntryCrudEvents
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
205
345
|
const updateTimeEntryCommand = {
|
|
206
346
|
id: "staff.timesheets.time_entries.update",
|
|
207
347
|
async prepare(rawInput, ctx) {
|
|
@@ -434,6 +574,7 @@ const deleteTimeEntryCommand = {
|
|
|
434
574
|
}
|
|
435
575
|
};
|
|
436
576
|
registerCommand(createTimeEntryCommand);
|
|
577
|
+
registerCommand(startTimerCommand);
|
|
437
578
|
registerCommand(updateTimeEntryCommand);
|
|
438
579
|
registerCommand(deleteTimeEntryCommand);
|
|
439
580
|
//# sourceMappingURL=timesheets-entries.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/timesheets-entries.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTimeEntry, StaffTimeProject, type StaffTimeEntrySource } from '../data/entities'\n\nconst timeEntryCrudIndexer: CrudIndexerConfig<StaffTimeEntry> = {\n entityType: 'staff:staff_time_entry',\n}\nimport {\n staffTimeEntryCreateSchema,\n staffTimeEntryUpdateSchema,\n type StaffTimeEntryCreateInput,\n type StaffTimeEntryUpdateInput,\n} from '../data/validators'\nimport { staffTimeEntryCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { getStaffMemberByUserId } from '../lib/staffMemberResolver'\n\ntype RbacServiceLike = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n scope: { tenantId: string | null; organizationId: string | null },\n ) => Promise<boolean>\n}\n\n/**\n * Returns true when the caller holds `staff.timesheets.manage_all`, honoring\n * wildcard ACL grants (`staff.*`, `*`) and the super-admin flag via the cached\n * rbacService. Returns false when no auth context (e.g. system/CLI ctx) so\n * write paths that lack a caller identity are NOT silently elevated.\n */\nasync function callerHasManageAll(ctx: {\n auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null\n container: { resolve: (token: string) => unknown }\n}): Promise<boolean> {\n const userId = ctx.auth?.sub\n if (!userId) return false\n try {\n const rbac = ctx.container.resolve('rbacService') as RbacServiceLike | undefined\n if (!rbac?.userHasAllFeatures) return false\n return await rbac.userHasAllFeatures(\n userId,\n ['staff.timesheets.manage_all'],\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n } catch {\n return false\n }\n}\n\nasync function resolveCallerStaffMemberId(\n em: EntityManager,\n ctx: { auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null },\n): Promise<string | null> {\n const userId = ctx.auth?.sub\n if (!userId) return null\n const member = await getStaffMemberByUserId(\n em,\n userId,\n ctx.auth?.tenantId ?? null,\n ctx.auth?.orgId ?? null,\n )\n return member?.id ?? null\n}\n\n/**\n * Verifies the referenced time project exists and is in-scope (same tenant + org,\n * not soft-deleted). Throws 422 if the ID is provided but unresolvable.\n * No-op when projectId is null/undefined (timeProjectId is optional on entries).\n */\nasync function assertTimeProjectInScope(\n em: EntityManager,\n projectId: string | null | undefined,\n tenantId: string,\n organizationId: string,\n): Promise<void> {\n if (!projectId) return\n const exists = await em.findOne(\n StaffTimeProject,\n { id: projectId, tenantId, organizationId, deletedAt: null },\n { fields: ['id'] },\n )\n if (!exists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n}\n\ntype TimeEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n staffMemberId: string\n date: string\n durationMinutes: number\n startedAt: string | null\n endedAt: string | null\n notes: string | null\n timeProjectId: string | null\n customerId: string | null\n dealId: string | null\n orderId: string | null\n source: string\n deletedAt: string | null\n}\n\ntype TimeEntryUndoPayload = {\n before?: TimeEntrySnapshot | null\n after?: TimeEntrySnapshot | null\n}\n\nasync function loadTimeEntrySnapshot(em: EntityManager, id: string): Promise<TimeEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, StaffTimeEntry, { id }, undefined, { tenantId: null, organizationId: null })\n if (!entry) return null\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n staffMemberId: entry.staffMemberId,\n date: entry.date instanceof Date ? entry.date.toISOString().split('T')[0] : String(entry.date),\n durationMinutes: entry.durationMinutes,\n startedAt: entry.startedAt ? entry.startedAt.toISOString() : null,\n endedAt: entry.endedAt ? entry.endedAt.toISOString() : null,\n notes: entry.notes ?? null,\n timeProjectId: entry.timeProjectId ?? null,\n customerId: entry.customerId ?? null,\n dealId: entry.dealId ?? null,\n orderId: entry.orderId ?? null,\n source: entry.source,\n deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeEntrySeedFromSnapshot(snapshot: TimeEntrySnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n staffMemberId: snapshot.staffMemberId,\n date: snapshot.date,\n durationMinutes: snapshot.durationMinutes,\n startedAt: snapshot.startedAt ? new Date(snapshot.startedAt) : null,\n endedAt: snapshot.endedAt ? new Date(snapshot.endedAt) : null,\n notes: snapshot.notes ?? null,\n timeProjectId: snapshot.timeProjectId ?? null,\n customerId: snapshot.customerId ?? null,\n dealId: snapshot.dealId ?? null,\n orderId: snapshot.orderId ?? null,\n source: (snapshot.source ?? 'manual') as StaffTimeEntrySource,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeEntryCommand: CommandHandler<StaffTimeEntryCreateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only create entries attributed to themselves. Silent override\n // (mirrors `bulk/route.ts` behavior) so the request body's staffMemberId\n // can't forge an entry under a colleague's identity.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n // Validate referenced timeProjectId is in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const entry = em.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: parsed.durationMinutes,\n startedAt: parsed.startedAt ?? null,\n endedAt: parsed.endedAt ?? null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: parsed.customerId ?? null,\n dealId: parsed.dealId ?? null,\n orderId: parsed.orderId ?? null,\n source: parsed.source ?? 'manual',\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(entry)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.create', 'Create time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: after.id })\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeEntry, TimeEntrySnapshot, StaffTimeEntryCreateInput, { timeEntryId: string }>({\n entityClass: StaffTimeEntry,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeEntrySeedFromSnapshot,\n buildResult: (entity) => ({ timeEntryId: entity.id }),\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n }),\n}\n\nconst updateTimeEntryCommand: CommandHandler<StaffTimeEntryUpdateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, parsed.id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n { id: parsed.id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only update entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n // Validate referenced timeProjectId is in-scope when it's being changed to a non-null value.\n if (parsed.timeProjectId !== undefined && parsed.timeProjectId !== null) {\n await assertTimeProjectInScope(em, parsed.timeProjectId, entry.tenantId, entry.organizationId)\n }\n\n if (parsed.date !== undefined) entry.date = parsed.date\n if (parsed.durationMinutes !== undefined) entry.durationMinutes = parsed.durationMinutes\n if (parsed.timeProjectId !== undefined) entry.timeProjectId = parsed.timeProjectId ?? null\n if (parsed.customerId !== undefined) entry.customerId = parsed.customerId ?? null\n if (parsed.dealId !== undefined) entry.dealId = parsed.dealId ?? null\n if (parsed.orderId !== undefined) entry.orderId = parsed.orderId ?? null\n if (parsed.notes !== undefined) entry.notes = parsed.notes ?? null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeEntrySnapshot(em, before.id)\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'date',\n 'durationMinutes',\n 'timeProjectId',\n 'customerId',\n 'dealId',\n 'orderId',\n 'notes',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.update', 'Update time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) return\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.notes = before.notes ?? null\n entry.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nconst deleteTimeEntryCommand: CommandHandler<{ id?: string }, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n { id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only delete entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n entry.deletedAt = new Date()\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.delete', 'Delete time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) {\n entry = em.create(StaffTimeEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n staffMemberId: before.staffMemberId,\n date: before.date as unknown as Date,\n durationMinutes: before.durationMinutes,\n startedAt: before.startedAt ? new Date(before.startedAt) : null,\n endedAt: before.endedAt ? new Date(before.endedAt) : null,\n notes: before.notes ?? null,\n timeProjectId: before.timeProjectId ?? null,\n customerId: before.customerId ?? null,\n dealId: before.dealId ?? null,\n orderId: before.orderId ?? null,\n source: (before.source ?? 'manual') as StaffTimeEntrySource,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n } else {\n entry.staffMemberId = before.staffMemberId\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.startedAt = before.startedAt ? new Date(before.startedAt) : null\n entry.endedAt = before.endedAt ? new Date(before.endedAt) : null\n entry.notes = before.notes ?? null\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.source = (before.source ?? 'manual') as StaffTimeEntrySource\n entry.deletedAt = null\n entry.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeEntryCommand)\nregisterCommand(updateTimeEntryCommand)\nregisterCommand(deleteTimeEntryCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTimeEntry, StaffTimeEntrySegment, StaffTimeProject, type StaffTimeEntrySource } from '../data/entities'\nimport { emitStaffEvent } from '../events'\n\nconst timeEntryCrudIndexer: CrudIndexerConfig<StaffTimeEntry> = {\n entityType: 'staff:staff_time_entry',\n}\nimport {\n staffTimeEntryCreateSchema,\n staffTimeEntryStartTimerSchema,\n staffTimeEntryUpdateSchema,\n type StaffTimeEntryCreateInput,\n type StaffTimeEntryStartTimerInput,\n type StaffTimeEntryUpdateInput,\n} from '../data/validators'\nimport { staffTimeEntryCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { getStaffMemberByUserId } from '../lib/staffMemberResolver'\n\ntype RbacServiceLike = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n scope: { tenantId: string | null; organizationId: string | null },\n ) => Promise<boolean>\n}\n\n/**\n * Returns true when the caller holds `staff.timesheets.manage_all`, honoring\n * wildcard ACL grants (`staff.*`, `*`) and the super-admin flag via the cached\n * rbacService. Returns false when no auth context (e.g. system/CLI ctx) so\n * write paths that lack a caller identity are NOT silently elevated.\n */\nasync function callerHasManageAll(ctx: {\n auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null\n container: { resolve: (token: string) => unknown }\n}): Promise<boolean> {\n const userId = ctx.auth?.sub\n if (!userId) return false\n try {\n const rbac = ctx.container.resolve('rbacService') as RbacServiceLike | undefined\n if (!rbac?.userHasAllFeatures) return false\n return await rbac.userHasAllFeatures(\n userId,\n ['staff.timesheets.manage_all'],\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n } catch {\n return false\n }\n}\n\nasync function resolveCallerStaffMemberId(\n em: EntityManager,\n ctx: { auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null },\n): Promise<string | null> {\n const userId = ctx.auth?.sub\n if (!userId) return null\n const member = await getStaffMemberByUserId(\n em,\n userId,\n ctx.auth?.tenantId ?? null,\n ctx.auth?.orgId ?? null,\n )\n return member?.id ?? null\n}\n\n/**\n * Verifies the referenced time project exists and is in-scope (same tenant + org,\n * not soft-deleted). Throws 422 if the ID is provided but unresolvable.\n * No-op when projectId is null/undefined (timeProjectId is optional on entries).\n */\nasync function assertTimeProjectInScope(\n em: EntityManager,\n projectId: string | null | undefined,\n tenantId: string,\n organizationId: string,\n): Promise<void> {\n if (!projectId) return\n const exists = await em.findOne(\n StaffTimeProject,\n { id: projectId, tenantId, organizationId, deletedAt: null },\n { fields: ['id'] },\n )\n if (!exists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n}\n\ntype TimeEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n staffMemberId: string\n date: string\n durationMinutes: number\n startedAt: string | null\n endedAt: string | null\n notes: string | null\n timeProjectId: string | null\n customerId: string | null\n dealId: string | null\n orderId: string | null\n source: string\n deletedAt: string | null\n}\n\ntype TimeEntryUndoPayload = {\n before?: TimeEntrySnapshot | null\n after?: TimeEntrySnapshot | null\n}\n\nasync function loadTimeEntrySnapshot(em: EntityManager, id: string): Promise<TimeEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, StaffTimeEntry, { id }, undefined, { tenantId: null, organizationId: null })\n if (!entry) return null\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n staffMemberId: entry.staffMemberId,\n date: entry.date instanceof Date ? entry.date.toISOString().split('T')[0] : String(entry.date),\n durationMinutes: entry.durationMinutes,\n startedAt: entry.startedAt ? entry.startedAt.toISOString() : null,\n endedAt: entry.endedAt ? entry.endedAt.toISOString() : null,\n notes: entry.notes ?? null,\n timeProjectId: entry.timeProjectId ?? null,\n customerId: entry.customerId ?? null,\n dealId: entry.dealId ?? null,\n orderId: entry.orderId ?? null,\n source: entry.source,\n deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeEntrySeedFromSnapshot(snapshot: TimeEntrySnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n staffMemberId: snapshot.staffMemberId,\n date: snapshot.date,\n durationMinutes: snapshot.durationMinutes,\n startedAt: snapshot.startedAt ? new Date(snapshot.startedAt) : null,\n endedAt: snapshot.endedAt ? new Date(snapshot.endedAt) : null,\n notes: snapshot.notes ?? null,\n timeProjectId: snapshot.timeProjectId ?? null,\n customerId: snapshot.customerId ?? null,\n dealId: snapshot.dealId ?? null,\n orderId: snapshot.orderId ?? null,\n source: (snapshot.source ?? 'manual') as StaffTimeEntrySource,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeEntryCommand: CommandHandler<StaffTimeEntryCreateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only create entries attributed to themselves. Silent override\n // (mirrors `bulk/route.ts` behavior) so the request body's staffMemberId\n // can't forge an entry under a colleague's identity.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n // Validate referenced timeProjectId is in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const entry = em.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: parsed.durationMinutes,\n startedAt: parsed.startedAt ?? null,\n endedAt: parsed.endedAt ?? null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: parsed.customerId ?? null,\n dealId: parsed.dealId ?? null,\n orderId: parsed.orderId ?? null,\n source: parsed.source ?? 'manual',\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(entry)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.create', 'Create time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: after.id })\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeEntry, TimeEntrySnapshot, StaffTimeEntryCreateInput, { timeEntryId: string }>({\n entityClass: StaffTimeEntry,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeEntrySeedFromSnapshot,\n buildResult: (entity) => ({ timeEntryId: entity.id }),\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n }),\n}\n\nconst startTimerCommand: CommandHandler<StaffTimeEntryStartTimerInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.start_timer',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryStartTimerSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement mirrors createTimeEntryCommand: callers without\n // `staff.timesheets.manage_all` can only start their own timer, so the\n // request body's staffMemberId can't start a timer under a colleague's id.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const scopeCtx = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }\n\n // Create the timer entry AND start it inside a single transaction so a\n // partial failure can never leave an orphaned, never-started timer entry\n // (issue #3311 \u2014 the legacy two-request create-then-start flow). The\n // single-active-timer invariant (#2855) is re-checked here so a second\n // surface cannot create a parallel running timer for the same staff member.\n const { entry, startedAt } = await em.transactional(async (trx) => {\n const otherRunningEntry = await findOneWithDecryption(\n trx,\n StaffTimeEntry,\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n startedAt: { $ne: null },\n endedAt: null,\n deletedAt: null,\n },\n {},\n scopeCtx,\n )\n if (otherRunningEntry) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n 'staff.timesheets.errors.timerAlreadyRunning',\n 'Another timer is already running. Stop it before starting a new one.',\n ),\n })\n }\n\n const startedAt = new Date()\n const entry = trx.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: 0,\n startedAt,\n endedAt: null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: null,\n dealId: null,\n orderId: null,\n source: 'timer',\n createdAt: startedAt,\n updatedAt: startedAt,\n deletedAt: null,\n })\n // Flush so the DB-generated id is populated before the work segment\n // references it; both writes commit together when the transaction closes.\n await trx.flush()\n\n const segmentData = {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeEntryId: entry.id,\n startedAt,\n segmentType: 'work' as const,\n }\n trx.create(StaffTimeEntrySegment, segmentData as never)\n await trx.flush()\n\n return { entry, startedAt }\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n void emitStaffEvent('staff.timesheets.time_entry.timer_started', {\n id: entry.id,\n staffMemberId: effectiveStaffMemberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n startedAt: startedAt.toISOString(),\n }, { persistent: true }).catch((err) => {\n console.error('[staff.timesheets] emit timer_started failed', err)\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.startTimer', 'Start timer'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: after.id })\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n}\n\nconst updateTimeEntryCommand: CommandHandler<StaffTimeEntryUpdateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, parsed.id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n { id: parsed.id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only update entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n // Validate referenced timeProjectId is in-scope when it's being changed to a non-null value.\n if (parsed.timeProjectId !== undefined && parsed.timeProjectId !== null) {\n await assertTimeProjectInScope(em, parsed.timeProjectId, entry.tenantId, entry.organizationId)\n }\n\n if (parsed.date !== undefined) entry.date = parsed.date\n if (parsed.durationMinutes !== undefined) entry.durationMinutes = parsed.durationMinutes\n if (parsed.timeProjectId !== undefined) entry.timeProjectId = parsed.timeProjectId ?? null\n if (parsed.customerId !== undefined) entry.customerId = parsed.customerId ?? null\n if (parsed.dealId !== undefined) entry.dealId = parsed.dealId ?? null\n if (parsed.orderId !== undefined) entry.orderId = parsed.orderId ?? null\n if (parsed.notes !== undefined) entry.notes = parsed.notes ?? null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeEntrySnapshot(em, before.id)\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'date',\n 'durationMinutes',\n 'timeProjectId',\n 'customerId',\n 'dealId',\n 'orderId',\n 'notes',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.update', 'Update time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) return\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.notes = before.notes ?? null\n entry.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nconst deleteTimeEntryCommand: CommandHandler<{ id?: string }, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n { id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only delete entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n entry.deletedAt = new Date()\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.delete', 'Delete time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) {\n entry = em.create(StaffTimeEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n staffMemberId: before.staffMemberId,\n date: before.date as unknown as Date,\n durationMinutes: before.durationMinutes,\n startedAt: before.startedAt ? new Date(before.startedAt) : null,\n endedAt: before.endedAt ? new Date(before.endedAt) : null,\n notes: before.notes ?? null,\n timeProjectId: before.timeProjectId ?? null,\n customerId: before.customerId ?? null,\n dealId: before.dealId ?? null,\n orderId: before.orderId ?? null,\n source: (before.source ?? 'manual') as StaffTimeEntrySource,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n } else {\n entry.staffMemberId = before.staffMemberId\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.startedAt = before.startedAt ? new Date(before.startedAt) : null\n entry.endedAt = before.endedAt ? new Date(before.endedAt) : null\n entry.notes = before.notes ?? null\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.source = (before.source ?? 'manual') as StaffTimeEntrySource\n entry.deletedAt = null\n entry.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeEntryCommand)\nregisterCommand(startTimerCommand)\nregisterCommand(updateTimeEntryCommand)\nregisterCommand(deleteTimeEntryCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["startedAt", "entry"]
|
|
7
7
|
}
|
|
@@ -201,6 +201,13 @@ const staffTimeEntryUpdateSchema = z.object({
|
|
|
201
201
|
orderId: z.string().uuid().optional().nullable(),
|
|
202
202
|
notes: z.string().max(2e3).optional().nullable()
|
|
203
203
|
});
|
|
204
|
+
const staffTimeEntryStartTimerSchema = z.object({
|
|
205
|
+
...scopedCreateFields,
|
|
206
|
+
staffMemberId: z.string().uuid(),
|
|
207
|
+
date: z.coerce.date(),
|
|
208
|
+
timeProjectId: z.string().uuid().optional().nullable(),
|
|
209
|
+
notes: z.string().max(2e3).optional().nullable()
|
|
210
|
+
});
|
|
204
211
|
const staffTimeEntryBulkItemSchema = z.object({
|
|
205
212
|
id: z.string().uuid().optional().nullable(),
|
|
206
213
|
date: z.coerce.date(),
|
|
@@ -295,6 +302,7 @@ export {
|
|
|
295
302
|
staffTimeEntryCreateSchema,
|
|
296
303
|
staffTimeEntrySegmentCreateSchema,
|
|
297
304
|
staffTimeEntrySegmentUpdateSchema,
|
|
305
|
+
staffTimeEntryStartTimerSchema,
|
|
298
306
|
staffTimeEntryUpdateSchema,
|
|
299
307
|
staffTimeProjectCreateSchema,
|
|
300
308
|
staffTimeProjectMemberAssignSchema,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { PROJECT_COLOR_KEYS } from '../lib/timesheets-ui/colors'\n\nconst projectColorSchema = z\n .string()\n .refine(\n (value) => (PROJECT_COLOR_KEYS as readonly string[]).includes(value),\n { message: 'Invalid project color key.' },\n )\n\nconst tagsSchema = z.array(z.string().min(1)).optional().default([])\n\nexport const optimisticUpdatedAtSchema = z.string().refine(\n (value) => !Number.isNaN(new Date(value).getTime()),\n { message: 'Invalid datetime' },\n)\n\nconst scopedCreateFields = {\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n}\n\nconst scopedUpdateFields = {\n id: z.string().uuid(),\n}\n\nexport const staffTeamCreateSchema = z.object({\n ...scopedCreateFields,\n name: z.string().min(1),\n description: z.string().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamUpdateSchema = z.object({\n ...scopedUpdateFields,\n name: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamRoleCreateSchema = z.object({\n ...scopedCreateFields,\n teamId: z.string().uuid().optional().nullable(),\n name: z.string().min(1),\n description: z.string().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamRoleUpdateSchema = z.object({\n ...scopedUpdateFields,\n teamId: z.string().uuid().optional().nullable(),\n name: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberCreateSchema = z.object({\n ...scopedCreateFields,\n teamId: z.string().uuid().optional().nullable(),\n displayName: z.string().min(1),\n description: z.string().optional().nullable(),\n userId: z.string().uuid().optional().nullable(),\n roleIds: z.array(z.string().uuid()).optional().default([]),\n tags: tagsSchema,\n availabilityRuleSetId: z.string().uuid().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamMemberUpdateSchema = z.object({\n ...scopedUpdateFields,\n teamId: z.string().uuid().optional().nullable(),\n displayName: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n userId: z.string().uuid().optional().nullable(),\n roleIds: z.array(z.string().uuid()).optional(),\n tags: z.array(z.string().min(1)).optional(),\n availabilityRuleSetId: z.string().uuid().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamMemberActivityCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n occurredAt: z.coerce.date().optional(),\n authorUserId: z.string().uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberActivityUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberActivityCreateSchema.partial())\n\nexport const staffTeamMemberJobHistoryCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n name: z.string().min(1).max(200),\n companyName: z.string().max(200).optional().nullable(),\n description: z.string().max(2000).optional().nullable(),\n startDate: z.coerce.date(),\n endDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTeamMemberJobHistoryUpdateSchema = z\n .object({\n id: z.string().uuid(),\n updatedAt: optimisticUpdatedAtSchema.optional(),\n })\n .merge(staffTeamMemberJobHistoryCreateSchema.partial())\n\nexport const staffTeamMemberCommentCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n body: z.string().min(1).max(8000),\n authorUserId: z.string().uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberCommentUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberCommentCreateSchema.partial())\n\nexport const staffTeamMemberAddressCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce.number().optional(),\n longitude: z.coerce.number().optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const staffTeamMemberAddressUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberAddressCreateSchema.partial())\n\nexport const staffTeamMemberTagAssignmentSchema = z.object({\n ...scopedCreateFields,\n memberId: z.string().uuid(),\n tag: z.string().min(1),\n})\n\nconst staffLeaveRequestStatusSchema = z.enum(['pending', 'approved', 'rejected'])\n\nconst validateStaffLeaveRequestDateRange = (\n value: { startDate?: Date; endDate?: Date },\n ctx: z.RefinementCtx,\n) => {\n if (!value.startDate || !value.endDate) return\n if (value.endDate < value.startDate) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'End date must be after start date.',\n path: ['endDate'],\n })\n }\n}\n\nexport const staffLeaveRequestCreateSchema = z\n .object({\n ...scopedCreateFields,\n memberId: z.string().uuid(),\n timezone: z.string().min(1),\n startDate: z.coerce.date(),\n endDate: z.coerce.date(),\n unavailabilityReasonEntryId: z.string().uuid().optional().nullable(),\n unavailabilityReasonValue: z.string().trim().min(1).max(150).optional().nullable(),\n note: z.string().max(2000).optional().nullable(),\n submittedByUserId: z.string().uuid().optional().nullable(),\n })\n .superRefine(validateStaffLeaveRequestDateRange)\n\nexport const staffLeaveRequestUpdateSchema = z\n .object({\n ...scopedUpdateFields,\n timezone: z.string().min(1).optional(),\n memberId: z.string().uuid().optional(),\n startDate: z.coerce.date().optional(),\n endDate: z.coerce.date().optional(),\n unavailabilityReasonEntryId: z.string().uuid().optional().nullable(),\n unavailabilityReasonValue: z.string().trim().min(1).max(150).optional().nullable(),\n note: z.string().max(2000).optional().nullable(),\n })\n .superRefine(validateStaffLeaveRequestDateRange)\n\nexport const staffLeaveRequestDecisionSchema = z.object({\n id: z.string().uuid(),\n decisionComment: z.string().max(2000).optional().nullable(),\n decidedByUserId: z.string().uuid().optional().nullable(),\n})\n\nexport const staffTeamMemberSelfCreateSchema = z.object({\n ...scopedCreateFields,\n displayName: z.string().min(1),\n description: z.string().max(2000).optional().nullable(),\n})\n\nexport type StaffTeamCreateInput = z.infer<typeof staffTeamCreateSchema>\nexport type StaffTeamUpdateInput = z.infer<typeof staffTeamUpdateSchema>\nexport type StaffTeamRoleCreateInput = z.infer<typeof staffTeamRoleCreateSchema>\nexport type StaffTeamRoleUpdateInput = z.infer<typeof staffTeamRoleUpdateSchema>\nexport type StaffTeamMemberCreateInput = z.infer<typeof staffTeamMemberCreateSchema>\nexport type StaffTeamMemberUpdateInput = z.infer<typeof staffTeamMemberUpdateSchema>\nexport type StaffTeamMemberTagAssignmentInput = z.infer<typeof staffTeamMemberTagAssignmentSchema>\nexport type StaffTeamMemberActivityCreateInput = z.infer<typeof staffTeamMemberActivityCreateSchema>\nexport type StaffTeamMemberActivityUpdateInput = z.infer<typeof staffTeamMemberActivityUpdateSchema>\nexport type StaffTeamMemberJobHistoryCreateInput = z.infer<typeof staffTeamMemberJobHistoryCreateSchema>\nexport type StaffTeamMemberJobHistoryUpdateInput = z.infer<typeof staffTeamMemberJobHistoryUpdateSchema>\nexport type StaffTeamMemberCommentCreateInput = z.infer<typeof staffTeamMemberCommentCreateSchema>\nexport type StaffTeamMemberCommentUpdateInput = z.infer<typeof staffTeamMemberCommentUpdateSchema>\nexport type StaffTeamMemberAddressCreateInput = z.infer<typeof staffTeamMemberAddressCreateSchema>\nexport type StaffTeamMemberAddressUpdateInput = z.infer<typeof staffTeamMemberAddressUpdateSchema>\nexport type StaffLeaveRequestStatus = z.infer<typeof staffLeaveRequestStatusSchema>\nexport type StaffLeaveRequestCreateInput = z.infer<typeof staffLeaveRequestCreateSchema>\nexport type StaffLeaveRequestUpdateInput = z.infer<typeof staffLeaveRequestUpdateSchema>\nexport type StaffLeaveRequestDecisionInput = z.infer<typeof staffLeaveRequestDecisionSchema>\nexport type StaffTeamMemberSelfCreateInput = z.infer<typeof staffTeamMemberSelfCreateSchema>\n\n// --- Timesheets validators (Phase 1) ---\n\nconst timeEntrySourceSchema = z.enum(['manual', 'timer', 'kiosk', 'mobile'])\nconst timeProjectStatusSchema = z.enum(['active', 'on_hold', 'completed'])\nconst timeProjectMemberStatusSchema = z.enum(['active', 'inactive'])\nconst timeEntrySegmentTypeSchema = z.enum(['work', 'break'])\nconst projectCodeSchema = z.string().min(1).max(50).regex(/^[a-zA-Z0-9-]+$/)\n\nexport const staffTimeEntryCreateSchema = z.object({\n ...scopedCreateFields,\n staffMemberId: z.string().uuid(),\n date: z.coerce.date(),\n durationMinutes: z.number().int().min(0).max(1440),\n startedAt: z.coerce.date().optional().nullable(),\n endedAt: z.coerce.date().optional().nullable(),\n timeProjectId: z.string().uuid().optional().nullable(),\n customerId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n orderId: z.string().uuid().optional().nullable(),\n notes: z.string().max(2000).optional().nullable(),\n source: timeEntrySourceSchema.optional().default('manual'),\n})\n\nexport const staffTimeEntryUpdateSchema = z.object({\n ...scopedUpdateFields,\n date: z.coerce.date().optional(),\n durationMinutes: z.number().int().min(0).max(1440).optional(),\n timeProjectId: z.string().uuid().optional().nullable(),\n customerId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n orderId: z.string().uuid().optional().nullable(),\n notes: z.string().max(2000).optional().nullable(),\n})\n\nexport const staffTimeEntryBulkItemSchema = z.object({\n id: z.string().uuid().optional().nullable(),\n date: z.coerce.date(),\n timeProjectId: z.string().uuid(),\n durationMinutes: z.number().int().min(0).max(1440),\n notes: z.string().max(2000).optional().nullable(),\n})\n\nexport const staffTimeEntryBulkSaveSchema = z.object({\n entries: z.array(staffTimeEntryBulkItemSchema).min(1).max(200),\n})\n\nexport const staffTimeEntrySegmentCreateSchema = z.object({\n ...scopedCreateFields,\n timeEntryId: z.string().uuid(),\n startedAt: z.coerce.date(),\n endedAt: z.coerce.date().optional().nullable(),\n segmentType: timeEntrySegmentTypeSchema.optional().default('work'),\n})\n\nexport const staffTimeEntrySegmentUpdateSchema = z.object({\n ...scopedUpdateFields,\n startedAt: z.coerce.date().optional(),\n endedAt: z.coerce.date().optional().nullable(),\n segmentType: timeEntrySegmentTypeSchema.optional(),\n})\n\nexport const staffTimeProjectCreateSchema = z.object({\n ...scopedCreateFields,\n name: z.string().min(1).max(255),\n customerId: z.string().uuid().optional().nullable(),\n code: projectCodeSchema,\n description: z.string().max(2000).optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: projectColorSchema.optional().nullable(),\n status: timeProjectStatusSchema.optional().default('active'),\n ownerUserId: z.string().uuid().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n startDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectUpdateSchema = z.object({\n ...scopedUpdateFields,\n name: z.string().min(1).max(255).optional(),\n customerId: z.string().uuid().optional().nullable(),\n code: projectCodeSchema.optional(),\n description: z.string().max(2000).optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: projectColorSchema.optional().nullable(),\n status: timeProjectStatusSchema.optional(),\n ownerUserId: z.string().uuid().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n startDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectMemberAssignSchema = z.object({\n ...scopedCreateFields,\n timeProjectId: z.string().uuid(),\n staffMemberId: z.string().uuid(),\n role: z.string().max(100).optional().nullable(),\n status: timeProjectMemberStatusSchema.optional().default('active'),\n assignedStartDate: z.coerce.date(),\n assignedEndDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectMemberUpdateSchema = z.object({\n ...scopedUpdateFields,\n role: z.string().max(100).optional().nullable(),\n status: timeProjectMemberStatusSchema.optional(),\n assignedEndDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffMyProjectVisibilityUpdateSchema = z.object({\n showInGrid: z.boolean(),\n})\n\nexport type StaffTimeEntryCreateInput = z.infer<typeof staffTimeEntryCreateSchema>\nexport type StaffTimeEntryUpdateInput = z.infer<typeof staffTimeEntryUpdateSchema>\nexport type StaffTimeEntryBulkSaveInput = z.infer<typeof staffTimeEntryBulkSaveSchema>\nexport type StaffTimeEntrySegmentCreateInput = z.infer<typeof staffTimeEntrySegmentCreateSchema>\nexport type StaffTimeEntrySegmentUpdateInput = z.infer<typeof staffTimeEntrySegmentUpdateSchema>\nexport type StaffTimeProjectCreateInput = z.infer<typeof staffTimeProjectCreateSchema>\nexport type StaffTimeProjectUpdateInput = z.infer<typeof staffTimeProjectUpdateSchema>\nexport type StaffTimeProjectMemberAssignInput = z.infer<typeof staffTimeProjectMemberAssignSchema>\nexport type StaffTimeProjectMemberUpdateInput = z.infer<typeof staffTimeProjectMemberUpdateSchema>\nexport type StaffMyProjectVisibilityUpdateInput = z.infer<typeof staffMyProjectVisibilityUpdateSchema>\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { PROJECT_COLOR_KEYS } from '../lib/timesheets-ui/colors'\n\nconst projectColorSchema = z\n .string()\n .refine(\n (value) => (PROJECT_COLOR_KEYS as readonly string[]).includes(value),\n { message: 'Invalid project color key.' },\n )\n\nconst tagsSchema = z.array(z.string().min(1)).optional().default([])\n\nexport const optimisticUpdatedAtSchema = z.string().refine(\n (value) => !Number.isNaN(new Date(value).getTime()),\n { message: 'Invalid datetime' },\n)\n\nconst scopedCreateFields = {\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n}\n\nconst scopedUpdateFields = {\n id: z.string().uuid(),\n}\n\nexport const staffTeamCreateSchema = z.object({\n ...scopedCreateFields,\n name: z.string().min(1),\n description: z.string().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamUpdateSchema = z.object({\n ...scopedUpdateFields,\n name: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamRoleCreateSchema = z.object({\n ...scopedCreateFields,\n teamId: z.string().uuid().optional().nullable(),\n name: z.string().min(1),\n description: z.string().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamRoleUpdateSchema = z.object({\n ...scopedUpdateFields,\n teamId: z.string().uuid().optional().nullable(),\n name: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberCreateSchema = z.object({\n ...scopedCreateFields,\n teamId: z.string().uuid().optional().nullable(),\n displayName: z.string().min(1),\n description: z.string().optional().nullable(),\n userId: z.string().uuid().optional().nullable(),\n roleIds: z.array(z.string().uuid()).optional().default([]),\n tags: tagsSchema,\n availabilityRuleSetId: z.string().uuid().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamMemberUpdateSchema = z.object({\n ...scopedUpdateFields,\n teamId: z.string().uuid().optional().nullable(),\n displayName: z.string().min(1).optional(),\n description: z.string().optional().nullable(),\n userId: z.string().uuid().optional().nullable(),\n roleIds: z.array(z.string().uuid()).optional(),\n tags: z.array(z.string().min(1)).optional(),\n availabilityRuleSetId: z.string().uuid().optional().nullable(),\n isActive: z.boolean().optional(),\n})\n\nexport const staffTeamMemberActivityCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n occurredAt: z.coerce.date().optional(),\n authorUserId: z.string().uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberActivityUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberActivityCreateSchema.partial())\n\nexport const staffTeamMemberJobHistoryCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n name: z.string().min(1).max(200),\n companyName: z.string().max(200).optional().nullable(),\n description: z.string().max(2000).optional().nullable(),\n startDate: z.coerce.date(),\n endDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTeamMemberJobHistoryUpdateSchema = z\n .object({\n id: z.string().uuid(),\n updatedAt: optimisticUpdatedAtSchema.optional(),\n })\n .merge(staffTeamMemberJobHistoryCreateSchema.partial())\n\nexport const staffTeamMemberCommentCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n body: z.string().min(1).max(8000),\n authorUserId: z.string().uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const staffTeamMemberCommentUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberCommentCreateSchema.partial())\n\nexport const staffTeamMemberAddressCreateSchema = z.object({\n ...scopedCreateFields,\n entityId: z.string().uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce.number().optional(),\n longitude: z.coerce.number().optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const staffTeamMemberAddressUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(staffTeamMemberAddressCreateSchema.partial())\n\nexport const staffTeamMemberTagAssignmentSchema = z.object({\n ...scopedCreateFields,\n memberId: z.string().uuid(),\n tag: z.string().min(1),\n})\n\nconst staffLeaveRequestStatusSchema = z.enum(['pending', 'approved', 'rejected'])\n\nconst validateStaffLeaveRequestDateRange = (\n value: { startDate?: Date; endDate?: Date },\n ctx: z.RefinementCtx,\n) => {\n if (!value.startDate || !value.endDate) return\n if (value.endDate < value.startDate) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'End date must be after start date.',\n path: ['endDate'],\n })\n }\n}\n\nexport const staffLeaveRequestCreateSchema = z\n .object({\n ...scopedCreateFields,\n memberId: z.string().uuid(),\n timezone: z.string().min(1),\n startDate: z.coerce.date(),\n endDate: z.coerce.date(),\n unavailabilityReasonEntryId: z.string().uuid().optional().nullable(),\n unavailabilityReasonValue: z.string().trim().min(1).max(150).optional().nullable(),\n note: z.string().max(2000).optional().nullable(),\n submittedByUserId: z.string().uuid().optional().nullable(),\n })\n .superRefine(validateStaffLeaveRequestDateRange)\n\nexport const staffLeaveRequestUpdateSchema = z\n .object({\n ...scopedUpdateFields,\n timezone: z.string().min(1).optional(),\n memberId: z.string().uuid().optional(),\n startDate: z.coerce.date().optional(),\n endDate: z.coerce.date().optional(),\n unavailabilityReasonEntryId: z.string().uuid().optional().nullable(),\n unavailabilityReasonValue: z.string().trim().min(1).max(150).optional().nullable(),\n note: z.string().max(2000).optional().nullable(),\n })\n .superRefine(validateStaffLeaveRequestDateRange)\n\nexport const staffLeaveRequestDecisionSchema = z.object({\n id: z.string().uuid(),\n decisionComment: z.string().max(2000).optional().nullable(),\n decidedByUserId: z.string().uuid().optional().nullable(),\n})\n\nexport const staffTeamMemberSelfCreateSchema = z.object({\n ...scopedCreateFields,\n displayName: z.string().min(1),\n description: z.string().max(2000).optional().nullable(),\n})\n\nexport type StaffTeamCreateInput = z.infer<typeof staffTeamCreateSchema>\nexport type StaffTeamUpdateInput = z.infer<typeof staffTeamUpdateSchema>\nexport type StaffTeamRoleCreateInput = z.infer<typeof staffTeamRoleCreateSchema>\nexport type StaffTeamRoleUpdateInput = z.infer<typeof staffTeamRoleUpdateSchema>\nexport type StaffTeamMemberCreateInput = z.infer<typeof staffTeamMemberCreateSchema>\nexport type StaffTeamMemberUpdateInput = z.infer<typeof staffTeamMemberUpdateSchema>\nexport type StaffTeamMemberTagAssignmentInput = z.infer<typeof staffTeamMemberTagAssignmentSchema>\nexport type StaffTeamMemberActivityCreateInput = z.infer<typeof staffTeamMemberActivityCreateSchema>\nexport type StaffTeamMemberActivityUpdateInput = z.infer<typeof staffTeamMemberActivityUpdateSchema>\nexport type StaffTeamMemberJobHistoryCreateInput = z.infer<typeof staffTeamMemberJobHistoryCreateSchema>\nexport type StaffTeamMemberJobHistoryUpdateInput = z.infer<typeof staffTeamMemberJobHistoryUpdateSchema>\nexport type StaffTeamMemberCommentCreateInput = z.infer<typeof staffTeamMemberCommentCreateSchema>\nexport type StaffTeamMemberCommentUpdateInput = z.infer<typeof staffTeamMemberCommentUpdateSchema>\nexport type StaffTeamMemberAddressCreateInput = z.infer<typeof staffTeamMemberAddressCreateSchema>\nexport type StaffTeamMemberAddressUpdateInput = z.infer<typeof staffTeamMemberAddressUpdateSchema>\nexport type StaffLeaveRequestStatus = z.infer<typeof staffLeaveRequestStatusSchema>\nexport type StaffLeaveRequestCreateInput = z.infer<typeof staffLeaveRequestCreateSchema>\nexport type StaffLeaveRequestUpdateInput = z.infer<typeof staffLeaveRequestUpdateSchema>\nexport type StaffLeaveRequestDecisionInput = z.infer<typeof staffLeaveRequestDecisionSchema>\nexport type StaffTeamMemberSelfCreateInput = z.infer<typeof staffTeamMemberSelfCreateSchema>\n\n// --- Timesheets validators (Phase 1) ---\n\nconst timeEntrySourceSchema = z.enum(['manual', 'timer', 'kiosk', 'mobile'])\nconst timeProjectStatusSchema = z.enum(['active', 'on_hold', 'completed'])\nconst timeProjectMemberStatusSchema = z.enum(['active', 'inactive'])\nconst timeEntrySegmentTypeSchema = z.enum(['work', 'break'])\nconst projectCodeSchema = z.string().min(1).max(50).regex(/^[a-zA-Z0-9-]+$/)\n\nexport const staffTimeEntryCreateSchema = z.object({\n ...scopedCreateFields,\n staffMemberId: z.string().uuid(),\n date: z.coerce.date(),\n durationMinutes: z.number().int().min(0).max(1440),\n startedAt: z.coerce.date().optional().nullable(),\n endedAt: z.coerce.date().optional().nullable(),\n timeProjectId: z.string().uuid().optional().nullable(),\n customerId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n orderId: z.string().uuid().optional().nullable(),\n notes: z.string().max(2000).optional().nullable(),\n source: timeEntrySourceSchema.optional().default('manual'),\n})\n\nexport const staffTimeEntryUpdateSchema = z.object({\n ...scopedUpdateFields,\n date: z.coerce.date().optional(),\n durationMinutes: z.number().int().min(0).max(1440).optional(),\n timeProjectId: z.string().uuid().optional().nullable(),\n customerId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n orderId: z.string().uuid().optional().nullable(),\n notes: z.string().max(2000).optional().nullable(),\n})\n\nexport const staffTimeEntryStartTimerSchema = z.object({\n ...scopedCreateFields,\n staffMemberId: z.string().uuid(),\n date: z.coerce.date(),\n timeProjectId: z.string().uuid().optional().nullable(),\n notes: z.string().max(2000).optional().nullable(),\n})\n\nexport const staffTimeEntryBulkItemSchema = z.object({\n id: z.string().uuid().optional().nullable(),\n date: z.coerce.date(),\n timeProjectId: z.string().uuid(),\n durationMinutes: z.number().int().min(0).max(1440),\n notes: z.string().max(2000).optional().nullable(),\n})\n\nexport const staffTimeEntryBulkSaveSchema = z.object({\n entries: z.array(staffTimeEntryBulkItemSchema).min(1).max(200),\n})\n\nexport const staffTimeEntrySegmentCreateSchema = z.object({\n ...scopedCreateFields,\n timeEntryId: z.string().uuid(),\n startedAt: z.coerce.date(),\n endedAt: z.coerce.date().optional().nullable(),\n segmentType: timeEntrySegmentTypeSchema.optional().default('work'),\n})\n\nexport const staffTimeEntrySegmentUpdateSchema = z.object({\n ...scopedUpdateFields,\n startedAt: z.coerce.date().optional(),\n endedAt: z.coerce.date().optional().nullable(),\n segmentType: timeEntrySegmentTypeSchema.optional(),\n})\n\nexport const staffTimeProjectCreateSchema = z.object({\n ...scopedCreateFields,\n name: z.string().min(1).max(255),\n customerId: z.string().uuid().optional().nullable(),\n code: projectCodeSchema,\n description: z.string().max(2000).optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: projectColorSchema.optional().nullable(),\n status: timeProjectStatusSchema.optional().default('active'),\n ownerUserId: z.string().uuid().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n startDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectUpdateSchema = z.object({\n ...scopedUpdateFields,\n name: z.string().min(1).max(255).optional(),\n customerId: z.string().uuid().optional().nullable(),\n code: projectCodeSchema.optional(),\n description: z.string().max(2000).optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: projectColorSchema.optional().nullable(),\n status: timeProjectStatusSchema.optional(),\n ownerUserId: z.string().uuid().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n startDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectMemberAssignSchema = z.object({\n ...scopedCreateFields,\n timeProjectId: z.string().uuid(),\n staffMemberId: z.string().uuid(),\n role: z.string().max(100).optional().nullable(),\n status: timeProjectMemberStatusSchema.optional().default('active'),\n assignedStartDate: z.coerce.date(),\n assignedEndDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffTimeProjectMemberUpdateSchema = z.object({\n ...scopedUpdateFields,\n role: z.string().max(100).optional().nullable(),\n status: timeProjectMemberStatusSchema.optional(),\n assignedEndDate: z.coerce.date().optional().nullable(),\n})\n\nexport const staffMyProjectVisibilityUpdateSchema = z.object({\n showInGrid: z.boolean(),\n})\n\nexport type StaffTimeEntryCreateInput = z.infer<typeof staffTimeEntryCreateSchema>\nexport type StaffTimeEntryUpdateInput = z.infer<typeof staffTimeEntryUpdateSchema>\nexport type StaffTimeEntryStartTimerInput = z.infer<typeof staffTimeEntryStartTimerSchema>\nexport type StaffTimeEntryBulkSaveInput = z.infer<typeof staffTimeEntryBulkSaveSchema>\nexport type StaffTimeEntrySegmentCreateInput = z.infer<typeof staffTimeEntrySegmentCreateSchema>\nexport type StaffTimeEntrySegmentUpdateInput = z.infer<typeof staffTimeEntrySegmentUpdateSchema>\nexport type StaffTimeProjectCreateInput = z.infer<typeof staffTimeProjectCreateSchema>\nexport type StaffTimeProjectUpdateInput = z.infer<typeof staffTimeProjectUpdateSchema>\nexport type StaffTimeProjectMemberAssignInput = z.infer<typeof staffTimeProjectMemberAssignSchema>\nexport type StaffTimeProjectMemberUpdateInput = z.infer<typeof staffTimeProjectMemberUpdateSchema>\nexport type StaffMyProjectVisibilityUpdateInput = z.infer<typeof staffMyProjectVisibilityUpdateSchema>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,6 +8,7 @@ import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
|
8
8
|
import { apiCall, apiCallOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
9
9
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
10
10
|
import { ProjectColorDot } from "./ProjectColorDot.js";
|
|
11
|
+
import { startTimerEntry } from "./startTimer.js";
|
|
11
12
|
function formatElapsed(seconds) {
|
|
12
13
|
const h = Math.floor(seconds / 3600);
|
|
13
14
|
const m = Math.floor(seconds % 3600 / 60);
|
|
@@ -101,28 +102,13 @@ function TimerBar({ projects, staffMemberId, onTimerStopped }) {
|
|
|
101
102
|
setIsStarting(true);
|
|
102
103
|
try {
|
|
103
104
|
const today = getToday();
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
timeProjectId: selectedProjectId,
|
|
112
|
-
date: today,
|
|
113
|
-
durationMinutes: 0,
|
|
114
|
-
source: "timer",
|
|
115
|
-
notes: description || null
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
);
|
|
119
|
-
const created = createResponse.result;
|
|
120
|
-
const entryId = created?.id;
|
|
121
|
-
await apiCallOrThrow(
|
|
122
|
-
`/api/staff/timesheets/time-entries/${entryId}/timer-start`,
|
|
123
|
-
{ method: "POST" }
|
|
124
|
-
);
|
|
125
|
-
setActiveEntryId(entryId ?? null);
|
|
105
|
+
const { id: entryId } = await startTimerEntry({
|
|
106
|
+
staffMemberId,
|
|
107
|
+
timeProjectId: selectedProjectId,
|
|
108
|
+
date: today,
|
|
109
|
+
notes: description || null
|
|
110
|
+
});
|
|
111
|
+
setActiveEntryId(entryId);
|
|
126
112
|
setActiveProjectId(selectedProjectId);
|
|
127
113
|
startElapsedCounter((/* @__PURE__ */ new Date()).toISOString());
|
|
128
114
|
} catch {
|