feat: 拆分学号/身份证字段 + 考勤教师展示 + 代码优化

- 入住导入模板:学号和身份证号拆为独立字段,前后端对齐
- 排课查询关联教师,考勤归档页展示教师姓名
- 抽查时段增加 IsIn 校验
- 抽取 withPessimisticWriteLock 去重悲观锁查询
- import 增加文件空 buffer 校验
- 测试 mock 补全,适配事务 manager
- MySQL init.sql VALUES() 语法兼容修复
This commit is contained in:
2026-07-20 11:54:01 +08:00
parent 375c7ec60b
commit c7ba2799b9
12 changed files with 772 additions and 365 deletions

View File

@@ -5,7 +5,7 @@ import {
} from './occupancy-import-template';
describe('occupancy import template', () => {
it('includes the current occupancy fields including bed and locker numbers', () => {
it('includes the current occupancy fields including separate student and ID numbers', () => {
const workbook = createOccupancyImportTemplateWorkbook();
const ws = workbook.getWorksheet('入住名单导入模板')!;
const headers = ws.getRow(1).values as unknown[];
@@ -18,11 +18,14 @@ describe('occupancy import template', () => {
'柜子号',
'计费起始日',
'电话',
'学号',
'身份证号',
'入住类型',
'备注',
]),
);
expect(headers).not.toContain('所属机构');
expect(headers).not.toContain('学号/身份证');
expect(ws.columnCount).toBe(OCCUPANCY_IMPORT_COLUMNS.length);
});
@@ -32,6 +35,7 @@ describe('occupancy import template', () => {
const instructions = helpWs.getColumn(1).values.join('\n');
expect(instructions).toContain('按手机号关联已有学生');
expect(instructions).toContain('学号和身份证号为两个独立字段');
expect(instructions).toContain('所属机构自动取学生档案');
expect(instructions).toContain('导入时自动收押金');
expect(instructions).toContain('历史入住不会自动收取');
@@ -40,9 +44,9 @@ describe('occupancy import template', () => {
it('keeps Excel Date cells on the same local calendar day', () => {
const workbook = createOccupancyImportTemplateWorkbook();
const ws = workbook.getWorksheet('入住名单导入模板')!;
ws.getCell('J2').value = new Date(2026, 3, 21);
ws.getCell('K2').value = new Date(2026, 3, 22);
ws.getCell('L2').value = new Date(2026, 3, 30);
ws.getCell('K2').value = new Date(2026, 3, 21);
ws.getCell('L2').value = new Date(2026, 3, 22);
ws.getCell('M2').value = new Date(2026, 3, 30);
expect(parseOccupancyImportWorksheet(ws)[0]).toMatchObject({
checkInDate: '2026-04-21',
@@ -62,6 +66,8 @@ describe('occupancy import template', () => {
bedNumber: '1号床',
lockerNumber: 'A01',
name: '张三',
studentNo: '2024001',
idNumber: '11010120060101001X',
checkInDate: '2026-04-21',
billingStartDate: '2026-04-21',
stayType: 'short',
@@ -69,6 +75,8 @@ describe('occupancy import template', () => {
expect(rows[1]).toMatchObject({
bedNumber: '2号床',
lockerNumber: 'A02',
studentNo: '2024002',
idNumber: '11010120060202002X',
stayType: 'long',
});
});