diff --git a/VOL.Business/IServices/School/IS_ClassService.cs b/VOL.Business/IServices/School/IS_ClassService.cs index a9a88be..3d6b279 100644 --- a/VOL.Business/IServices/School/IS_ClassService.cs +++ b/VOL.Business/IServices/School/IS_ClassService.cs @@ -57,6 +57,11 @@ namespace VOL.Business.IServices.School /// Task ModifyClass(ModifyClassParam paramDto); + /// + /// 删除没有学生的班级 + /// + Task DeleteClass(int classId); + /// /// 班级数据统计 /// diff --git a/VOL.Business/Services/School/S_ClassService.cs b/VOL.Business/Services/School/S_ClassService.cs index de4f9e9..c847db5 100644 --- a/VOL.Business/Services/School/S_ClassService.cs +++ b/VOL.Business/Services/School/S_ClassService.cs @@ -3,6 +3,7 @@ using Castle.DynamicProxy.Generators; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; +using System.Data; using VOL.Business.IServices.Norm; using VOL.Business.IServices.School; using VOL.Core.CacheManager; @@ -384,6 +385,44 @@ namespace VOL.Business.Services.School } } + /// + /// 删除空班级,同时清理班级与老师的关联 + /// + public async Task DeleteClass(int classId) + { + if (classId <= 0) + throw new ArgumentException("班级参数无效"); + + var tenantId = UserContext.Current.TenantId; + await using var transaction = await _classRepository.DbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); + + var classModel = await _classRepository.DbContext.Set() + .FirstOrDefaultAsync(x => x.Id == classId && x.SchoolCode == tenantId); + if (classModel == null) + throw new Exception("班级不存在或无权删除,请刷新列表后重试"); + + var hasStudents = await _classRepository.DbContext.Set() + .AnyAsync(x => x.ClassId == classId); + if (hasStudents) + return false; + + var teacherAssociations = await _classRepository.DbContext.Set() + .Where(x => x.ClassId == classId) + .ToListAsync(); + _classRepository.DbContext.RemoveRange(teacherAssociations); + _classRepository.DbContext.Remove(classModel); + await _classRepository.SaveChangesAsync(); + await transaction.CommitAsync(); + + await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam + { + EventType = EventType.Delete.GetDisplayName(), + DataType = IOTDataSyncType.Class.GetDisplayName(), + Json = JsonConvert.SerializeObject(classModel) + }); + return true; + } + /// /// 添加班级 /// @@ -902,4 +941,4 @@ namespace VOL.Business.Services.School return result; } } -} \ No newline at end of file +} diff --git a/VOL.Business/Services/School/S_StudentService.cs b/VOL.Business/Services/School/S_StudentService.cs index 94f4e7f..3cef4d4 100644 --- a/VOL.Business/Services/School/S_StudentService.cs +++ b/VOL.Business/Services/School/S_StudentService.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; using System; using System.Collections.Generic; +using System.Data; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; @@ -443,27 +444,25 @@ namespace VOL.Business.Services.School if (studentIds.Count == 0) throw new ArgumentException("请至少选择一名学生"); + await using var transaction = await _studentRepository.DbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); + + var activeBatchIds = await _studentRepository.DbContext.Set() + .Where(x => x.SchoolCode == UserContext.Current.TenantId && x.Status == 1) + .Select(x => x.Id) + .ToListAsync(); + var promotionDetails = await _studentRepository.DbContext.Set() + .Where(x => activeBatchIds.Contains(x.BatchId) && studentIds.Contains(x.StudentId)) + .ToListAsync(); var students = await _studentRepository.FindAsIQueryable(x => x.SchoolCode == UserContext.Current.TenantId && studentIds.Contains(x.Id)) .ToListAsync(); if (students.Count != studentIds.Count) throw new Exception("部分学生不存在或不属于当前学校,请刷新列表后重新选择"); - var activeBatchId = await _studentRepository.DbContext.Set() - .Where(x => x.SchoolCode == UserContext.Current.TenantId && x.Status == 1) - .OrderByDescending(x => x.Id) - .Select(x => (int?)x.Id) - .FirstOrDefaultAsync(); - if (activeBatchId.HasValue) - { - var promotionStudentCount = await _studentRepository.DbContext.Set() - .CountAsync(x => x.BatchId == activeBatchId.Value && studentIds.Contains(x.StudentId)); - if (promotionStudentCount > 0) - throw new Exception($"所选学生中有{promotionStudentCount}人属于当前可撤回的升学记录,请先撤回升学后再删除"); - } - + _studentRepository.DbContext.RemoveRange(promotionDetails); _studentRepository.DbContext.RemoveRange(students); await _studentRepository.SaveChangesAsync(); + await transaction.CommitAsync(); await _iotDataSyncService.DataSyncCallBack(new DataSyncCallBackParam { @@ -1789,6 +1788,8 @@ namespace VOL.Business.Services.School public async Task UndoPromotion() { var school = await GetPromotionSchool(); + await using (var transaction = await _studentRepository.DbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable)) + { var batch = await _studentRepository.DbContext.Set() .Where(x => x.SchoolCode == school.SchoolCode) .OrderByDescending(x => x.Id) @@ -1832,58 +1833,56 @@ namespace VOL.Business.Services.School throw new Exception($"升学后已有{changedTeacherCount}条教师班级关系被修改,无法自动撤回"); var now = DateTime.Now; - using (var transaction = await _studentRepository.DbContext.Database.BeginTransactionAsync()) + try { - try + foreach (var detail in details) { - foreach (var detail in details) - { - var student = studentById[detail.StudentId]; - student.ClassId = detail.OriginalClassId; - student.ClassName = detail.OriginalClassName; - student.StudentStatus = detail.OriginalStatus; - student.Age = detail.OriginalAge; - student.Modifier = UserContext.Current.UserId; - student.ModifyDate = now; - } - - foreach (var snapshot in teacherSnapshots) - { - if (snapshot.TargetClassId > 0) - { - var association = currentTeacherAssociationById[snapshot.AssociationId]; - association.ClassId = snapshot.OriginalClassId; - association.Modifier = snapshot.Modifier; - association.ModifyDate = snapshot.ModifyDate; - _studentRepository.DbContext.Set().Update(association); - } - else - { - await _studentRepository.DbContext.Set().AddAsync(new S_ClassAssocTeacher - { - ClassId = snapshot.OriginalClassId, - TeacherId = snapshot.TeacherId, - Creator = snapshot.Creator, - CreateDate = snapshot.CreateDate, - Modifier = snapshot.Modifier, - ModifyDate = snapshot.ModifyDate - }); - } - } - - batch.Status = 2; - batch.RevokeOperatorId = UserContext.Current.UserId; - batch.RevokeDate = now; - _studentRepository.UpdateRange(students); - _studentRepository.DbContext.Set().Update(batch); - await _studentRepository.SaveChangesAsync(); - await transaction.CommitAsync(); + var student = studentById[detail.StudentId]; + student.ClassId = detail.OriginalClassId; + student.ClassName = detail.OriginalClassName; + student.StudentStatus = detail.OriginalStatus; + student.Age = detail.OriginalAge; + student.Modifier = UserContext.Current.UserId; + student.ModifyDate = now; } - catch + + foreach (var snapshot in teacherSnapshots) { - await transaction.RollbackAsync(); - throw; + if (snapshot.TargetClassId > 0) + { + var association = currentTeacherAssociationById[snapshot.AssociationId]; + association.ClassId = snapshot.OriginalClassId; + association.Modifier = snapshot.Modifier; + association.ModifyDate = snapshot.ModifyDate; + _studentRepository.DbContext.Set().Update(association); + } + else + { + await _studentRepository.DbContext.Set().AddAsync(new S_ClassAssocTeacher + { + ClassId = snapshot.OriginalClassId, + TeacherId = snapshot.TeacherId, + Creator = snapshot.Creator, + CreateDate = snapshot.CreateDate, + Modifier = snapshot.Modifier, + ModifyDate = snapshot.ModifyDate + }); + } } + + batch.Status = 2; + batch.RevokeOperatorId = UserContext.Current.UserId; + batch.RevokeDate = now; + _studentRepository.UpdateRange(students); + _studentRepository.DbContext.Set().Update(batch); + await _studentRepository.SaveChangesAsync(); + await transaction.CommitAsync(); + } + catch + { + await transaction.RollbackAsync(); + throw; + } } return await GetPromotionStatus(); diff --git a/VOL.WebApi/Controllers/Business/ClassController.cs b/VOL.WebApi/Controllers/Business/ClassController.cs index 3113a5c..79e9ed1 100644 --- a/VOL.WebApi/Controllers/Business/ClassController.cs +++ b/VOL.WebApi/Controllers/Business/ClassController.cs @@ -101,6 +101,24 @@ namespace VOL.WebApi.Controllers.Business return Ok("更新成功"); } + /// + /// 删除空班级 + /// + [HttpPost(nameof(DeleteClass))] + public async Task DeleteClass([FromQuery] int classId) + { + if (!await _classService.DeleteClass(classId)) + { + return new JsonResult(new WebResponseContent + { + Code = 409, + Status = false, + Message = "班级内还有学生,请先删除学生后再删除班级" + }); + } + return Ok("删除成功"); + } + /// /// 班级列表导出 ///