- 新增 PayRoll(工资)、Wms(仓储)、Prod(车速/缫丝/考勤/丝片检测/丝片台账/纤检日报/质量日报) 模块 - 新增对应 Domain 实体、Application DTO/Service、Api Controller 与前端页面 - 移除旧 Attendance 考勤模块(Controller/Service/Entity/DTO 及 5 个前端页面),由 Prod/Kaoqin 取代 - 调整路由、仪表盘、Lsjl 流丝记录实体与服务 - 更新业务种子数据与 DbSeeder - 补充工作进度文档 14-27
610 lines
26 KiB
C#
610 lines
26 KiB
C#
using F9WebAiTest.Application.Common;
|
|
using F9WebAiTest.Application.Dtos.Prod;
|
|
using F9WebAiTest.Domain.Common;
|
|
using F9WebAiTest.Domain.Entities.Base;
|
|
using F9WebAiTest.Domain.Entities.Prod;
|
|
using F9WebAiTest.Domain.Entities.SYS.Registries;
|
|
using F9WebAiTest.Domain.Enums.SYS.Employees;
|
|
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
|
|
|
|
namespace F9WebAiTest.Application.Services.Prod;
|
|
|
|
/// <summary>
|
|
/// 煮茧日报(生产-前缫):某日某车间某庄口某规格一条日报,含「机组」「班次」「机组班次」三层明细。
|
|
/// 对应 F9 Page_Zjrb(列表)、Page_Zjrb_EditV2(录入)、Zjrb_SaveCommand / Zjrb_DelCommand /
|
|
/// CalculateJizuSaosiHoursCommand(计算缫丝时长)。
|
|
///
|
|
/// 计算口径(与 F9 前端 Page_Zjrb_EditV2 一致,服务端保存时重算):
|
|
/// 机组.今缫桶数 = 甲班 + 乙班
|
|
/// 机组.今存桶数 = 上存 + 今缫 − 今落(今落为 0 且余量够一个标准桶时自动补「工艺落丝桶数」)
|
|
/// 班次.今缫重量 = 该班次机组今缫桶数 × 每桶茧量 ÷ 1000
|
|
/// 班次.领入/退回重量 = 包数 × 联统茧标重(标重未配置则保留录入值)
|
|
/// 班次.今缫包数 = 今缫重量 ÷ 联统茧标重(四舍五入取整)
|
|
/// 班次.今存 = 上存 + 领入 − 今缫 − 退回
|
|
/// 主表 = 甲班 + 乙班
|
|
/// </summary>
|
|
public interface IZjrbService
|
|
{
|
|
/// <summary>日报列表(账期起止 + 车间 + 关键字)</summary>
|
|
Task<PageResult<ZjrbReadDto_View>> GetPagedAsync(DateTime dateFrom, DateTime dateTo, long depId,
|
|
string like, int pageIndex, int pageSize);
|
|
|
|
/// <summary>某条日报的机组明细(列表页下半表)</summary>
|
|
Task<List<ZjrbJizuDto>> GetJizuListAsync(long zjrbId);
|
|
|
|
/// <summary>修改回填:主表 + 班次 + 机组 + 机组班次</summary>
|
|
Task<ZjrbSaveDto> GetForEditAsync(long id);
|
|
|
|
/// <summary>新增:按上一日结存带出上存、每桶茧量、工艺落丝桶数,并按机组车台生成机组行</summary>
|
|
Task<ZjrbSaveDto> BuildDefaultsAsync(DateTime date, long depId, long gyzkId, string guige);
|
|
|
|
/// <summary>保存(整条替换:主表 upsert + 三层明细先删后建)</summary>
|
|
Task<long> SaveAsync(ZjrbSaveDto dto);
|
|
|
|
/// <summary>删除(四张表级联物理删除)</summary>
|
|
Task DeleteAsync(long id);
|
|
|
|
/// <summary>计算缫丝时长(整日整车间重算:单班 9 小时 / 双班 18 小时,按茧量比例分配)</summary>
|
|
Task<int> CalculateJizuSaosiHoursAsync(DateTime date, long depId);
|
|
}
|
|
|
|
public class ZjrbService : IZjrbService
|
|
{
|
|
/// <summary>单班 / 双班的机组标准时长</summary>
|
|
private const decimal SingleBanciHours = 9m;
|
|
private const decimal TwoBanciHours = 18m;
|
|
|
|
/// <summary>联统茧标重的参数配置位置(与 F9 一致)</summary>
|
|
private const string RegistryCategory = @"生产\前缫\煮茧";
|
|
private const string RegistryKey = "联统茧标重";
|
|
|
|
private readonly IRepository<ZjrbRecord> _zjrbRepo;
|
|
private readonly IRepository<ZjrbJizu> _jizuRepo;
|
|
private readonly IRepository<ZjrbBanci> _banciRepo;
|
|
private readonly IRepository<ZjrbJizuBanci> _jizuBanciRepo;
|
|
private readonly IRepository<JizuChetai> _jzctRepo;
|
|
private readonly IRepository<ChejianBanci> _cjbcRepo;
|
|
private readonly IRepository<CraftZhuangKou> _gyzkRepo;
|
|
private readonly IRepository<Registry> _registryRepo;
|
|
private readonly IRepository<SysDept.Department> _deptRepo;
|
|
|
|
public ZjrbService(IRepository<ZjrbRecord> zjrbRepo, IRepository<ZjrbJizu> jizuRepo,
|
|
IRepository<ZjrbBanci> banciRepo, IRepository<ZjrbJizuBanci> jizuBanciRepo,
|
|
IRepository<JizuChetai> jzctRepo, IRepository<ChejianBanci> cjbcRepo,
|
|
IRepository<CraftZhuangKou> gyzkRepo, IRepository<Registry> registryRepo,
|
|
IRepository<SysDept.Department> deptRepo)
|
|
{
|
|
_zjrbRepo = zjrbRepo;
|
|
_jizuRepo = jizuRepo;
|
|
_banciRepo = banciRepo;
|
|
_jizuBanciRepo = jizuBanciRepo;
|
|
_jzctRepo = jzctRepo;
|
|
_cjbcRepo = cjbcRepo;
|
|
_gyzkRepo = gyzkRepo;
|
|
_registryRepo = registryRepo;
|
|
_deptRepo = deptRepo;
|
|
}
|
|
|
|
// ==================== 查询 ====================
|
|
|
|
public async Task<PageResult<ZjrbReadDto_View>> GetPagedAsync(DateTime dateFrom, DateTime dateTo, long depId,
|
|
string like, int pageIndex, int pageSize)
|
|
{
|
|
if (pageIndex <= 0) pageIndex = 1;
|
|
if (pageSize <= 0) pageSize = 20;
|
|
|
|
var from = dateFrom.Date;
|
|
var to = dateTo.Date;
|
|
if (to < from) (from, to) = (to, from);
|
|
|
|
var ctx = await BuildContextAsync();
|
|
|
|
var rows = await _zjrbRepo.FindAsync(x => x.Date >= from && x.Date <= to);
|
|
if (depId > 0) rows = rows.Where(x => x.DeptId == depId).ToList();
|
|
|
|
if (!string.IsNullOrWhiteSpace(like))
|
|
{
|
|
var kw = like.Trim();
|
|
rows = rows.Where(x =>
|
|
ctx.GyzkNames.GetValueOrDefault(x.GyzkId, "").Contains(kw, StringComparison.OrdinalIgnoreCase)
|
|
|| (x.Guige ?? "").Contains(kw, StringComparison.OrdinalIgnoreCase))
|
|
.ToList();
|
|
}
|
|
|
|
var total = rows.Count;
|
|
var pageRows = rows
|
|
.OrderByDescending(x => x.Date)
|
|
.ThenBy(x => ctx.DeptNames.GetValueOrDefault(x.DeptId, ""))
|
|
.ThenBy(x => x.GyzkId)
|
|
.ThenBy(x => x.Guige)
|
|
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
|
|
|
var ids = pageRows.Select(x => x.Id).ToList();
|
|
var jizus = ids.Count == 0
|
|
? new List<ZjrbJizu>()
|
|
: await _jizuRepo.FindAsync(x => ids.Contains(x.ZjrbId));
|
|
|
|
var items = pageRows.Select(x =>
|
|
{
|
|
var jz = jizus.Where(j => j.ZjrbId == x.Id).ToList();
|
|
return new ZjrbReadDto_View
|
|
{
|
|
Id = x.Id,
|
|
Date = x.Date,
|
|
DepId = x.DeptId,
|
|
DepName = ctx.DeptNames.GetValueOrDefault(x.DeptId, ""),
|
|
GyzkId = x.GyzkId,
|
|
GyzkName = ctx.GyzkNames.GetValueOrDefault(x.GyzkId, ""),
|
|
Guige = x.Guige ?? "",
|
|
LastDate = x.LastDate,
|
|
StandardLuositongshu = x.StandardLuositongshu,
|
|
MeitongJianliang = x.MeitongJianliang,
|
|
BaoshuShangcun = x.BaoshuShangcun,
|
|
BaoshuLingru = x.BaoshuLingru,
|
|
BaoshuSaosi = x.BaoshuSaosi,
|
|
BaoshuTuihui = x.BaoshuTuihui,
|
|
BaoshuJincun = x.BaoshuJincun,
|
|
JianliangShangcun = x.JianliangShangcun,
|
|
JianliangLingru = x.JianliangLingru,
|
|
JianliangSaosi = x.JianliangSaosi,
|
|
JianliangTuihui = x.JianliangTuihui,
|
|
JianliangJincun = x.JianliangJincun,
|
|
TongshuShangcun = jz.Sum(j => j.TongshuShangcun),
|
|
TongshuJinsao = jz.Sum(j => j.TongshuJinsao),
|
|
TongshuJinluo = jz.Sum(j => j.TongshuJinluo),
|
|
TongshuJincun = jz.Sum(j => j.TongshuJincun),
|
|
JizuSaosiHours = jz.Sum(j => j.JizuSaosiHours)
|
|
};
|
|
}).ToList();
|
|
|
|
return new PageResult<ZjrbReadDto_View>
|
|
{
|
|
Items = items,
|
|
Total = total,
|
|
PageIndex = pageIndex,
|
|
PageSize = pageSize
|
|
};
|
|
}
|
|
|
|
public async Task<List<ZjrbJizuDto>> GetJizuListAsync(long zjrbId)
|
|
{
|
|
var jizus = (await _jizuRepo.FindAsync(x => x.ZjrbId == zjrbId)).OrderBy(x => x.Jizu).ToList();
|
|
var jb = await _jizuBanciRepo.FindAsync(x => x.ZjrbId == zjrbId);
|
|
return jizus.Select(j => ToJizuDto(j, jb)).ToList();
|
|
}
|
|
|
|
public async Task<ZjrbSaveDto> GetForEditAsync(long id)
|
|
{
|
|
var master = await _zjrbRepo.GetByIdAsync(id);
|
|
if (master == null) throw new ServiceException("煮茧日报不存在或已删除");
|
|
|
|
var ctx = await BuildContextAsync();
|
|
var banciRows = (await _banciRepo.FindAsync(x => x.ZjrbId == id)).OrderBy(x => x.Banci).ToList();
|
|
var jizuRows = (await _jizuRepo.FindAsync(x => x.ZjrbId == id)).OrderBy(x => x.Jizu).ToList();
|
|
var jbRows = await _jizuBanciRepo.FindAsync(x => x.ZjrbId == id);
|
|
|
|
var dto = new ZjrbSaveDto
|
|
{
|
|
Id = master.Id,
|
|
Date = master.Date,
|
|
DepId = master.DeptId,
|
|
DepName = ctx.DeptNames.GetValueOrDefault(master.DeptId, ""),
|
|
GyzkId = master.GyzkId,
|
|
GyzkName = ctx.GyzkNames.GetValueOrDefault(master.GyzkId, ""),
|
|
Guige = master.Guige ?? "",
|
|
LastDate = master.LastDate,
|
|
StandardLuositongshu = master.StandardLuositongshu,
|
|
MeitongJianliang = master.MeitongJianliang,
|
|
LiantongBiaozhong = await GetLiantongBiaozhongAsync(),
|
|
BaoshuShangcun = master.BaoshuShangcun,
|
|
BaoshuLingru = master.BaoshuLingru,
|
|
BaoshuSaosi = master.BaoshuSaosi,
|
|
BaoshuTuihui = master.BaoshuTuihui,
|
|
BaoshuJincun = master.BaoshuJincun,
|
|
JianliangShangcun = master.JianliangShangcun,
|
|
JianliangLingru = master.JianliangLingru,
|
|
JianliangSaosi = master.JianliangSaosi,
|
|
JianliangTuihui = master.JianliangTuihui,
|
|
JianliangJincun = master.JianliangJincun,
|
|
Bancis = banciRows.Select(ToBanciDto).ToList(),
|
|
Jizus = jizuRows.Select(j => ToJizuDto(j, jbRows)).ToList()
|
|
};
|
|
|
|
// 历史数据可能缺班次行(或车间班次配置调整过),按配置补齐甲乙班
|
|
var need = (await GetBanciKindsAsync(master.DeptId));
|
|
foreach (var b in need)
|
|
{
|
|
if (dto.Bancis.All(x => x.Banci != b))
|
|
dto.Bancis.Add(new ZjrbBanciDto { Banci = b, BanciName = b.ToString() });
|
|
}
|
|
dto.Bancis = dto.Bancis.OrderBy(x => x.Banci).ToList();
|
|
|
|
return dto;
|
|
}
|
|
|
|
public async Task<ZjrbSaveDto> BuildDefaultsAsync(DateTime date, long depId, long gyzkId, string guige)
|
|
{
|
|
if (depId <= 0) throw new ServiceException("请选择车间");
|
|
|
|
var ctx = await BuildContextAsync();
|
|
var d = date.Date;
|
|
var g = (guige ?? string.Empty).Trim();
|
|
|
|
// 上一日:同车间 + 同庄口(+ 同规格)的最近一条日报
|
|
var candidates = await _zjrbRepo.FindAsync(x => x.Date < d && x.DeptId == depId && x.GyzkId == gyzkId);
|
|
var last = candidates
|
|
.Where(x => string.IsNullOrEmpty(g) || (x.Guige ?? "") == g)
|
|
.OrderByDescending(x => x.Date)
|
|
.FirstOrDefault();
|
|
|
|
var dto = new ZjrbSaveDto
|
|
{
|
|
Date = d,
|
|
DepId = depId,
|
|
DepName = ctx.DeptNames.GetValueOrDefault(depId, ""),
|
|
GyzkId = gyzkId,
|
|
GyzkName = ctx.GyzkNames.GetValueOrDefault(gyzkId, ""),
|
|
Guige = g,
|
|
LiantongBiaozhong = await GetLiantongBiaozhongAsync()
|
|
};
|
|
|
|
List<ZjrbBanci> lastBancis = new();
|
|
List<ZjrbJizu> lastJizus = new();
|
|
if (last != null)
|
|
{
|
|
dto.LastDate = last.Date;
|
|
dto.StandardLuositongshu = last.StandardLuositongshu;
|
|
dto.MeitongJianliang = last.MeitongJianliang;
|
|
lastBancis = await _banciRepo.FindAsync(x => x.ZjrbId == last.Id);
|
|
lastJizus = await _jizuRepo.FindAsync(x => x.ZjrbId == last.Id);
|
|
}
|
|
|
|
// 班次行:按车间班次配置;未配置则固定甲乙两班
|
|
foreach (var b in await GetBanciKindsAsync(depId))
|
|
{
|
|
var prev = lastBancis.FirstOrDefault(x => x.Banci == b);
|
|
dto.Bancis.Add(new ZjrbBanciDto
|
|
{
|
|
Banci = b,
|
|
BanciName = b.ToString(),
|
|
BaoshuShangcun = prev?.BaoshuJincun ?? 0,
|
|
JianliangShangcun = prev?.JianliangJincun ?? 0
|
|
});
|
|
}
|
|
|
|
// 机组行:按机组车台配置;上存桶数取上一日该机组今存桶数
|
|
var jizus = (await _jzctRepo.FindAsync(x => x.DepartmentId == depId))
|
|
.Select(x => x.Jizu).Distinct().OrderBy(x => x).ToList();
|
|
foreach (var jz in jizus)
|
|
{
|
|
var prev = lastJizus.FirstOrDefault(x => x.Jizu == jz);
|
|
dto.Jizus.Add(new ZjrbJizuDto
|
|
{
|
|
Jizu = jz,
|
|
TongshuShangcun = prev?.TongshuJincun ?? 0
|
|
});
|
|
}
|
|
|
|
return dto;
|
|
}
|
|
|
|
// ==================== 保存 / 删除 ====================
|
|
|
|
public async Task<long> SaveAsync(ZjrbSaveDto dto)
|
|
{
|
|
if (dto == null) throw new ServiceException("参数不能为空");
|
|
if (dto.Date == default) throw new ServiceException("请选择日期");
|
|
if (dto.DepId <= 0) throw new ServiceException("请选择车间");
|
|
if (dto.GyzkId <= 0) throw new ServiceException("请选择工艺庄口");
|
|
if (dto.MeitongJianliang <= 0) throw new ServiceException("每桶茧量必须大于 0");
|
|
if (dto.StandardLuositongshu <= 0) throw new ServiceException("工艺落丝桶数必须大于 0");
|
|
if (dto.Bancis == null || dto.Bancis.Count == 0) throw new ServiceException("请至少保留一个班次行");
|
|
|
|
var d = dto.Date.Date;
|
|
var guige = (dto.Guige ?? string.Empty).Trim();
|
|
|
|
// 唯一性:同 日期 + 车间 + 庄口 + 规格
|
|
var exists = await _zjrbRepo.AnyAsync(x =>
|
|
x.Id != dto.Id && x.Date == d && x.DeptId == dto.DepId && x.GyzkId == dto.GyzkId && x.Guige == guige);
|
|
if (exists) throw new ServiceException("已存在相同的煮茧日报!");
|
|
|
|
Normalize(dto, guige);
|
|
|
|
long id = dto.Id;
|
|
if (id > 0)
|
|
{
|
|
var master = await _zjrbRepo.GetByIdAsync(id);
|
|
if (master == null) throw new ServiceException("煮茧日报不存在或已删除");
|
|
CopyMaster(dto, master);
|
|
await _zjrbRepo.UpdateAsync(master);
|
|
await DeleteChildrenAsync(id);
|
|
}
|
|
else
|
|
{
|
|
var master = new ZjrbRecord { LastDate = dto.LastDate };
|
|
CopyMaster(dto, master);
|
|
await _zjrbRepo.AddAsync(master);
|
|
id = master.Id;
|
|
}
|
|
|
|
// 班次
|
|
foreach (var b in dto.Bancis)
|
|
{
|
|
await _banciRepo.AddAsync(new ZjrbBanci
|
|
{
|
|
ZjrbId = id,
|
|
Banci = b.Banci,
|
|
BaoshuShangcun = b.BaoshuShangcun,
|
|
BaoshuLingru = b.BaoshuLingru,
|
|
BaoshuSaosi = b.BaoshuSaosi,
|
|
BaoshuTuihui = b.BaoshuTuihui,
|
|
BaoshuJincun = b.BaoshuJincun,
|
|
JianliangShangcun = b.JianliangShangcun,
|
|
JianliangLingru = b.JianliangLingru,
|
|
JianliangSaosi = b.JianliangSaosi,
|
|
JianliangTuihui = b.JianliangTuihui,
|
|
JianliangJincun = b.JianliangJincun
|
|
});
|
|
}
|
|
|
|
// 机组 + 机组班次(机组班次挂在刚生成的机组 Id 上)
|
|
foreach (var j in dto.Jizus)
|
|
{
|
|
var jizu = await _jizuRepo.AddAsync(new ZjrbJizu
|
|
{
|
|
ZjrbId = id,
|
|
Jizu = j.Jizu,
|
|
JizuSaosiHours = j.JizuSaosiHours,
|
|
TongshuShangcun = j.TongshuShangcun,
|
|
TongshuJinsao = j.TongshuJinsaoJiaban + j.TongshuJinsaoYiban,
|
|
TongshuJinluo = j.TongshuJinluo,
|
|
TongshuJincun = j.TongshuJincun
|
|
});
|
|
|
|
foreach (var b in dto.Bancis)
|
|
{
|
|
await _jizuBanciRepo.AddAsync(new ZjrbJizuBanci
|
|
{
|
|
ZjrbId = id,
|
|
ZjrbJizuId = jizu.Id,
|
|
Jizu = j.Jizu,
|
|
Banci = b.Banci,
|
|
TongshuJinsao = b.Banci == Prod_Banci_Enum.甲 ? j.TongshuJinsaoJiaban : j.TongshuJinsaoYiban
|
|
});
|
|
}
|
|
}
|
|
|
|
await _zjrbRepo.SaveChangesAsync();
|
|
return id;
|
|
}
|
|
|
|
public async Task DeleteAsync(long id)
|
|
{
|
|
var master = await _zjrbRepo.GetByIdAsync(id);
|
|
if (master == null) throw new ServiceException("煮茧日报不存在或已删除");
|
|
await DeleteChildrenAsync(id);
|
|
await _zjrbRepo.HardDeleteAsync(master);
|
|
}
|
|
|
|
private async Task DeleteChildrenAsync(long zjrbId)
|
|
{
|
|
var jizuRows = await _jizuRepo.FindAsync(x => x.ZjrbId == zjrbId);
|
|
if (jizuRows.Count > 0) await _jizuRepo.HardDeleteRangeAsync(jizuRows);
|
|
|
|
var banciRows = await _banciRepo.FindAsync(x => x.ZjrbId == zjrbId);
|
|
if (banciRows.Count > 0) await _banciRepo.HardDeleteRangeAsync(banciRows);
|
|
|
|
var jbRows = await _jizuBanciRepo.FindAsync(x => x.ZjrbId == zjrbId);
|
|
if (jbRows.Count > 0) await _jizuBanciRepo.HardDeleteRangeAsync(jbRows);
|
|
}
|
|
|
|
// ==================== 计算缫丝时长 ====================
|
|
|
|
public async Task<int> CalculateJizuSaosiHoursAsync(DateTime date, long depId)
|
|
{
|
|
if (depId <= 0) throw new ServiceException("请选择车间");
|
|
var d = date.Date;
|
|
|
|
var reports = await _zjrbRepo.FindAsync(x => x.Date == d && x.DeptId == depId);
|
|
if (reports.Count == 0) throw new ServiceException("该日该车间没有煮茧日报,无法计算缫丝时长");
|
|
|
|
var reportMap = reports.ToDictionary(x => x.Id);
|
|
var ids = reportMap.Keys.ToList();
|
|
var jizus = await _jizuRepo.FindAsync(x => ids.Contains(x.ZjrbId));
|
|
if (jizus.Count == 0) throw new ServiceException("该日该车间没有机组明细,无法计算缫丝时长");
|
|
var jbRows = await _jizuBanciRepo.FindAsync(x => ids.Contains(x.ZjrbId));
|
|
|
|
// 双班判据:该机组「今缫桶数 > 0」的班次个数为 2 → 18 小时,否则 9 小时
|
|
var hasTwoBanci = jizus.Select(x => x.Jizu).Distinct().ToDictionary(
|
|
jz => jz,
|
|
jz => jbRows.Where(x => x.Jizu == jz && x.TongshuJinsao > 0)
|
|
.Select(x => x.Banci).Distinct().Count() == 2);
|
|
|
|
// 机组总茧量 = Σ(每桶茧量 × 机组今缫桶数)
|
|
var totalJianliang = jizus.GroupBy(x => x.Jizu).ToDictionary(
|
|
g => g.Key,
|
|
g => g.Sum(x => (decimal)reportMap[x.ZjrbId].MeitongJianliang * x.TongshuJinsao));
|
|
|
|
var changed = 0;
|
|
var groups = jizus.GroupBy(x => new
|
|
{
|
|
reportMap[x.ZjrbId].GyzkId,
|
|
Guige = reportMap[x.ZjrbId].Guige ?? "",
|
|
x.Jizu
|
|
});
|
|
|
|
foreach (var group in groups)
|
|
{
|
|
var jz = group.Key.Jizu;
|
|
var totalHours = hasTwoBanci.GetValueOrDefault(jz) ? TwoBanciHours : SingleBanciHours;
|
|
var jizuTotal = totalJianliang.GetValueOrDefault(jz);
|
|
var current = group.Sum(x => (decimal)reportMap[x.ZjrbId].MeitongJianliang * x.TongshuJinsao);
|
|
var ratio = jizuTotal > 0 ? current / jizuTotal : 0m;
|
|
var newHours = Math.Round(ratio * totalHours, 1, MidpointRounding.AwayFromZero);
|
|
|
|
foreach (var item in group)
|
|
{
|
|
if (item.JizuSaosiHours == newHours) continue;
|
|
item.JizuSaosiHours = newHours;
|
|
await _jizuRepo.UpdateAsync(item);
|
|
changed++;
|
|
}
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
// ==================== 内部:口径重算 / 上下文 ====================
|
|
|
|
/// <summary>按 F9 编辑页口径重算派生字段(机组今存、班次重量与今存、主表合计)</summary>
|
|
private static void Normalize(ZjrbSaveDto dto, string guige)
|
|
{
|
|
dto.Guige = guige;
|
|
|
|
foreach (var j in dto.Jizus)
|
|
{
|
|
if (j.JizuSaosiHours < 0) throw new ServiceException($"机组{j.Jizu}的缫丝时长不能为负数");
|
|
if (j.JizuSaosiHours > 20) throw new ServiceException($"机组{j.Jizu}缫丝时长不能大于 20");
|
|
j.TongshuJinsao = j.TongshuJinsaoJiaban + j.TongshuJinsaoYiban;
|
|
if (j.TongshuJinsao > 0 && j.JizuSaosiHours <= 0)
|
|
throw new ServiceException($"机组{j.Jizu}今缫桶数大于 0 时,请输入缫丝时长");
|
|
|
|
var pre = j.TongshuShangcun + j.TongshuJinsao - j.TongshuJinluo;
|
|
if (j.TongshuJinluo == 0 && dto.StandardLuositongshu > 0 && pre >= dto.StandardLuositongshu)
|
|
{
|
|
j.TongshuJinluo = dto.StandardLuositongshu;
|
|
pre -= dto.StandardLuositongshu;
|
|
}
|
|
j.TongshuJincun = pre;
|
|
}
|
|
|
|
foreach (var b in dto.Bancis)
|
|
{
|
|
if (b.BaoshuShangcun > 0 && b.JianliangShangcun <= 0)
|
|
throw new ServiceException($"{b.Banci}班上存包数大于 0 时,请填写上存重量");
|
|
|
|
var tongshu = dto.Jizus.Sum(j => b.Banci == Prod_Banci_Enum.甲
|
|
? j.TongshuJinsaoJiaban
|
|
: j.TongshuJinsaoYiban);
|
|
|
|
b.JianliangSaosi = Math.Round(tongshu * (decimal)dto.MeitongJianliang / 1000m, 1,
|
|
MidpointRounding.AwayFromZero);
|
|
|
|
if (dto.LiantongBiaozhong > 0)
|
|
{
|
|
b.JianliangLingru = Math.Round(b.BaoshuLingru * dto.LiantongBiaozhong, 1,
|
|
MidpointRounding.AwayFromZero);
|
|
b.JianliangTuihui = Math.Round(b.BaoshuTuihui * dto.LiantongBiaozhong, 1,
|
|
MidpointRounding.AwayFromZero);
|
|
b.BaoshuSaosi = (int)Math.Round(b.JianliangSaosi / dto.LiantongBiaozhong, 0,
|
|
MidpointRounding.AwayFromZero);
|
|
}
|
|
|
|
b.JianliangJincun = b.JianliangShangcun + b.JianliangLingru - b.JianliangSaosi - b.JianliangTuihui;
|
|
b.BaoshuJincun = b.BaoshuShangcun + b.BaoshuLingru - b.BaoshuSaosi - b.BaoshuTuihui;
|
|
}
|
|
|
|
// 主表 = 甲班 + 乙班
|
|
dto.BaoshuShangcun = dto.Bancis.Sum(x => x.BaoshuShangcun);
|
|
dto.BaoshuLingru = dto.Bancis.Sum(x => x.BaoshuLingru);
|
|
dto.BaoshuSaosi = dto.Bancis.Sum(x => x.BaoshuSaosi);
|
|
dto.BaoshuTuihui = dto.Bancis.Sum(x => x.BaoshuTuihui);
|
|
dto.BaoshuJincun = dto.Bancis.Sum(x => x.BaoshuJincun);
|
|
dto.JianliangShangcun = dto.Bancis.Sum(x => x.JianliangShangcun);
|
|
dto.JianliangLingru = dto.Bancis.Sum(x => x.JianliangLingru);
|
|
dto.JianliangSaosi = dto.Bancis.Sum(x => x.JianliangSaosi);
|
|
dto.JianliangTuihui = dto.Bancis.Sum(x => x.JianliangTuihui);
|
|
dto.JianliangJincun = dto.Bancis.Sum(x => x.JianliangJincun);
|
|
}
|
|
|
|
private static void CopyMaster(ZjrbSaveDto dto, ZjrbRecord master)
|
|
{
|
|
master.Date = dto.Date.Date;
|
|
master.DeptId = dto.DepId;
|
|
master.GyzkId = dto.GyzkId;
|
|
master.Guige = dto.Guige ?? "";
|
|
master.LastDate = dto.LastDate;
|
|
master.StandardLuositongshu = dto.StandardLuositongshu;
|
|
master.MeitongJianliang = dto.MeitongJianliang;
|
|
master.BaoshuShangcun = dto.BaoshuShangcun;
|
|
master.BaoshuLingru = dto.BaoshuLingru;
|
|
master.BaoshuSaosi = dto.BaoshuSaosi;
|
|
master.BaoshuTuihui = dto.BaoshuTuihui;
|
|
master.BaoshuJincun = dto.BaoshuJincun;
|
|
master.JianliangShangcun = dto.JianliangShangcun;
|
|
master.JianliangLingru = dto.JianliangLingru;
|
|
master.JianliangSaosi = dto.JianliangSaosi;
|
|
master.JianliangTuihui = dto.JianliangTuihui;
|
|
master.JianliangJincun = dto.JianliangJincun;
|
|
}
|
|
|
|
private static ZjrbBanciDto ToBanciDto(ZjrbBanci x) => new()
|
|
{
|
|
Id = x.Id,
|
|
ZjrbId = x.ZjrbId,
|
|
Banci = x.Banci,
|
|
BanciName = x.Banci.ToString(),
|
|
BaoshuShangcun = x.BaoshuShangcun,
|
|
BaoshuLingru = x.BaoshuLingru,
|
|
BaoshuSaosi = x.BaoshuSaosi,
|
|
BaoshuTuihui = x.BaoshuTuihui,
|
|
BaoshuJincun = x.BaoshuJincun,
|
|
JianliangShangcun = x.JianliangShangcun,
|
|
JianliangLingru = x.JianliangLingru,
|
|
JianliangSaosi = x.JianliangSaosi,
|
|
JianliangTuihui = x.JianliangTuihui,
|
|
JianliangJincun = x.JianliangJincun
|
|
};
|
|
|
|
private static ZjrbJizuDto ToJizuDto(ZjrbJizu x, List<ZjrbJizuBanci> jbRows) => new()
|
|
{
|
|
Id = x.Id,
|
|
ZjrbId = x.ZjrbId,
|
|
Jizu = x.Jizu,
|
|
JizuSaosiHours = x.JizuSaosiHours,
|
|
TongshuShangcun = x.TongshuShangcun,
|
|
TongshuJinsaoJiaban = jbRows.FirstOrDefault(b => b.ZjrbJizuId == x.Id && b.Banci == Prod_Banci_Enum.甲)
|
|
?.TongshuJinsao ?? 0,
|
|
TongshuJinsaoYiban = jbRows.FirstOrDefault(b => b.ZjrbJizuId == x.Id && b.Banci == Prod_Banci_Enum.乙)
|
|
?.TongshuJinsao ?? 0,
|
|
TongshuJinsao = x.TongshuJinsao,
|
|
TongshuJinluo = x.TongshuJinluo,
|
|
TongshuJincun = x.TongshuJincun
|
|
};
|
|
|
|
/// <summary>车间班次配置;未配置时固定甲乙两班</summary>
|
|
private async Task<List<Prod_Banci_Enum>> GetBanciKindsAsync(long depId)
|
|
{
|
|
var cfgs = await _cjbcRepo.FindAsync(x => x.DeptId == depId);
|
|
if (cfgs.Count == 0) return new List<Prod_Banci_Enum> { Prod_Banci_Enum.甲, Prod_Banci_Enum.乙 };
|
|
return cfgs.Select(x => x.Banci).Distinct().OrderBy(x => x).ToList();
|
|
}
|
|
|
|
private async Task<decimal> GetLiantongBiaozhongAsync()
|
|
{
|
|
var row = await _registryRepo.FirstOrDefaultAsync(x =>
|
|
x.Category == RegistryCategory && x.KeyName == RegistryKey);
|
|
if (row == null || string.IsNullOrWhiteSpace(row.Value)) return 0m;
|
|
return decimal.TryParse(row.Value, out var v) ? v : 0m;
|
|
}
|
|
|
|
private sealed class Ctx
|
|
{
|
|
public Dictionary<long, string> DeptNames { get; init; } = new();
|
|
public Dictionary<long, string> GyzkNames { get; init; } = new();
|
|
}
|
|
|
|
private async Task<Ctx> BuildContextAsync()
|
|
{
|
|
var depts = await _deptRepo.GetAllAsync();
|
|
var gyzks = await _gyzkRepo.GetAllAsync();
|
|
return new Ctx
|
|
{
|
|
DeptNames = depts.ToDictionary(d => d.Id, d => d.Name),
|
|
GyzkNames = gyzks.ToDictionary(z => z.Id, z => z.ProductionDisplayName is { Length: > 0 } n
|
|
? n
|
|
: z.ZhuangKouName)
|
|
};
|
|
}
|
|
}
|