R59 A1-A6:极简考勤打卡
- 新增 AttendanceRecord 与 AttendancePolicy 模型 - 上下班打卡、今日状态、月度统计端点 - 考勤管理页面(我的/团队/设置三 Tab) - 移动端快速打卡入口 - 管理员补卡与审计日志 - 单测覆盖打卡幂等、迟到计算、工时计算、权限边界
这个提交包含在:
@@ -289,6 +289,13 @@ const DEFAULT_FEATURE_FLAGS = [
|
||||
department_ids: [],
|
||||
note: "bootstrap default: force_off",
|
||||
},
|
||||
{
|
||||
flag_key: "attendance_v1",
|
||||
override_mode: "force_off",
|
||||
rollout_type: "global",
|
||||
department_ids: [],
|
||||
note: "bootstrap default: force_off",
|
||||
},
|
||||
{
|
||||
flag_key: "weekly_report_v1",
|
||||
override_mode: "force_off",
|
||||
@@ -552,6 +559,45 @@ async function seedFeatureFlags(prisma) {
|
||||
}
|
||||
}
|
||||
|
||||
async function seedAttendancePolicy(prisma) {
|
||||
const now = new Date();
|
||||
const current = await prisma.attendancePolicy.findFirst({
|
||||
orderBy: { created_at: "asc" },
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
if (current) {
|
||||
await prisma.attendancePolicy.update({
|
||||
where: { id: current.id },
|
||||
data: {
|
||||
work_start_time: "09:00",
|
||||
work_end_time: "18:00",
|
||||
lunch_start_time: "12:00",
|
||||
lunch_end_time: "13:00",
|
||||
late_tolerance_minutes: 0,
|
||||
enabled: true,
|
||||
updated_at: now,
|
||||
updated_by: null,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await prisma.attendancePolicy.create({
|
||||
data: {
|
||||
work_start_time: "09:00",
|
||||
work_end_time: "18:00",
|
||||
lunch_start_time: "12:00",
|
||||
lunch_end_time: "13:00",
|
||||
late_tolerance_minutes: 0,
|
||||
enabled: true,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
updated_by: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function seedBudgetControlRules(prisma) {
|
||||
const now = new Date();
|
||||
|
||||
@@ -794,6 +840,7 @@ async function main() {
|
||||
await seedWorkflowDefinition(prisma);
|
||||
await seedLeaveTypes(prisma);
|
||||
await seedFeatureFlags(prisma);
|
||||
await seedAttendancePolicy(prisma);
|
||||
await seedBudgetControlRules(prisma);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -818,6 +865,8 @@ async function main() {
|
||||
console.log(`- leave types: ${DEFAULT_LEAVE_TYPES.length} seeded with default policies`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`- feature flags: ${DEFAULT_FEATURE_FLAGS.length} seeded`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("- attendance policy: default 09:00-18:00 seeded");
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
await pool.end();
|
||||
|
||||
在新工单中引用
屏蔽一个用户