Files
yanpeng200212 1f1b184411 新增工资/仓储/生产日报等模块,移除旧考勤模块
- 新增 PayRoll(工资)、Wms(仓储)、Prod(车速/缫丝/考勤/丝片检测/丝片台账/纤检日报/质量日报) 模块
- 新增对应 Domain 实体、Application DTO/Service、Api Controller 与前端页面
- 移除旧 Attendance 考勤模块(Controller/Service/Entity/DTO 及 5 个前端页面),由 Prod/Kaoqin 取代
- 调整路由、仪表盘、Lsjl 流丝记录实体与服务
- 更新业务种子数据与 DbSeeder
- 补充工作进度文档 14-27
2026-10-27 09:09:57 +08:00

497 lines
23 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
/// <summary>
/// 选剥茧(对应 F9 生产-选剥茧 XBJ):选茧日报(含盈亏/联统率)、选茧计划及其明细、选茧班组及职工。
/// </summary>
public interface IXjrbService
{
// ---- 选茧日报 ----
Task<PageResult<XjrbListDto>> GetPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize);
Task<XjrbSaveDto> GetByIdAsync(long id);
Task<long> SaveAsync(XjrbSaveDto dto);
Task DeleteAsync(long id);
Task<XjrbYingkuiDto> CountYingkuiAsync(XjrbSaveDto dto);
// ---- 选茧计划 ----
Task<PageResult<XjrbPlanListDto>> GetPlanPagedAsync(DateTime? start, DateTime? end, string like, int pageIndex, int pageSize);
Task<XjrbPlanSaveDto> GetPlanByIdAsync(long id);
Task<long> SavePlanAsync(XjrbPlanSaveDto dto);
Task DeletePlanAsync(long id);
// ---- 选茧计划明细 ----
Task<List<XjrbItemDto>> GetPlanItemsAsync(long planId);
Task<long> SavePlanItemAsync(XjrbItemSaveDto dto);
Task DeletePlanItemAsync(long id);
Task<XjrbYingkuiDto> CountPlanYingkuiAsync(XjrbItemSaveDto dto);
// ---- 选茧班组 ----
Task<PageResult<XjpbBanzuDto>> GetBanzuPagedAsync(string banci, int? zu, int pageIndex, int pageSize);
Task<List<XjpbBanzuZhigongDto>> GetBanzuZhigongAsync(long banzuId);
Task SaveBanzuZhigongAsync(List<XjpbBanzuZhigongSaveDto> dtos);
}
public class XjrbService : IXjrbService
{
private readonly IRepository<XjrbRecord> _xjrbRepo;
private readonly IRepository<XjrbPlan> _planRepo;
private readonly IRepository<XjrbItem> _itemRepo;
private readonly IRepository<XjpbBanzu> _banzuRepo;
private readonly IRepository<XjpbBanzuZhigong> _zgRepo;
private readonly IRepository<CraftZhuangKou> _gyzkRepo;
public XjrbService(
IRepository<XjrbRecord> xjrbRepo, IRepository<XjrbPlan> planRepo, IRepository<XjrbItem> itemRepo,
IRepository<XjpbBanzu> banzuRepo, IRepository<XjpbBanzuZhigong> zgRepo, IRepository<CraftZhuangKou> 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<Dictionary<long, string>> GyzkDictAsync()
=> (await _gyzkRepo.GetAllAsync()).ToDictionary(x => x.Id, x => x.ZhuangKouName);
// ==================== 选茧日报 ====================
public async Task<PageResult<XjrbListDto>> 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<XjrbListDto>
{
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<XjrbSaveDto> 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<long> 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);
}
/// <summary>
/// 计算盈亏 / 联统率(对齐 F9 GetXjrbCountYingkuiQuery + GetXjrbLingruStartDateQuery)。
/// 起始日期:由近及远跳过「联统率 = 0(未结算)」的日报,直到碰到已结算的一条为止;
/// 累计区间 = [起始日期, 当前日期];累加当前录入值 + 区间内历史日报(排除自身)。
/// 联统率 = 累计联统茧重量 ÷ 累计干茧领入重量 × 100;盈亏 = 累计选出总重量 − 累计干茧领入重量。
/// </summary>
public async Task<XjrbYingkuiDto> 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<PageResult<XjrbPlanListDto>> 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<XjrbPlanListDto>
{
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<XjrbPlanSaveDto> 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<long> 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<List<XjrbItemDto>> 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<long> 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);
}
/// <summary>
/// 计划维度盈亏(对齐 F9 GetXjrbPlanYingkuiQuery,口径与日报不同):
/// 联统率按「包数」:联统茧包数 ÷ 各类茧包数之和 × 100;盈亏 = 累计选出总重量 − 计划原料领入重量。
/// 注:老系统仓储里 wjjBaoshu / wjjZhongliang 源字段交叉写反(疑似 bug),此处已按正确字段聚合。
/// </summary>
public async Task<XjrbYingkuiDto> 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<PageResult<XjpbBanzuDto>> 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<XjpbBanzuDto>
{
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<List<XjpbBanzuZhigongDto>> GetBanzuZhigongAsync(long banzuId)
{
if (banzuId <= 0) return new List<XjpbBanzuZhigongDto>();
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();
}
/// <summary>
/// 班组「编辑录入」批量保存(对齐 F9 XjpbBanzuZhigong_SaveCommand):
/// 按班次整体覆盖——先清该班次旧职工与班组,再把「已勾选且有组别」的职工写入,并重建班组。
/// </summary>
public async Task SaveBanzuZhigongAsync(List<XjpbBanzuZhigongSaveDto> dtos)
{
var list = dtos ?? new List<XjpbBanzuZhigongSaveDto>();
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<int, long>();
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
});
}
}
}