using F9WebAiTest.Application.Common;
using F9WebAiTest.Application.Dtos.Prod;
using F9WebAiTest.Domain.Common;
using F9WebAiTest.Domain.Entities.Base;
using F9WebAiTest.Domain.Entities.Prod;
namespace F9WebAiTest.Application.Services.Prod;
///
/// 选剥茧(对应 F9 生产-选剥茧 XBJ):选茧日报(含盈亏/联统率)、选茧计划及其明细、选茧班组及职工。
///
public interface IXjrbService
{
// ---- 选茧日报 ----
Task> GetPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize);
Task GetByIdAsync(long id);
Task SaveAsync(XjrbSaveDto dto);
Task DeleteAsync(long id);
Task CountYingkuiAsync(XjrbSaveDto dto);
// ---- 选茧计划 ----
Task> GetPlanPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize);
Task GetPlanByIdAsync(long id);
Task SavePlanAsync(XjrbPlanSaveDto dto);
Task DeletePlanAsync(long id);
// ---- 选茧计划明细 ----
Task> GetPlanItemsAsync(long planId);
Task SavePlanItemAsync(XjrbItemSaveDto dto);
Task DeletePlanItemAsync(long id);
Task CountPlanYingkuiAsync(XjrbItemSaveDto dto);
// ---- 选茧班组 ----
Task> GetBanzuPagedAsync(string banci, int? zu, int pageIndex, int pageSize);
Task> GetBanzuZhigongAsync(long banzuId);
Task SaveBanzuZhigongAsync(List dtos);
}
public class XjrbService : IXjrbService
{
private readonly IRepository _xjrbRepo;
private readonly IRepository _planRepo;
private readonly IRepository _itemRepo;
private readonly IRepository _banzuRepo;
private readonly IRepository _zgRepo;
private readonly IRepository _gyzkRepo;
public XjrbService(
IRepository xjrbRepo, IRepository planRepo, IRepository itemRepo,
IRepository banzuRepo, IRepository zgRepo, IRepository gyzkRepo)
{
_xjrbRepo = xjrbRepo; _planRepo = planRepo; _itemRepo = itemRepo;
_banzuRepo = banzuRepo; _zgRepo = zgRepo; _gyzkRepo = gyzkRepo;
}
private static decimal Round2(decimal v) => Math.Round(v, 2);
private async Task> GyzkDictAsync()
=> (await _gyzkRepo.GetAllAsync()).ToDictionary(x => x.Id, x => x.ZhuangKouName);
// ==================== 选茧日报 ====================
public async Task> GetPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize)
{
var all = await _xjrbRepo.GetAllAsync();
var q = all.AsQueryable();
if (start.HasValue) q = q.Where(x => x.Date.Date >= start.Value.Date);
if (end.HasValue) q = q.Where(x => x.Date.Date <= end.Value.Date);
var gyzkDict = await GyzkDictAsync();
if (!string.IsNullOrWhiteSpace(like))
{
var key = like.Trim();
q = q.Where(x => x.GyzkId > 0 && gyzkDict.ContainsKey(x.GyzkId) && gyzkDict[x.GyzkId].Contains(key));
}
var total = q.LongCount();
var items = q.OrderByDescending(x => x.Date).ThenByDescending(x => x.Id)
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult
{
Items = items.Select(ToDto).ToList(),
Total = total, PageIndex = pageIndex, PageSize = pageSize
};
}
private static XjrbListDto ToDto(XjrbRecord x) => new()
{
Id = x.Id, Date = x.Date, GyzkId = x.GyzkId,
YlLrBaoshu = x.YlLrBaoshu, YlLrZhongliang = x.YlLrZhongliang,
LtjBaoshu = x.LtjBaoshu, LtjZhongliang = x.LtjZhongliang,
HwjjBaoshu = x.HwjjBaoshu, HwjjZhongliang = x.HwjjZhongliang,
LjjBaoshu = x.LjjBaoshu, LjjZhongliang = x.LjjZhongliang,
MjBaoshu = x.MjBaoshu, MjZhongliang = x.MjZhongliang,
SgjBaoshu = x.SgjBaoshu, SgjZhongliang = x.SgjZhongliang,
XjjBaoshu = x.XjjBaoshu, XjjZhongliang = x.XjjZhongliang,
JyBaoshu = x.JyBaoshu, JyZhongliang = x.JyZhongliang,
JhBaoshu = x.JhBaoshu, JhZhongliang = x.JhZhongliang,
TotalZhongliang = x.TotalZhongliang,
ThBaoshu = x.ThBaoshu, ThZhongliang = x.ThZhongliang,
LiantongRate = x.LiantongRate, Yingkui = x.Yingkui
};
public async Task GetByIdAsync(long id)
{
var x = await _xjrbRepo.GetByIdAsync(id);
if (x == null) throw new ServiceException("选茧日报不存在", 404);
return new XjrbSaveDto
{
Id = x.Id, Date = x.Date, GyzkId = x.GyzkId,
YlLrBaoshu = x.YlLrBaoshu, YlLrZhongliang = x.YlLrZhongliang,
LtjBaoshu = x.LtjBaoshu, LtjZhongliang = x.LtjZhongliang,
HwjjBaoshu = x.HwjjBaoshu, HwjjZhongliang = x.HwjjZhongliang,
LjjBaoshu = x.LjjBaoshu, LjjZhongliang = x.LjjZhongliang,
MjBaoshu = x.MjBaoshu, MjZhongliang = x.MjZhongliang,
SgjBaoshu = x.SgjBaoshu, SgjZhongliang = x.SgjZhongliang,
XjjBaoshu = x.XjjBaoshu, XjjZhongliang = x.XjjZhongliang,
JyBaoshu = x.JyBaoshu, JyZhongliang = x.JyZhongliang,
JhBaoshu = x.JhBaoshu, JhZhongliang = x.JhZhongliang,
ThBaoshu = x.ThBaoshu, ThZhongliang = x.ThZhongliang,
LiantongRate = x.LiantongRate, Yingkui = x.Yingkui
};
}
public async Task SaveAsync(XjrbSaveDto dto)
{
if (dto.Date == default) throw new ServiceException("请选择选茧日期");
if (dto.GyzkId <= 0) throw new ServiceException("请选择工艺庄口");
XjrbRecord entity;
var isNew = dto.Id == 0;
if (isNew) entity = new XjrbRecord();
else
{
entity = await _xjrbRepo.GetByIdAsync(dto.Id);
if (entity == null) throw new ServiceException("选茧日报不存在", 404);
}
entity.Date = dto.Date.Date;
entity.GyzkId = dto.GyzkId;
entity.YlLrBaoshu = dto.YlLrBaoshu;
entity.YlLrZhongliang = dto.YlLrZhongliang;
entity.LtjBaoshu = dto.LtjBaoshu; entity.LtjZhongliang = dto.LtjZhongliang;
entity.HwjjBaoshu = dto.HwjjBaoshu; entity.HwjjZhongliang = dto.HwjjZhongliang;
entity.LjjBaoshu = dto.LjjBaoshu; entity.LjjZhongliang = dto.LjjZhongliang;
entity.MjBaoshu = dto.MjBaoshu; entity.MjZhongliang = dto.MjZhongliang;
entity.SgjBaoshu = dto.SgjBaoshu; entity.SgjZhongliang = dto.SgjZhongliang;
entity.XjjBaoshu = dto.XjjBaoshu; entity.XjjZhongliang = dto.XjjZhongliang;
entity.JyBaoshu = dto.JyBaoshu; entity.JyZhongliang = dto.JyZhongliang;
entity.JhBaoshu = dto.JhBaoshu; entity.JhZhongliang = dto.JhZhongliang;
entity.ThBaoshu = dto.ThBaoshu; entity.ThZhongliang = dto.ThZhongliang;
entity.LiantongRate = dto.LiantongRate;
entity.Yingkui = dto.Yingkui;
// 合计重量 = 8 类茧重量之和(不含退回、不含领入)
entity.TotalZhongliang = Round2(entity.LtjZhongliang + entity.HwjjZhongliang + entity.LjjZhongliang
+ entity.MjZhongliang + entity.SgjZhongliang + entity.XjjZhongliang + entity.JyZhongliang + entity.JhZhongliang);
if (isNew) await _xjrbRepo.AddAsync(entity); else await _xjrbRepo.UpdateAsync(entity);
return entity.Id;
}
public async Task DeleteAsync(long id)
{
var x = await _xjrbRepo.GetByIdAsync(id);
if (x == null) throw new ServiceException("选茧日报不存在", 404);
await _xjrbRepo.HardDeleteAsync(x);
}
///
/// 计算盈亏 / 联统率(对齐 F9 GetXjrbCountYingkuiQuery + GetXjrbLingruStartDateQuery)。
/// 起始日期:由近及远跳过「联统率 = 0(未结算)」的日报,直到碰到已结算的一条为止;
/// 累计区间 = [起始日期, 当前日期];累加当前录入值 + 区间内历史日报(排除自身)。
/// 联统率 = 累计联统茧重量 ÷ 累计干茧领入重量 × 100;盈亏 = 累计选出总重量 − 累计干茧领入重量。
///
public async Task CountYingkuiAsync(XjrbSaveDto dto)
{
if (dto.GyzkId <= 0) throw new ServiceException("请选择工艺庄口");
var date = dto.Date.Date;
var all = await _xjrbRepo.GetAllAsync();
var history = all.Where(x => x.GyzkId == dto.GyzkId && x.Date.Date < date && x.Id != dto.Id)
.OrderByDescending(x => x.Date).ToList();
// 步骤 1:往回跳过未结算(LiantongRate == 0)的记录,确定起始日期
var startDate = date;
foreach (var item in history)
{
if (item.LiantongRate != 0) break;
startDate = item.Date.Date;
}
// 步骤 2:累计区间(闭区间,排除自身)
var range = history.Where(x => x.Date.Date >= startDate && x.Date.Date <= date).ToList();
// 步骤 3:累加(初始值 = 当前表单输入值)
decimal ltj = dto.LtjZhongliang;
decimal yllr = dto.YlLrZhongliang;
decimal allW = dto.LtjZhongliang + dto.HwjjZhongliang + dto.LjjZhongliang + dto.MjZhongliang
+ dto.SgjZhongliang + dto.XjjZhongliang + dto.JyZhongliang + dto.JhZhongliang;
foreach (var item in range)
{
ltj += item.LtjZhongliang;
yllr += item.YlLrZhongliang;
allW += item.LtjZhongliang + item.HwjjZhongliang + item.LjjZhongliang + item.MjZhongliang
+ item.SgjZhongliang + item.XjjZhongliang + item.JyZhongliang + item.JhZhongliang;
}
// 步骤 4:公式
var rate = yllr != 0 ? Round2(ltj / yllr * 100) : 0;
var yingkui = Round2(allW - yllr);
return new XjrbYingkuiDto { LiantongRate = rate, Yingkui = yingkui, StartDate = startDate };
}
// ==================== 选茧计划 ====================
public async Task> GetPlanPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize)
{
var all = await _planRepo.GetAllAsync();
var q = all.AsQueryable();
if (start.HasValue) q = q.Where(x => x.Date.Date >= start.Value.Date);
if (end.HasValue) q = q.Where(x => x.Date.Date <= end.Value.Date);
var gyzkDict = await GyzkDictAsync();
if (!string.IsNullOrWhiteSpace(like))
{
var key = like.Trim();
q = q.Where(x => x.GyzkId > 0 && gyzkDict.ContainsKey(x.GyzkId) && gyzkDict[x.GyzkId].Contains(key));
}
var total = q.LongCount();
var items = q.OrderByDescending(x => x.Date).ThenByDescending(x => x.Id)
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult
{
Items = items.Select(ToPlanDto).ToList(),
Total = total, PageIndex = pageIndex, PageSize = pageSize
};
}
private static XjrbPlanListDto ToPlanDto(XjrbPlan x) => new()
{
Id = x.Id, Date = x.Date, GyzkId = x.GyzkId, YllingliaodanId = x.YllingliaodanId,
YlBaoshu = x.YlBaoshu, YlZhongliang = x.YlZhongliang,
LtjBaoshu = x.LtjBaoshu, LtjZhongliang = x.LtjZhongliang,
HwjjBaoshu = x.HwjjBaoshu, HwjjZhongliang = x.HwjjZhongliang,
WjjBaoshu = x.WjjBaoshu, WjjZhongliang = x.WjjZhongliang,
SgjBaoshu = x.SgjBaoshu, SgjZhongliang = x.SgjZhongliang,
XjjBaoshu = x.XjjBaoshu, XjjZhongliang = x.XjjZhongliang,
JyBaoshu = x.JyBaoshu, JyZhongliang = x.JyZhongliang,
JhBaoshu = x.JhBaoshu, JhZhongliang = x.JhZhongliang,
TotalZhongliang = x.TotalZhongliang, LiantongRate = x.LiantongRate,
Yingkui = x.Yingkui, IsFinish = x.IsFinish
};
public async Task GetPlanByIdAsync(long id)
{
var x = await _planRepo.GetByIdAsync(id);
if (x == null) throw new ServiceException("选茧计划不存在", 404);
return new XjrbPlanSaveDto
{
Id = x.Id, Date = x.Date, GyzkId = x.GyzkId, YllingliaodanId = x.YllingliaodanId,
YlBaoshu = x.YlBaoshu, YlZhongliang = x.YlZhongliang,
LtjBaoshu = x.LtjBaoshu, LtjZhongliang = x.LtjZhongliang,
HwjjBaoshu = x.HwjjBaoshu, HwjjZhongliang = x.HwjjZhongliang,
WjjBaoshu = x.WjjBaoshu, WjjZhongliang = x.WjjZhongliang,
SgjBaoshu = x.SgjBaoshu, SgjZhongliang = x.SgjZhongliang,
XjjBaoshu = x.XjjBaoshu, XjjZhongliang = x.XjjZhongliang,
JyBaoshu = x.JyBaoshu, JyZhongliang = x.JyZhongliang,
JhBaoshu = x.JhBaoshu, JhZhongliang = x.JhZhongliang
};
}
public async Task SavePlanAsync(XjrbPlanSaveDto dto)
{
if (dto.Date == default) throw new ServiceException("请选择日期");
if (dto.GyzkId <= 0) throw new ServiceException("请选择工艺庄口");
XjrbPlan entity;
var isNew = dto.Id == 0;
if (isNew) entity = new XjrbPlan();
else
{
entity = await _planRepo.GetByIdAsync(dto.Id);
if (entity == null) throw new ServiceException("选茧计划不存在", 404);
if (entity.IsFinish) throw new ServiceException("该计划已选茧完成,不能修改");
}
entity.Date = dto.Date.Date;
entity.GyzkId = dto.GyzkId;
entity.YllingliaodanId = dto.YllingliaodanId;
entity.YlBaoshu = dto.YlBaoshu; entity.YlZhongliang = dto.YlZhongliang;
entity.LtjBaoshu = dto.LtjBaoshu; entity.LtjZhongliang = dto.LtjZhongliang;
entity.HwjjBaoshu = dto.HwjjBaoshu; entity.HwjjZhongliang = dto.HwjjZhongliang;
entity.WjjBaoshu = dto.WjjBaoshu; entity.WjjZhongliang = dto.WjjZhongliang;
entity.SgjBaoshu = dto.SgjBaoshu; entity.SgjZhongliang = dto.SgjZhongliang;
entity.XjjBaoshu = dto.XjjBaoshu; entity.XjjZhongliang = dto.XjjZhongliang;
entity.JyBaoshu = dto.JyBaoshu; entity.JyZhongliang = dto.JyZhongliang;
entity.JhBaoshu = dto.JhBaoshu; entity.JhZhongliang = dto.JhZhongliang;
entity.TotalZhongliang = Round2(entity.LtjZhongliang + entity.HwjjZhongliang + entity.WjjZhongliang
+ entity.SgjZhongliang + entity.XjjZhongliang + entity.JyZhongliang + entity.JhZhongliang);
if (isNew) await _planRepo.AddAsync(entity); else await _planRepo.UpdateAsync(entity);
return entity.Id;
}
public async Task DeletePlanAsync(long id)
{
var x = await _planRepo.GetByIdAsync(id);
if (x == null) throw new ServiceException("选茧计划不存在", 404);
if (x.IsFinish) throw new ServiceException("该计划已选茧完成,不能删除");
var items = await _itemRepo.FindAsync(i => i.XjrbPlanId == id);
if (items.Count > 0) await _itemRepo.HardDeleteRangeAsync(items);
await _planRepo.HardDeleteAsync(x);
}
// ==================== 选茧计划明细 ====================
public async Task> GetPlanItemsAsync(long planId)
{
var items = await _itemRepo.FindAsync(x => x.XjrbPlanId == planId);
return items.OrderBy(x => x.Date).ThenBy(x => x.Id).Select(x => new XjrbItemDto
{
Id = x.Id, XjrbPlanId = x.XjrbPlanId, Date = x.Date,
LtjBaoshu = x.LtjBaoshu, LtjZhongliang = x.LtjZhongliang,
HwjjBaoshu = x.HwjjBaoshu, HwjjZhongliang = x.HwjjZhongliang,
WjjBaoshu = x.WjjBaoshu, WjjZhongliang = x.WjjZhongliang,
SgjBaoshu = x.SgjBaoshu, SgjZhongliang = x.SgjZhongliang,
XjjBaoshu = x.XjjBaoshu, XjjZhongliang = x.XjjZhongliang,
JyBaoshu = x.JyBaoshu, JyZhongliang = x.JyZhongliang,
JhBaoshu = x.JhBaoshu, JhZhongliang = x.JhZhongliang,
TotalZhongliang = x.TotalZhongliang, IsFinish = x.IsFinish
}).ToList();
}
public async Task SavePlanItemAsync(XjrbItemSaveDto dto)
{
if (dto.XjrbPlanId <= 0) throw new ServiceException("计划无效");
if (dto.Date == default) throw new ServiceException("请选择选茧日期");
var plan = await _planRepo.GetByIdAsync(dto.XjrbPlanId);
if (plan == null) throw new ServiceException("选茧计划不存在", 404);
if (plan.IsFinish) throw new ServiceException("该计划已选茧完成,不能修改明细");
XjrbItem entity;
var isNew = dto.Id == 0;
if (isNew) entity = new XjrbItem { XjrbPlanId = dto.XjrbPlanId };
else
{
entity = await _itemRepo.GetByIdAsync(dto.Id);
if (entity == null) throw new ServiceException("选茧明细不存在", 404);
}
entity.Date = dto.Date.Date;
entity.LtjBaoshu = dto.LtjBaoshu; entity.LtjZhongliang = dto.LtjZhongliang;
entity.HwjjBaoshu = dto.HwjjBaoshu; entity.HwjjZhongliang = dto.HwjjZhongliang;
entity.WjjBaoshu = dto.WjjBaoshu; entity.WjjZhongliang = dto.WjjZhongliang;
entity.SgjBaoshu = dto.SgjBaoshu; entity.SgjZhongliang = dto.SgjZhongliang;
entity.XjjBaoshu = dto.XjjBaoshu; entity.XjjZhongliang = dto.XjjZhongliang;
entity.JyBaoshu = dto.JyBaoshu; entity.JyZhongliang = dto.JyZhongliang;
entity.JhBaoshu = dto.JhBaoshu; entity.JhZhongliang = dto.JhZhongliang;
entity.TotalZhongliang = Round2(entity.LtjZhongliang + entity.HwjjZhongliang + entity.WjjZhongliang
+ entity.SgjZhongliang + entity.XjjZhongliang + entity.JyZhongliang + entity.JhZhongliang);
entity.IsFinish = dto.IsFinish;
if (isNew) await _itemRepo.AddAsync(entity); else await _itemRepo.UpdateAsync(entity);
// 勾选「选茧完成」时把盈亏回写计划(对齐 F9 UpdateXjrbPlanYingkuiCommand)
if (dto.IsFinish)
{
var yk = await CountPlanYingkuiAsync(dto);
plan.TotalZhongliang = Round2(plan.TotalZhongliang + entity.TotalZhongliang);
plan.Yingkui = yk.Yingkui;
plan.LiantongRate = yk.LiantongRate;
plan.IsFinish = true;
await _planRepo.UpdateAsync(plan);
}
return entity.Id;
}
public async Task DeletePlanItemAsync(long id)
{
var x = await _itemRepo.GetByIdAsync(id);
if (x == null) throw new ServiceException("选茧明细不存在", 404);
var plan = await _planRepo.GetByIdAsync(x.XjrbPlanId);
if (plan != null && plan.IsFinish) throw new ServiceException("该计划已选茧完成,不能删除明细");
await _itemRepo.HardDeleteAsync(x);
}
///
/// 计划维度盈亏(对齐 F9 GetXjrbPlanYingkuiQuery,口径与日报不同):
/// 联统率按「包数」:联统茧包数 ÷ 各类茧包数之和 × 100;盈亏 = 累计选出总重量 − 计划原料领入重量。
/// 注:老系统仓储里 wjjBaoshu / wjjZhongliang 源字段交叉写反(疑似 bug),此处已按正确字段聚合。
///
public async Task CountPlanYingkuiAsync(XjrbItemSaveDto dto)
{
var plan = await _planRepo.GetByIdAsync(dto.XjrbPlanId);
if (plan == null) throw new ServiceException("选茧计划不存在", 404);
var items = (await _itemRepo.FindAsync(x => x.XjrbPlanId == dto.XjrbPlanId && x.Id != dto.Id)).ToList();
decimal ltjZ = dto.LtjZhongliang, hwjjZ = dto.HwjjZhongliang, wjjZ = dto.WjjZhongliang,
sgjZ = dto.SgjZhongliang, xjjZ = dto.XjjZhongliang, jyZ = dto.JyZhongliang, jhZ = dto.JhZhongliang;
decimal ltjB = dto.LtjBaoshu, hwjjB = dto.HwjjBaoshu, wjjB = dto.WjjBaoshu,
sgjB = dto.SgjBaoshu, xjjB = dto.XjjBaoshu, jyB = dto.JyBaoshu, jhB = dto.JhBaoshu;
foreach (var it in items)
{
ltjZ += it.LtjZhongliang; hwjjZ += it.HwjjZhongliang; wjjZ += it.WjjZhongliang;
sgjZ += it.SgjZhongliang; xjjZ += it.XjjZhongliang; jyZ += it.JyZhongliang; jhZ += it.JhZhongliang;
ltjB += it.LtjBaoshu; hwjjB += it.HwjjBaoshu; wjjB += it.WjjBaoshu;
sgjB += it.SgjBaoshu; xjjB += it.XjjBaoshu; jyB += it.JyBaoshu; jhB += it.JhBaoshu;
}
var totalZhongliang = Round2(ltjZ + hwjjZ + wjjZ + sgjZ + xjjZ + jyZ + jhZ);
var baoshuSum = ltjB + hwjjB + wjjB + sgjB + xjjB + jyB + jhB;
var rate = baoshuSum != 0 ? Round2(ltjB / (decimal)baoshuSum * 100) : 0;
return new XjrbYingkuiDto { LiantongRate = rate, Yingkui = Round2(totalZhongliang - plan.YlZhongliang), StartDate = plan.Date };
}
// ==================== 选茧班组 ====================
public async Task> GetBanzuPagedAsync(string banci, int? zu, int pageIndex, int pageSize)
{
var all = await _banzuRepo.GetAllAsync();
var q = all.AsQueryable();
if (!string.IsNullOrWhiteSpace(banci)) q = q.Where(x => x.Banci == banci);
if (zu.HasValue) q = q.Where(x => x.Zu == zu.Value);
var total = q.LongCount();
var items = q.OrderBy(x => x.Banci).ThenBy(x => x.Zu)
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new PageResult
{
Items = items.Select(x => new XjpbBanzuDto { Id = x.Id, Banci = x.Banci, Zu = x.Zu }).ToList(),
Total = total, PageIndex = pageIndex, PageSize = pageSize
};
}
public async Task> GetBanzuZhigongAsync(long banzuId)
{
if (banzuId <= 0) return new List();
var list = await _zgRepo.FindAsync(x => x.BanzuId == banzuId);
return list.OrderBy(x => x.Sort).ThenBy(x => x.Id).Select(x => new XjpbBanzuZhigongDto
{
Id = x.Id, BanzuId = x.BanzuId, Banci = x.Banci, Zu = x.Zu,
YgId = x.YgId, YgName = x.YgName, YgPhone = x.YgPhone, Sort = x.Sort
}).ToList();
}
///
/// 班组「编辑录入」批量保存(对齐 F9 XjpbBanzuZhigong_SaveCommand):
/// 按班次整体覆盖——先清该班次旧职工与班组,再把「已勾选且有组别」的职工写入,并重建班组。
///
public async Task SaveBanzuZhigongAsync(List dtos)
{
var list = dtos ?? new List();
var banci = list.FirstOrDefault()?.Banci ?? "";
if (string.IsNullOrWhiteSpace(banci)) throw new ServiceException("班次无效");
// 清理该班次旧数据
var oldZg = await _zgRepo.FindAsync(x => x.Banci == banci);
if (oldZg.Count > 0) await _zgRepo.HardDeleteRangeAsync(oldZg);
var oldBanzu = await _banzuRepo.FindAsync(x => x.Banci == banci);
if (oldBanzu.Count > 0) await _banzuRepo.HardDeleteRangeAsync(oldBanzu);
var picked = list.Where(x => x.Selected && x.Zu > 0).ToList();
if (picked.Count == 0) return;
// 重建班组(班次 + 组 去重)
var banzuDict = new Dictionary();
foreach (var zu in picked.Select(x => x.Zu).Distinct().OrderBy(x => x))
{
var banzu = new XjpbBanzu { Banci = banci, Zu = zu };
await _banzuRepo.AddAsync(banzu);
banzuDict[zu] = banzu.Id;
}
var sort = 0;
foreach (var p in picked)
{
await _zgRepo.AddAsync(new XjpbBanzuZhigong
{
BanzuId = banzuDict.TryGetValue(p.Zu, out var bid) ? bid : 0,
Banci = banci, Zu = p.Zu,
YgId = p.YgId, YgName = p.YgName ?? "", YgPhone = p.YgPhone ?? "",
Sort = p.Sort > 0 ? p.Sort : ++sort
});
}
}
}