273 lines
11 KiB
C#
273 lines
11 KiB
C#
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<PageResult<HbjyListItemDto>> GetPagedAsync(int pageIndex, int pageSize, DateTime? date, long? deptId);
|
|
Task<HbjyEditDto> GetEditAsync(long lsjlId);
|
|
Task SaveAsync(HbjySaveDto dto);
|
|
}
|
|
|
|
public class HbjyService : IHbjyService
|
|
{
|
|
private readonly IRepository<LsjlRecord> _lsjlRepo;
|
|
private readonly IRepository<HbjyLsjl> _hbjyLsjlRepo;
|
|
private readonly IRepository<HbjyRecord> _hbjyRecordRepo;
|
|
private readonly IRepository<SysDept.Department> _deptRepo;
|
|
private readonly IRepository<CraftZhuangKou> _zkRepo;
|
|
private readonly IMediator _mediator;
|
|
|
|
public HbjyService(
|
|
IRepository<LsjlRecord> lsjlRepo,
|
|
IRepository<HbjyLsjl> hbjyLsjlRepo,
|
|
IRepository<HbjyRecord> hbjyRecordRepo,
|
|
IRepository<SysDept.Department> deptRepo,
|
|
IRepository<CraftZhuangKou> zkRepo,
|
|
IMediator mediator)
|
|
{
|
|
_lsjlRepo = lsjlRepo;
|
|
_hbjyLsjlRepo = hbjyLsjlRepo;
|
|
_hbjyRecordRepo = hbjyRecordRepo;
|
|
_deptRepo = deptRepo;
|
|
_zkRepo = zkRepo;
|
|
_mediator = mediator;
|
|
}
|
|
|
|
public async Task<PageResult<HbjyListItemDto>> 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<HbjyListItemDto>
|
|
{
|
|
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<HbjyEditDto> 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<HbjyRecordDto> items;
|
|
if (records.Count > 0)
|
|
{
|
|
items = records.OrderBy(r => r.Chetaihao).Select(ToDto).ToList();
|
|
}
|
|
else
|
|
{
|
|
items = new List<HbjyRecordDto>();
|
|
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<HbjyRecordDto> 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)
|
|
};
|
|
}
|
|
}
|