Files
gongxue-base/apps/server/src/entities/ding-attendance-raw.entity.ts
wangziqi f50301148d fix(correctness): 并发/事务/实体/时区/状态一致性修复
由 OCR(open-codereview.ai,deepseek-v4-flash)审查驱动修复:
- wallets 原子扣款防 double-spend;refund 条件更新幂等;findTransactions 分页
- financial/imports/occupancies/attendance 事务与 advisory lock;重复生成/提交幂等
- 矛盾校验器、日期区间、实体双映射/DECIMAL/nullable、时区统一(china-time)
- rbac-seed 防重激活、exam 权限恢复、状态一致性、路由顺序、N+1/IN 分块等性能项

Reviewed-by: OCR (open-codereview.ai)
2026-08-09 21:29:54 +08:00

75 lines
2.0 KiB
TypeScript

import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
ManyToOne,
JoinColumn,
Index,
} from 'typeorm';
import { Student } from './student.entity';
@Entity('ding_attendance_raw')
@Index(['attendanceDate'])
@Index(['matchStatus'])
export class DingAttendanceRaw {
@PrimaryGeneratedColumn()
id: number;
@Column({ name: 'ding_user_id', length: 100 })
dingUserId: string;
@Column({ name: 'user_name', length: 100 })
userName: string;
@Column({ name: 'attendance_date', type: 'date' })
attendanceDate: string;
@Column({ name: 'ding_id', length: 100, unique: true })
dingId: string;
@Column({ name: 'check_in_time', type: 'datetime', nullable: true })
checkInTime: Date;
@Column({ name: 'check_out_time', type: 'datetime', nullable: true })
checkOutTime: Date;
@Column({ name: 'attendance_type', length: 20 })
attendanceType: string;
@Column({ name: 'time_result', length: 20 })
timeResult: string;
@Column({ name: 'location_result', length: 20, nullable: true })
locationResult: string;
@Column({ name: 'punch_source', type: 'varchar', length: 40, nullable: true })
punchSource: string | null;
@Column({ name: 'punch_device_name', type: 'varchar', length: 100, nullable: true })
punchDeviceName: string | null;
@Column({ name: 'punch_device_id', type: 'varchar', length: 100, nullable: true })
punchDeviceId: string | null;
@Column({ name: 'match_status', length: 20, default: 'unmatched' })
matchStatus: string;
@Column({ name: 'matched_student_id', type: 'integer', nullable: true })
matchedStudentId: number | null;
@ManyToOne(() => Student, { onDelete: 'SET NULL', nullable: true })
@JoinColumn({ name: 'matched_student_id' })
matchedStudent: Student | null;
@Column({ name: 'raw_data', type: 'text', nullable: true })
rawData: string;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
}