98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Body,
|
|
Param,
|
|
Query,
|
|
UseGuards,
|
|
Request,
|
|
} from '@nestjs/common';
|
|
import { AttendanceService } from './attendance.service';
|
|
import {
|
|
BatchCreateAttendanceDto,
|
|
AttendanceSummaryQueryDto,
|
|
AttendanceCalendarQueryDto,
|
|
QueryDingRawDto,
|
|
MatchDingRecordDto,
|
|
} from './dto/attendance.dto';
|
|
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
|
import { OperationLogsService } from '../operation-logs/operation-logs.service';
|
|
import { extractRequestInfo } from '../common/request-utils';
|
|
import { RequirePermission } from '../auth/decorators/permission.decorator';
|
|
|
|
@UseGuards(JwtAuthGuard)
|
|
@Controller()
|
|
export class AttendanceController {
|
|
constructor(
|
|
private readonly service: AttendanceService,
|
|
private readonly logService: OperationLogsService,
|
|
) {}
|
|
|
|
// ── Batch create attendance records ──
|
|
@Post('attendance-records/batch')
|
|
@RequirePermission('attendance:create')
|
|
async batchCreate(
|
|
@Body() dto: BatchCreateAttendanceDto,
|
|
@Request() req: any,
|
|
) {
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
const result = await this.service.batchCreate(dto);
|
|
await this.logService.log({
|
|
userId: req.user?.id,
|
|
username: req.user?.username,
|
|
module: '考勤管理',
|
|
action: '批量录入考勤',
|
|
detail: `共 ${result.count} 条`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
|
|
// ── Attendance summary ──
|
|
@Get('attendance-records/summary')
|
|
@RequirePermission('attendance:view')
|
|
getSummary(@Query() query: AttendanceSummaryQueryDto) {
|
|
return this.service.getSummary(query);
|
|
}
|
|
|
|
// ── Attendance calendar ──
|
|
@Get('attendance-records/calendar')
|
|
@RequirePermission('attendance:view')
|
|
getCalendar(@Query() query: AttendanceCalendarQueryDto) {
|
|
return this.service.getCalendar(query);
|
|
}
|
|
|
|
// ── DingAttendance raw records ──
|
|
@Get('ding-attendance-raw')
|
|
@RequirePermission('attendance:view')
|
|
getDingRaw(@Query() query: QueryDingRawDto) {
|
|
return this.service.getDingRaw(query);
|
|
}
|
|
|
|
// ── Match a dingtalk record to a student ──
|
|
@Post('ding-attendance-raw/:id/match')
|
|
@RequirePermission('attendance:edit')
|
|
async matchDingRecord(
|
|
@Param('id') id: string,
|
|
@Body() dto: MatchDingRecordDto,
|
|
@Request() req: any,
|
|
) {
|
|
const { ipAddress, userAgent } = extractRequestInfo(req);
|
|
const result = await this.service.matchDingRecord(+id, dto);
|
|
await this.logService.log({
|
|
userId: req.user?.id,
|
|
username: req.user?.username,
|
|
module: '考勤管理',
|
|
action: '匹配考勤记录',
|
|
targetId: +id,
|
|
targetType: 'dingAttendanceRaw',
|
|
detail: `匹配到学生 ${dto.studentId}`,
|
|
ipAddress,
|
|
userAgent,
|
|
});
|
|
return result;
|
|
}
|
|
}
|