using F9WebAiTest.Application.Common; using F9WebAiTest.Application.Dtos; using F9WebAiTest.Application.Dtos.Prod; using F9WebAiTest.Application.Services.Notice; using F9WebAiTest.Domain.Common; using F9WebAiTest.Domain.Entities; using F9WebAiTest.Domain.Entities.Base; using F9WebAiTest.Domain.Entities.Notice; using F9WebAiTest.Domain.Entities.Prod; using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments; using MediatR; namespace F9WebAiTest.Application.Services.Prod; public interface IHbjyService { Task> GetPagedAsync(int pageIndex, int pageSize, DateTime? date, long? deptId); Task GetEditAsync(long lsjlId); Task SaveAsync(HbjySaveDto dto); } public class HbjyService : IHbjyService { private readonly IRepository _lsjlRepo; private readonly IRepository _hbjyLsjlRepo; private readonly IRepository _hbjyRecordRepo; private readonly IRepository _deptRepo; private readonly IRepository _zkRepo; private readonly IMediator _mediator; public HbjyService( IRepository lsjlRepo, IRepository hbjyLsjlRepo, IRepository hbjyRecordRepo, IRepository deptRepo, IRepository zkRepo, IMediator mediator) { _lsjlRepo = lsjlRepo; _hbjyLsjlRepo = hbjyLsjlRepo; _hbjyRecordRepo = hbjyRecordRepo; _deptRepo = deptRepo; _zkRepo = zkRepo; _mediator = mediator; } public async Task> GetPagedAsync(int pageIndex, int pageSize, DateTime? date, long? deptId) { var lsjls = await _lsjlRepo.GetAllAsync(); var q = lsjls.AsQueryable(); if (date.HasValue) q = q.Where(x => x.WorkDate.Date == date.Value.Date); if (deptId.HasValue) q = q.Where(x => x.DeptId == deptId.Value); var depts = await _deptRepo.GetAllAsync(); var deptDict = depts.ToDictionary(d => d.Id, d => d.Name); var zks = await _zkRepo.GetAllAsync(); var zkDict = zks.ToDictionary(z => z.Id, z => z.ZhuangKouName); var sums = (await _hbjyLsjlRepo.GetAllAsync()).ToDictionary(h => h.LsjlId); var total = q.LongCount(); var items = q.OrderByDescending(x => x.WorkDate).ThenByDescending(x => x.Id) .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); return new PageResult { Items = items.Select(x => { sums.TryGetValue(x.Id, out var sum); return new HbjyListItemDto { LsjlId = x.Id, WorkDate = x.WorkDate, DeptId = x.DeptId, DeptName = deptDict.GetValueOrDefault(x.DeptId, ""), Jizu = x.Jizu, Huishu = x.Huishu, Guige = x.Guige, ZhuangKouName = zkDict.GetValueOrDefault(x.GyzkId, ""), Yanse = x.Yanse, Isbanche = x.Isbanche, IsbancheName = x.Isbanche ? "半车" : "整车", LuosiTime = x.LuosiTime, Chetaishu = x.Chetaishu, ChetaiStart = x.ChetaiStart, ChetaiEnd = x.ChetaiEnd, YingluPianshu = x.Chetaishu * 20, IsChecked = sum != null, Pianshu = sum?.Pianshu ?? 0, Qingjie = sum?.Qingjie ?? 0, Jiejing = sum?.Jiejing ?? 0, Dengji = sum?.Dengji ?? "" }; }).ToList(), Total = total, PageIndex = pageIndex, PageSize = pageSize }; } public async Task GetEditAsync(long lsjlId) { var lsjl = await _lsjlRepo.GetByIdAsync(lsjlId); if (lsjl == null) throw new ServiceException("落丝记录不存在", 404); var dept = await _deptRepo.GetByIdAsync(lsjl.DeptId); var zk = await _zkRepo.GetByIdAsync(lsjl.GyzkId); var sum = await _hbjyLsjlRepo.FirstOrDefaultAsync(h => h.LsjlId == lsjlId); var records = await _hbjyRecordRepo.FindAsync(h => h.LsjlId == lsjlId); List items; if (records.Count > 0) { items = records.OrderBy(r => r.Chetaihao).Select(ToDto).ToList(); } else { items = new List(); for (int i = lsjl.ChetaiStart; i <= lsjl.ChetaiEnd; i++) { items.Add(new HbjyRecordDto { Chetaihao = i }); } } return new HbjyEditDto { LsjlId = lsjl.Id, DeptName = dept?.Name ?? "", Jizu = lsjl.Jizu, Huishu = lsjl.Huishu, ZhuangKouName = zk?.ZhuangKouName ?? "", Yanse = lsjl.Yanse, Isbanche = lsjl.Isbanche, IsbancheName = lsjl.Isbanche ? "半车" : "整车", Guige = lsjl.Guige, ChetaiStart = lsjl.ChetaiStart, ChetaiEnd = lsjl.ChetaiEnd, Chetaishu = lsjl.Chetaishu, YingluPianshu = lsjl.Chetaishu * 20, Dengji = sum?.Dengji ?? "", Records = items }; } public async Task SaveAsync(HbjySaveDto dto) { if (dto.LsjlId == 0) throw new ServiceException("落丝记录无效"); var lsjl = await _lsjlRepo.GetByIdAsync(dto.LsjlId); if (lsjl == null) throw new ServiceException("落丝记录不存在", 404); if (dto.Records == null || dto.Records.Count == 0) throw new ServiceException("请先录入检验数据"); var invalid = dto.Records.Where(i => i.Chetaihao < lsjl.ChetaiStart || i.Chetaihao > lsjl.ChetaiEnd).ToList(); if (invalid.Count > 0) throw new ServiceException($"车台号超出范围 [{lsjl.ChetaiStart}-{lsjl.ChetaiEnd}]"); // 计算每车台片数 foreach (var item in dto.Records) { item.Pianshu = CalcPianshu(item); } var totalPianshu = dto.Records.Sum(x => x.Pianshu); if (totalPianshu == 0) throw new ServiceException("请至少录入一个洁净等级片数"); // 物理删除旧明细 var oldRecords = await _hbjyRecordRepo.FindAsync(h => h.LsjlId == dto.LsjlId); await _hbjyRecordRepo.HardDeleteRangeAsync(oldRecords); foreach (var item in dto.Records) { await _hbjyRecordRepo.AddAsync(new HbjyRecord { LsjlId = dto.LsjlId, Chetaihao = item.Chetaihao, YdYidu = item.YdYidu, YdErdu = item.YdErdu, YdSandu = item.YdSandu, Jj100 = item.Jj100, Jj95 = item.Jj95, Jj90 = item.Jj90, Jj85 = item.Jj85, Jj80 = item.Jj80, Jj75 = item.Jj75, Jj70 = item.Jj70, Jj65 = item.Jj65, Jj60 = item.Jj60, QjZycdTdc = item.QjZycdTdc, QjCycdFs = item.QjCycdFs, QjCycdDc = item.QjCycdDc, QjCycdNfc = item.QjCycdNfc, QjCycdDcj = item.QjCycdDcj, QjCycdZlx = item.QjCycdZlx, QjPtcdXc = item.QjPtcdXc, QjPtcdCj = item.QjPtcdCj, QjPtcdLx = item.QjPtcdLx, QjPtcdHjls = item.QjPtcdHjls, Pianshu = item.Pianshu }); } // 汇总 var sum = CalcSummary(dto.Records); var hbjyLsjl = await _hbjyLsjlRepo.FirstOrDefaultAsync(h => h.LsjlId == dto.LsjlId); if (hbjyLsjl == null) { hbjyLsjl = new HbjyLsjl { LsjlId = dto.LsjlId }; await _hbjyLsjlRepo.AddAsync(hbjyLsjl); } hbjyLsjl.Pianshu = sum.Pianshu; hbjyLsjl.Qingjie = sum.Qingjie; hbjyLsjl.Jiejing = sum.Jiejing; hbjyLsjl.YdErdu = sum.YdErdu; hbjyLsjl.YdSandu = sum.YdSandu; hbjyLsjl.Dengji = dto.Dengji ?? ""; await _hbjyLsjlRepo.UpdateAsync(hbjyLsjl); // 业务系统触发消息:发现特大糙时,通过 MediatR 创建"发现特大糙"消息,由 BackgroundService 投递 var tdcCount = dto.Records.Sum(x => x.QjZycdTdc); if (tdcCount > 0) { await _mediator.Send(new CreateNotificationCommand { NotificationTypeCode = "TdcFound", BusinessType = "Hbjy", BusinessId = dto.LsjlId.ToString(), Title = $"发现特大糙:{lsjl.Guige} 规格", Content = $"落丝记录(机组 {lsjl.Jizu}、回数 {lsjl.Huishu})黑板检验发现 {tdcCount} 个特大糙,请关注。", Priority = NotificationPriority.Urgent, CreatorId = 0, CreatorName = "系统" }); } } // ==================== 计算逻辑 ==================== private static HbjyRecordDto ToDto(HbjyRecord r) => new() { Chetaihao = r.Chetaihao, YdYidu = r.YdYidu, YdErdu = r.YdErdu, YdSandu = r.YdSandu, Jj100 = r.Jj100, Jj95 = r.Jj95, Jj90 = r.Jj90, Jj85 = r.Jj85, Jj80 = r.Jj80, Jj75 = r.Jj75, Jj70 = r.Jj70, Jj65 = r.Jj65, Jj60 = r.Jj60, QjZycdTdc = r.QjZycdTdc, QjCycdFs = r.QjCycdFs, QjCycdDc = r.QjCycdDc, QjCycdNfc = r.QjCycdNfc, QjCycdDcj = r.QjCycdDcj, QjCycdZlx = r.QjCycdZlx, QjPtcdXc = r.QjPtcdXc, QjPtcdCj = r.QjPtcdCj, QjPtcdLx = r.QjPtcdLx, QjPtcdHjls = r.QjPtcdHjls, Pianshu = r.Pianshu }; // 片数 = 洁净等级各列之和 private static int CalcPianshu(HbjyRecordDto item) => item.Jj100 + item.Jj95 + item.Jj90 + item.Jj85 + item.Jj80 + item.Jj75 + item.Jj70 + item.Jj65 + item.Jj60; // 清洁扣分(特大类1分/个,大类0.4分/个,小类0.1分/个) private static decimal CalcQingjieDeduction(HbjyRecordDto item) { decimal teda = item.QjZycdTdc * 1.0M; decimal dalei = (item.QjCycdFs + item.QjCycdDc + item.QjCycdNfc + item.QjCycdDcj + item.QjCycdZlx) * 0.4M; decimal xiaolei = (item.QjPtcdXc + item.QjPtcdCj + item.QjPtcdLx + item.QjPtcdHjls) * 0.1M; return teda + dalei + xiaolei; } private static HbjyLsjl CalcSummary(List items) { int pianshu = items.Sum(x => x.Pianshu); // 清洁分 = (片数 - 总扣分) * 100 / 片数 decimal totalDeduction = items.Sum(CalcQingjieDeduction); double qingjie = pianshu == 0 ? 0 : Math.Round((double)((pianshu - totalDeduction) * 100 / pianshu), 2, MidpointRounding.AwayFromZero); // 洁净分 = (片数*100 - 扣分总和*5) / 片数 int jj95 = items.Sum(x => x.Jj95), jj90 = items.Sum(x => x.Jj90), jj85 = items.Sum(x => x.Jj85); int jj80 = items.Sum(x => x.Jj80), jj75 = items.Sum(x => x.Jj75), jj70 = items.Sum(x => x.Jj70); int jj65 = items.Sum(x => x.Jj65), jj60 = items.Sum(x => x.Jj60); decimal totalJiejingDeduction = 1 * jj95 + 2 * jj90 + 3 * jj85 + 4 * jj80 + 5 * jj75 + 6 * jj70 + 7 * jj65 + 8 * jj60; double jiejing = pianshu == 0 ? 0 : Math.Round((double)((pianshu * 100 - totalJiejingDeduction * 5) / (decimal)pianshu), 2, MidpointRounding.AwayFromZero); return new HbjyLsjl { Pianshu = pianshu, Qingjie = qingjie, Jiejing = jiejing, YdErdu = items.Sum(x => x.YdErdu), YdSandu = items.Sum(x => x.YdSandu) }; } }