新增工资/仓储/生产日报等模块,移除旧考勤模块
- 新增 PayRoll(工资)、Wms(仓储)、Prod(车速/缫丝/考勤/丝片检测/丝片台账/纤检日报/质量日报) 模块 - 新增对应 Domain 实体、Application DTO/Service、Api Controller 与前端页面 - 移除旧 Attendance 考勤模块(Controller/Service/Entity/DTO 及 5 个前端页面),由 Prod/Kaoqin 取代 - 调整路由、仪表盘、Lsjl 流丝记录实体与服务 - 更新业务种子数据与 DbSeeder - 补充工作进度文档 14-27
This commit is contained in:
@@ -0,0 +1,819 @@
|
||||
using F9WebAiTest.Application.Common;
|
||||
using F9WebAiTest.Application.Dtos.PayRoll;
|
||||
using F9WebAiTest.Domain.Common;
|
||||
using F9WebAiTest.Domain.Entities.Base;
|
||||
using F9WebAiTest.Domain.Entities.PayRoll;
|
||||
using F9WebAiTest.Domain.Entities.Prod;
|
||||
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
|
||||
using SysEmp = F9WebAiTest.Domain.Entities.SYS.Employees;
|
||||
using SysWt = F9WebAiTest.Domain.Entities.SYS.WorkTypes;
|
||||
|
||||
namespace F9WebAiTest.Application.Services.PayRoll;
|
||||
|
||||
/// <summary>
|
||||
/// 薪资计算-立缫挡车车头(挡车工 / 车头工 产量计算)
|
||||
/// 对应 F9 WinClient\F9.Business.PayRoll\PAYROLL\CALCLDCCT(Page_CalcLdcct + Page_CalcLdcct_Edit)
|
||||
/// 数据源:看台记录(挡车/车头)、煮茧日报(今缫桶数)、落丝记录(茧量)、秤大丝(丝量/缫折)、
|
||||
/// 纤度检验(纤度明细/均方差/总差)、黑板检验(二度/三度/清洁/洁净)、生丝规格、生丝定级指标。
|
||||
/// 配置:工艺庄口薪资配置、工种薪资配置、挡车岗位薪资配置、挡车纤度奖扣、薪资价格配置。
|
||||
/// </summary>
|
||||
public interface ICalcLdcctService
|
||||
{
|
||||
Task<PageResult<CalcLdcctListItemDto>> GetPagedAsync(int pageIndex, int pageSize, DateTime start, DateTime end,
|
||||
long? depId, long? worktypeId, string like);
|
||||
Task<CalcLdcctResultDto> CalcDcgAsync(CalcLdcctCalcDto dto);
|
||||
Task<CalcLdcctResultDto> CalcCtgAsync(CalcLdcctCalcDto dto);
|
||||
Task<int> SaveAsync(CalcLdcctSaveDto dto);
|
||||
Task DeleteAsync(DateTime start, DateTime end, long depId, long worktypeId);
|
||||
}
|
||||
|
||||
public class CalcLdcctService : ICalcLdcctService
|
||||
{
|
||||
private readonly IRepository<CalcLdcct> _repo;
|
||||
private readonly IRepository<KtjlDcg> _dcgRepo;
|
||||
private readonly IRepository<KtjlCtg> _ctgRepo;
|
||||
private readonly IRepository<ZjrbRecord> _zjrbRepo;
|
||||
private readonly IRepository<ZjrbJizu> _zjrbJizuRepo;
|
||||
private readonly IRepository<LsjlRecord> _lsjlRepo;
|
||||
private readonly IRepository<CdsLsjl> _cdsLsjlRepo;
|
||||
private readonly IRepository<CdsChetai> _cdsChetaiRepo;
|
||||
private readonly IRepository<XdjyLsjl> _xdjyLsjlRepo;
|
||||
private readonly IRepository<XdjyRecord> _xdjyRecordRepo;
|
||||
private readonly IRepository<HbjyRecord> _hbjyRepo;
|
||||
private readonly IRepository<ConfGyzk> _confGyzkRepo;
|
||||
private readonly IRepository<ConfGz> _confGzRepo;
|
||||
private readonly IRepository<ConfDcg> _confDcgRepo;
|
||||
private readonly IRepository<DangCheXianDuJiangKou> _xdjkRepo;
|
||||
private readonly IRepository<XinZiJiaGePeiZhi> _xzjgRepo;
|
||||
private readonly IRepository<ShengsiGuige> _guigeRepo;
|
||||
private readonly IRepository<ShengsiDingjizhibiao> _ssdjzbRepo;
|
||||
private readonly IRepository<CraftZhuangKou> _zkRepo;
|
||||
private readonly IRepository<SysDept.Department> _depRepo;
|
||||
private readonly IRepository<SysEmp.Employee> _empRepo;
|
||||
private readonly IRepository<SysWt.WorkType> _wtRepo;
|
||||
|
||||
public CalcLdcctService(
|
||||
IRepository<CalcLdcct> repo,
|
||||
IRepository<KtjlDcg> dcgRepo,
|
||||
IRepository<KtjlCtg> ctgRepo,
|
||||
IRepository<ZjrbRecord> zjrbRepo,
|
||||
IRepository<ZjrbJizu> zjrbJizuRepo,
|
||||
IRepository<LsjlRecord> lsjlRepo,
|
||||
IRepository<CdsLsjl> cdsLsjlRepo,
|
||||
IRepository<CdsChetai> cdsChetaiRepo,
|
||||
IRepository<XdjyLsjl> xdjyLsjlRepo,
|
||||
IRepository<XdjyRecord> xdjyRecordRepo,
|
||||
IRepository<HbjyRecord> hbjyRepo,
|
||||
IRepository<ConfGyzk> confGyzkRepo,
|
||||
IRepository<ConfGz> confGzRepo,
|
||||
IRepository<ConfDcg> confDcgRepo,
|
||||
IRepository<DangCheXianDuJiangKou> xdjkRepo,
|
||||
IRepository<XinZiJiaGePeiZhi> xzjgRepo,
|
||||
IRepository<ShengsiGuige> guigeRepo,
|
||||
IRepository<ShengsiDingjizhibiao> ssdjzbRepo,
|
||||
IRepository<CraftZhuangKou> zkRepo,
|
||||
IRepository<SysDept.Department> depRepo,
|
||||
IRepository<SysEmp.Employee> empRepo,
|
||||
IRepository<SysWt.WorkType> wtRepo)
|
||||
{
|
||||
_repo = repo; _dcgRepo = dcgRepo; _ctgRepo = ctgRepo;
|
||||
_zjrbRepo = zjrbRepo; _zjrbJizuRepo = zjrbJizuRepo; _lsjlRepo = lsjlRepo;
|
||||
_cdsLsjlRepo = cdsLsjlRepo; _cdsChetaiRepo = cdsChetaiRepo;
|
||||
_xdjyLsjlRepo = xdjyLsjlRepo; _xdjyRecordRepo = xdjyRecordRepo; _hbjyRepo = hbjyRepo;
|
||||
_confGyzkRepo = confGyzkRepo; _confGzRepo = confGzRepo; _confDcgRepo = confDcgRepo;
|
||||
_xdjkRepo = xdjkRepo; _xzjgRepo = xzjgRepo; _guigeRepo = guigeRepo; _ssdjzbRepo = ssdjzbRepo;
|
||||
_zkRepo = zkRepo; _depRepo = depRepo; _empRepo = empRepo; _wtRepo = wtRepo;
|
||||
}
|
||||
|
||||
// ==================== 常量(对齐 F9 Page_CalcLdcct) ====================
|
||||
private const decimal XushuPerTai = 20m; // 每台绪数
|
||||
private const decimal CtgTaiShu = 20m; // 车头工台时按 20 台/组
|
||||
private const decimal CtgHoursDiv = 9m; // 车头基础单价 /9(标准上班时长)
|
||||
private const decimal CtgRenShu = 2m; // 车头标准人数 2
|
||||
private const decimal DengjiStep = 0.1m; // 等级分步长
|
||||
private const int SaozheDeadZone = 2; // 缫折死区 ±2kg
|
||||
private const int DcgSaozheCap = 10; // 挡车缫折封顶 ±10
|
||||
private const int CtgSaozheCap = 3; // 车头缫折封顶 ±3
|
||||
private const string PriceGroup = "薪资.前缫";
|
||||
private const string DcgDengjiPriceKey = "挡车工计件等级奖扣单价";
|
||||
private const string CtgDengjiPriceKey = "车头工计件等级奖扣单价";
|
||||
|
||||
// ==================== 查询 ====================
|
||||
|
||||
public async Task<PageResult<CalcLdcctListItemDto>> GetPagedAsync(int pageIndex, int pageSize, DateTime start,
|
||||
DateTime end, long? depId, long? worktypeId, string like)
|
||||
{
|
||||
var all = await _repo.GetAllAsync();
|
||||
var from = start.Date;
|
||||
var to = end.Date;
|
||||
var q = all.AsQueryable().Where(x => x.Date.Date >= from && x.Date.Date <= to);
|
||||
if (depId.HasValue) q = q.Where(x => x.DepId == depId.Value);
|
||||
if (worktypeId.HasValue) q = q.Where(x => x.WorktypeId == worktypeId.Value);
|
||||
|
||||
var deps = await _depRepo.GetAllAsync();
|
||||
var emps = await _empRepo.GetAllAsync();
|
||||
var wts = await _wtRepo.GetAllAsync();
|
||||
var zks = await _zkRepo.GetAllAsync();
|
||||
var confGyzks = await _confGyzkRepo.GetAllAsync();
|
||||
|
||||
var depDict = deps.ToDictionary(d => d.Id, d => d.Name);
|
||||
var empDict = emps.ToDictionary(e => e.Id, e => e.Name);
|
||||
var wtDict = wts.ToDictionary(w => w.Id, w => w.WorkName);
|
||||
var zkDict = zks.ToDictionary(z => z.Id, z => z.ZhuangKouName);
|
||||
var confDict = confGyzks.GroupBy(c => $"{c.Year}-{c.Month}-{c.GyzkId}")
|
||||
.ToDictionary(g => g.Key, g => g.OrderByDescending(c => c.Id).First());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(like))
|
||||
{
|
||||
var empIds = emps.Where(e => e.Name.Contains(like)).Select(e => e.Id).ToHashSet();
|
||||
var zkIds = zks.Where(z => z.ZhuangKouName.Contains(like)).Select(z => z.Id).ToHashSet();
|
||||
q = q.Where(x => empIds.Contains(x.EmployeeId) || zkIds.Contains(x.GyzkId));
|
||||
}
|
||||
|
||||
var total = q.LongCount();
|
||||
var items = q.OrderBy(x => x.Date).ThenBy(x => x.Jizu).ThenBy(x => x.Banci).ThenBy(x => x.EmployeeId)
|
||||
.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
||||
|
||||
return new PageResult<CalcLdcctListItemDto>
|
||||
{
|
||||
Items = items.Select(x =>
|
||||
{
|
||||
confDict.TryGetValue($"{x.Date.Year}-{x.Date.Month}-{x.GyzkId}", out var cfg);
|
||||
return new CalcLdcctListItemDto
|
||||
{
|
||||
Id = x.Id, Date = x.Date, EmployeeId = x.EmployeeId,
|
||||
EmployeeName = empDict.GetValueOrDefault(x.EmployeeId, ""),
|
||||
DepId = x.DepId, DepName = depDict.GetValueOrDefault(x.DepId, ""),
|
||||
WorktypeId = x.WorktypeId, WorktypeName = wtDict.GetValueOrDefault(x.WorktypeId, ""),
|
||||
GyzkId = x.GyzkId, GyzkName = zkDict.GetValueOrDefault(x.GyzkId, ""),
|
||||
Guige = x.Guige, Chetai = x.Chetai, Jizu = x.Jizu, Banci = x.Banci,
|
||||
BanciName = BanciName(x.Banci),
|
||||
HoursKantai = x.HoursKantai, Dangcheshu = x.Dangcheshu,
|
||||
Dengji = x.Dengji, Dengjifen = x.Dengjifen,
|
||||
GyzkTaichan = cfg?.QsTaichan ?? 0, GyzkSaozhe = cfg?.SaoZhe ?? 0,
|
||||
ClDanjiaBase = x.ClDanjiaBase, ClDanjiaDengji = x.ClDanjiaDengji,
|
||||
ClDanjiaActual = x.ClDanjiaActual, ClSiliang = x.ClSiliang,
|
||||
ZlSaozhe = x.ZlSaozhe, ZlCenterxd = x.ZlCenterxd, ZlYexiannum = x.ZlYexiannum,
|
||||
ZlQingjie = x.ZlQingjie, ZlJiejing = x.ZlJiejing, ZlErdu = x.ZlErdu, ZlSandu = x.ZlSandu,
|
||||
JineCl_Original = x.JineCl_Original, Xishu_JineCl = x.Xishu_JineCl, JineCl = x.JineCl,
|
||||
JineZlSaozhe = x.JineZlSaozhe, JineZlCenterxd = x.JineZlCenterxd, JineZlYexian = x.JineZlYexian,
|
||||
JineZlQingjie = x.JineZlQingjie, JineZlJiejing = x.JineZlJiejing,
|
||||
JineZlErdu = x.JineZlErdu, JineZlSandu = x.JineZlSandu,
|
||||
JineZlTotal = x.JineZlSaozhe + x.JineZlCenterxd + x.JineZlYexian + x.JineZlQingjie
|
||||
+ x.JineZlJiejing + x.JineZlErdu + x.JineZlSandu
|
||||
};
|
||||
}).ToList(),
|
||||
Total = total, PageIndex = pageIndex, PageSize = pageSize
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== 一键计算:挡车工 ====================
|
||||
|
||||
public async Task<CalcLdcctResultDto> CalcDcgAsync(CalcLdcctCalcDto dto)
|
||||
{
|
||||
var ctx = await BuildContextAsync(dto);
|
||||
var result = new CalcLdcctResultDto();
|
||||
if (ctx.DcgKtjl.Count == 0)
|
||||
{
|
||||
result.Warnings.Add("该账期该部门没有挡车工看台记录");
|
||||
return result;
|
||||
}
|
||||
|
||||
var rows = new List<CalcLdcct>();
|
||||
|
||||
// 按「日 + 机组」组织
|
||||
var jizuDays = ctx.DcgKtjl.GroupBy(k => (k.Date.Date, k.Jizu));
|
||||
foreach (var jd in jizuDays)
|
||||
{
|
||||
var (date, jizu) = jd.Key;
|
||||
var ktjls = jd.Where(k => !k.NoChanliang).ToList();
|
||||
if (ktjls.Count == 0) continue;
|
||||
|
||||
// 该机组当日各庄口的今缫桶数(煮茧日报不分班)
|
||||
var gyzkTongshu = ctx.GyzkTongshuByJizuDay.TryGetValue((date, jizu), out var gt)
|
||||
? gt : new List<(long GyzkId, string Guige, int Tongshu, int StdLuosi)>();
|
||||
|
||||
var tongshuSum = gyzkTongshu.Sum(g => g.Tongshu);
|
||||
var banciNum = ktjls.Select(k => k.Banci).Distinct().Count();
|
||||
var half = banciNum >= 2 ? 0.5m : 1m;
|
||||
|
||||
foreach (var (gyzkId, guige, tongshu, stdLuosi) in gyzkTongshu)
|
||||
{
|
||||
var cfg = ctx.ConfGyzk(gyzkId, date);
|
||||
if (cfg == null)
|
||||
{
|
||||
result.Warnings.Add($"{date:yyyy-MM-dd} 机组 {jizu} 庄口缺少薪资配置,已跳过");
|
||||
continue;
|
||||
}
|
||||
var guigeCfg = ctx.Guige(guige);
|
||||
|
||||
// 每桶丝量 = 每车丝量(kg→g) / 标准落丝桶数
|
||||
if (stdLuosi <= 0 || cfg.MeiCheSiLiang <= 0)
|
||||
{
|
||||
result.Warnings.Add($"{date:yyyy-MM-dd} 庄口 {cfg.Guige} 缺少每车丝量/标准落丝桶数,已跳过");
|
||||
continue;
|
||||
}
|
||||
var meitongSiliang = cfg.MeiCheSiLiang * 1000m / stdLuosi;
|
||||
var jiayiSumSiliang = Math.Round(tongshu * meitongSiliang, 0, MidpointRounding.AwayFromZero);
|
||||
|
||||
var rate = tongshuSum > 0 ? (decimal)tongshu / tongshuSum : 0m;
|
||||
|
||||
// 按班次拆分丝量:按 台时 = 挡车数 × 时长 加权
|
||||
var jizuDayTaishi = ktjls.Sum(k => k.DangcheNum * k.Hours);
|
||||
foreach (var banciGroup in ktjls.GroupBy(k => k.Banci))
|
||||
{
|
||||
var banciTaishi = banciGroup.Sum(k => k.DangcheNum * k.Hours);
|
||||
var banciSiliang = jizuDayTaishi > 0
|
||||
? Math.Round(jiayiSumSiliang * (banciTaishi / jizuDayTaishi), 0, MidpointRounding.AwayFromZero)
|
||||
: 0m;
|
||||
var groupTaishi = banciTaishi;
|
||||
|
||||
foreach (var k in banciGroup)
|
||||
{
|
||||
// 看台时长:按庄口今缫桶数占比分摊个人工时
|
||||
var hoursKantai = Math.Round(k.Hours * rate, 1, MidpointRounding.AwayFromZero);
|
||||
|
||||
var siliang = groupTaishi > 0
|
||||
? Math.Round(banciSiliang * (k.DangcheNum * k.Hours / groupTaishi), 0, MidpointRounding.AwayFromZero)
|
||||
: 0m;
|
||||
|
||||
// ---- 质量(按车台看台比例分摊) ----
|
||||
var quality = CalcDcgQuality(ctx, date, jizu, gyzkId, k, half, cfg, guigeCfg);
|
||||
|
||||
// ---- 等级(木桶短板) ----
|
||||
var (dengji, dengjifen) = CalDengJi(ctx, guige, quality.Junfangcha, quality.Zongcha,
|
||||
quality.QingjieFen, quality.JiejingFen, quality.Erdu, quality.Sandu, cfg);
|
||||
|
||||
// ---- 单价 ----
|
||||
var xushu = k.DangcheNum * XushuPerTai;
|
||||
var gangweiBase = GetDcgDanJiaBase(xushu, ctx.ConfDcg);
|
||||
if (ctx.ConfGz == null || ctx.ConfGz.QqDaysStandard <= 0 || ctx.ConfGz.HoursPerday <= 0
|
||||
|| cfg.QsTaichan <= 0 || k.DangcheNum <= 0)
|
||||
{
|
||||
result.Warnings.Add($"工种薪资配置或庄口台产缺失,{date:yyyy-MM-dd} {k.EmployeeId} 已跳过");
|
||||
continue;
|
||||
}
|
||||
var danjiaBase = Math.Round(gangweiBase / ctx.ConfGz.QqDaysStandard / k.DangcheNum
|
||||
/ ctx.ConfGz.HoursPerday / cfg.QsTaichan, 7, MidpointRounding.AwayFromZero);
|
||||
if (danjiaBase == 0) continue;
|
||||
|
||||
var danjiaDengji = Math.Round(
|
||||
(dengjifen - cfg.QsDengjifen) / DengjiStep * ctx.DcgJjDengJiJkPrice / 10m / 1000m,
|
||||
7, MidpointRounding.AwayFromZero);
|
||||
var danjiaActual = Math.Round(danjiaBase + danjiaDengji, 7, MidpointRounding.AwayFromZero);
|
||||
|
||||
// ---- 金额 ----
|
||||
var e = new CalcLdcct
|
||||
{
|
||||
Date = date, EmployeeId = k.EmployeeId, DepId = dto.DepId, WorktypeId = dto.WorktypeId,
|
||||
Jizu = jizu, Banci = (int)k.Banci, GyzkId = gyzkId, Guige = guige,
|
||||
Chetai = k.ChetaiStart == k.ChetaiEnd ? k.ChetaiStart.ToString() : $"{k.ChetaiStart}-{k.ChetaiEnd}",
|
||||
HoursKantai = hoursKantai, Dangcheshu = k.DangcheNum, Dengji = dengji, Dengjifen = dengjifen,
|
||||
ClDanjiaBase = danjiaBase, ClDanjiaDengji = danjiaDengji, ClDanjiaActual = danjiaActual,
|
||||
ClSiliang = siliang,
|
||||
ZlSaozhe = quality.Saozhe, ZlCenterxd = quality.CenterNum, ZlYexiannum = quality.YexianNum,
|
||||
ZlQingjie = quality.QingjiePianshu, ZlJiejing = quality.JiejingPianshu,
|
||||
ZlErdu = quality.Erdu, ZlSandu = quality.Sandu,
|
||||
Xishu_JineCl = cfg.DcgJijianXishu
|
||||
};
|
||||
e.JineCl_Original = Math.Round(danjiaActual * siliang, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineCl = Math.Round(danjiaActual * siliang * cfg.DcgJijianXishu, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlSaozhe = CalJineSaozhe(cfg.SaoZhe, quality.Saozhe, siliang, DcgSaozheCap, 5m);
|
||||
e.JineZlCenterxd = Math.Round(quality.CenterNum * 1m, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlYexian = -Math.Round(quality.YexianKouKuan, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlQingjie = -Math.Round(quality.QingjieKouKuan, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlJiejing = -Math.Round(quality.JiejingKouKuan, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlErdu = -Math.Round(quality.Erdu * 2m, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlSandu = -Math.Round(quality.Sandu * 20m, 2, MidpointRounding.AwayFromZero);
|
||||
|
||||
rows.Add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await PersistAsync(rows, dto, result);
|
||||
}
|
||||
|
||||
// ==================== 一键计算:车头工 ====================
|
||||
|
||||
public async Task<CalcLdcctResultDto> CalcCtgAsync(CalcLdcctCalcDto dto)
|
||||
{
|
||||
var ctx = await BuildContextAsync(dto);
|
||||
var result = new CalcLdcctResultDto();
|
||||
if (ctx.CtgKtjl.Count == 0)
|
||||
{
|
||||
result.Warnings.Add("该账期该部门没有车头工看台记录");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 车头工强依赖已存的挡车工产量
|
||||
var dcgRows = (await _repo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= dto.StartDate.Date && x.Date.Date <= dto.EndDate.Date
|
||||
&& x.DepId == dto.DepId && x.WorktypeId == ctx.DcgWorktypeId).ToList();
|
||||
|
||||
var rows = new List<CalcLdcct>();
|
||||
|
||||
var jizuDays = ctx.CtgKtjl.GroupBy(k => (k.Date.Date, k.Jizu));
|
||||
foreach (var jd in jizuDays)
|
||||
{
|
||||
var (date, jizu) = jd.Key;
|
||||
var ktjls = jd.Where(k => !k.NoChanliang).ToList();
|
||||
if (ktjls.Count == 0) continue;
|
||||
|
||||
var gyzkTongshu = ctx.GyzkTongshuByJizuDay.TryGetValue((date, jizu), out var gt)
|
||||
? gt : new List<(long GyzkId, string Guige, int Tongshu, int StdLuosi)>();
|
||||
var tongshuSum = gyzkTongshu.Sum(g => g.Tongshu);
|
||||
var banciNum = ktjls.Select(k => k.Banci).Distinct().Count();
|
||||
var half = banciNum >= 2 ? 0.5m : 1m;
|
||||
|
||||
foreach (var (gyzkId, guige, tongshu, stdLuosi) in gyzkTongshu)
|
||||
{
|
||||
var cfg = ctx.ConfGyzk(gyzkId, date);
|
||||
if (cfg == null)
|
||||
{
|
||||
result.Warnings.Add($"{date:yyyy-MM-dd} 机组 {jizu} 庄口缺少薪资配置,已跳过");
|
||||
continue;
|
||||
}
|
||||
if (stdLuosi <= 0 || cfg.MeiCheSiLiang <= 0)
|
||||
{
|
||||
result.Warnings.Add($"{date:yyyy-MM-dd} 庄口 {cfg.Guige} 缺少每车丝量/标准落丝桶数,已跳过");
|
||||
continue;
|
||||
}
|
||||
var meitongSiliang = cfg.MeiCheSiLiang * 1000m / stdLuosi;
|
||||
var jiayiSumSiliang = Math.Round(tongshu * meitongSiliang, 0, MidpointRounding.AwayFromZero);
|
||||
var rate = tongshuSum > 0 ? (decimal)tongshu / tongshuSum : 0m;
|
||||
|
||||
// 全组汇总质量(落丝主表,不分摊)
|
||||
var lsjlIds = ctx.LsjlIdsByJizuDayGyzk.TryGetValue((date, jizu, gyzkId), out var ids)
|
||||
? ids : new List<long>();
|
||||
var saozheList = new List<decimal>();
|
||||
var erduSum = 0m; var sanduSum = 0m;
|
||||
foreach (var lid in lsjlIds)
|
||||
{
|
||||
if (ctx.CdsLsjl.TryGetValue(lid, out var cds) && cds.Siliang > 0 && cds.Jianliang > 0)
|
||||
saozheList.Add((decimal)cds.Jianliang * 100m / cds.Siliang);
|
||||
if (ctx.HbjyByLsjl.TryGetValue(lid, out var hb))
|
||||
{
|
||||
erduSum += hb.Sum(h => h.YdErdu);
|
||||
sanduSum += hb.Sum(h => h.YdSandu);
|
||||
}
|
||||
}
|
||||
var zlSaozhe = saozheList.Count > 0
|
||||
? Math.Round(saozheList.Average(), 0, MidpointRounding.AwayFromZero) : cfg.SaoZhe;
|
||||
|
||||
var jizuDayTaishi = ktjls.Sum(k => CtgTaiShu * k.Hours);
|
||||
|
||||
foreach (var banciGroup in ktjls.GroupBy(k => k.Banci))
|
||||
{
|
||||
var banciTaishi = banciGroup.Sum(k => CtgTaiShu * k.Hours);
|
||||
var banciSiliang = jizuDayTaishi > 0
|
||||
? Math.Round(jiayiSumSiliang * (banciTaishi / jizuDayTaishi), 0, MidpointRounding.AwayFromZero)
|
||||
: 0m;
|
||||
var maxHours = banciGroup.Max(k => k.Hours);
|
||||
|
||||
foreach (var k in banciGroup)
|
||||
{
|
||||
var hoursKantai = Math.Round(k.Hours * rate, 1, MidpointRounding.AwayFromZero);
|
||||
var siliang = maxHours > 0
|
||||
? Math.Round(banciSiliang * (k.Hours / (maxHours * CtgRenShu)), 0, MidpointRounding.AwayFromZero)
|
||||
: 0m;
|
||||
|
||||
// 等级:按挡车工丝量加权平均等级分再回落取整档
|
||||
var (dengji, dengjifen) = CalCtgDengji(ctx, dcgRows, date, jizu, gyzkId, guige, cfg);
|
||||
|
||||
if (ctx.ConfGz == null || ctx.ConfGz.QqDaysStandard <= 0 || cfg.QsTaichan <= 0)
|
||||
{
|
||||
result.Warnings.Add($"工种薪资配置缺失,{date:yyyy-MM-dd} {k.EmployeeId} 已跳过");
|
||||
continue;
|
||||
}
|
||||
var danjiaBase = Math.Round(ctx.ConfDcg.JineCtg / ctx.ConfGz.QqDaysStandard / CtgHoursDiv
|
||||
/ CtgTaiShu / cfg.QsTaichan * CtgRenShu, 7, MidpointRounding.AwayFromZero);
|
||||
if (danjiaBase == 0) continue;
|
||||
|
||||
var danjiaDengji = Math.Round(
|
||||
(dengjifen - cfg.QsDengjifen) / DengjiStep * ctx.CtgJjDengJiJkPrice / 10m / 1000m,
|
||||
7, MidpointRounding.AwayFromZero);
|
||||
var danjiaActual = Math.Round(danjiaBase + danjiaDengji, 7, MidpointRounding.AwayFromZero);
|
||||
|
||||
var e = new CalcLdcct
|
||||
{
|
||||
Date = date, EmployeeId = k.EmployeeId, DepId = dto.DepId, WorktypeId = dto.WorktypeId,
|
||||
Jizu = jizu, Banci = (int)k.Banci, GyzkId = gyzkId, Guige = guige, Chetai = "",
|
||||
HoursKantai = hoursKantai, Dangcheshu = 0, Dengji = dengji, Dengjifen = dengjifen,
|
||||
ClDanjiaBase = danjiaBase, ClDanjiaDengji = danjiaDengji, ClDanjiaActual = danjiaActual,
|
||||
ClSiliang = siliang,
|
||||
ZlSaozhe = zlSaozhe, ZlCenterxd = 0, ZlYexiannum = 0, ZlQingjie = 0, ZlJiejing = 0,
|
||||
ZlErdu = Math.Round(erduSum * half, 2, MidpointRounding.AwayFromZero),
|
||||
ZlSandu = Math.Round(sanduSum * half, 2, MidpointRounding.AwayFromZero),
|
||||
Xishu_JineCl = cfg.CtgJijianXishu
|
||||
};
|
||||
e.JineCl_Original = Math.Round(danjiaActual * siliang, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineCl = Math.Round(danjiaActual * siliang * cfg.CtgJijianXishu, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlSaozhe = CalJineSaozhe(cfg.SaoZhe, zlSaozhe, siliang, CtgSaozheCap, 1m);
|
||||
e.JineZlCenterxd = 0; e.JineZlYexian = 0; e.JineZlQingjie = 0; e.JineZlJiejing = 0;
|
||||
e.JineZlErdu = -Math.Round(e.ZlErdu * 2m, 2, MidpointRounding.AwayFromZero);
|
||||
e.JineZlSandu = -Math.Round(e.ZlSandu * 20m, 2, MidpointRounding.AwayFromZero);
|
||||
|
||||
rows.Add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await PersistAsync(rows, dto, result);
|
||||
}
|
||||
|
||||
// ==================== 保存 / 删除 ====================
|
||||
|
||||
public async Task<int> SaveAsync(CalcLdcctSaveDto dto)
|
||||
{
|
||||
var olds = (await _repo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= dto.StartDate.Date && x.Date.Date <= dto.EndDate.Date
|
||||
&& x.DepId == dto.DepId && x.WorktypeId == dto.WorktypeId).ToList();
|
||||
if (olds.Count > 0) await _repo.HardDeleteRangeAsync(olds);
|
||||
|
||||
foreach (var it in dto.Items)
|
||||
{
|
||||
var e = new CalcLdcct
|
||||
{
|
||||
Date = it.Date.Date, EmployeeId = it.EmployeeId, DepId = it.DepId, WorktypeId = it.WorktypeId,
|
||||
Jizu = it.Jizu, Banci = it.Banci, GyzkId = it.GyzkId, Guige = it.Guige ?? "", Chetai = it.Chetai ?? "",
|
||||
HoursKantai = it.HoursKantai, Dangcheshu = it.Dangcheshu, Dengji = it.Dengji ?? "", Dengjifen = it.Dengjifen,
|
||||
ClDanjiaBase = it.ClDanjiaBase, ClDanjiaDengji = it.ClDanjiaDengji, ClDanjiaActual = it.ClDanjiaActual,
|
||||
ClSiliang = it.ClSiliang,
|
||||
ZlSaozhe = it.ZlSaozhe, ZlCenterxd = it.ZlCenterxd, ZlYexiannum = it.ZlYexiannum,
|
||||
ZlQingjie = it.ZlQingjie, ZlJiejing = it.ZlJiejing, ZlErdu = it.ZlErdu, ZlSandu = it.ZlSandu,
|
||||
JineCl_Original = it.JineCl_Original, Xishu_JineCl = it.Xishu_JineCl, JineCl = it.JineCl,
|
||||
JineZlSaozhe = it.JineZlSaozhe, JineZlCenterxd = it.JineZlCenterxd, JineZlYexian = it.JineZlYexian,
|
||||
JineZlQingjie = it.JineZlQingjie, JineZlJiejing = it.JineZlJiejing,
|
||||
JineZlErdu = it.JineZlErdu, JineZlSandu = it.JineZlSandu
|
||||
};
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
return dto.Items.Count;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(DateTime start, DateTime end, long depId, long worktypeId)
|
||||
{
|
||||
var olds = (await _repo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= start.Date && x.Date.Date <= end.Date
|
||||
&& x.DepId == depId && x.WorktypeId == worktypeId).ToList();
|
||||
if (olds.Count > 0) await _repo.HardDeleteRangeAsync(olds);
|
||||
}
|
||||
|
||||
// ==================== 内部:上下文 ====================
|
||||
|
||||
private class CalcContext
|
||||
{
|
||||
public List<KtjlDcg> DcgKtjl = new();
|
||||
public List<KtjlCtg> CtgKtjl = new();
|
||||
public long DcgWorktypeId;
|
||||
public Dictionary<(DateTime, int), List<(long GyzkId, string Guige, int Tongshu, int StdLuosi)>> GyzkTongshuByJizuDay = new();
|
||||
public Dictionary<(DateTime, int, long), List<long>> LsjlIdsByJizuDayGyzk = new();
|
||||
public Dictionary<long, CdsLsjl> CdsLsjl = new();
|
||||
public Dictionary<long, List<CdsChetai>> CdsChetai = new();
|
||||
public Dictionary<long, List<XdjyRecord>> XdjyByLsjl = new();
|
||||
public Dictionary<long, List<HbjyRecord>> HbjyByLsjl = new();
|
||||
public Dictionary<long, List<ConfGyzk>> ConfByGyzk = new();
|
||||
public Dictionary<string, ShengsiGuige> GuigeDict = new();
|
||||
public Dictionary<string, List<DangCheXianDuJiangKou>> YeXianJk = new();
|
||||
public List<ShengsiDingjizhibiao> Djzb = new();
|
||||
public ConfGz ConfGz = null!;
|
||||
public ConfDcg ConfDcg = null!;
|
||||
public decimal DcgJjDengJiJkPrice;
|
||||
public decimal CtgJjDengJiJkPrice;
|
||||
public List<string> Warnings = new();
|
||||
|
||||
public ConfGyzk ConfGyzk(long gyzkId, DateTime date) =>
|
||||
ConfByGyzk.TryGetValue(gyzkId, out var list)
|
||||
? list.FirstOrDefault(c => c.Year == date.Year && c.Month == date.Month)
|
||||
?? list.OrderByDescending(c => c.Year).ThenByDescending(c => c.Month).FirstOrDefault()
|
||||
: null;
|
||||
|
||||
public ShengsiGuige Guige(string guige) =>
|
||||
GuigeDict.TryGetValue(guige ?? "", out var g) ? g : null;
|
||||
|
||||
public List<DangCheXianDuJiangKou> YeXianJiangKou(string guige) =>
|
||||
YeXianJk.TryGetValue(guige ?? "", out var l) ? l : new List<DangCheXianDuJiangKou>();
|
||||
}
|
||||
|
||||
private async Task<CalcContext> BuildContextAsync(CalcLdcctCalcDto dto)
|
||||
{
|
||||
var ctx = new CalcContext();
|
||||
var from = dto.StartDate.Date;
|
||||
var to = dto.EndDate.Date;
|
||||
|
||||
ctx.DcgKtjl = (await _dcgRepo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= from && x.Date.Date <= to && x.DeptId == dto.DepId).ToList();
|
||||
ctx.CtgKtjl = (await _ctgRepo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= from && x.Date.Date <= to && x.DeptId == dto.DepId).ToList();
|
||||
|
||||
// 挡车工工种:取看台记录中出现最多的工种(车头计算需按挡车工工种取已存产量)
|
||||
ctx.DcgWorktypeId = ctx.DcgKtjl.GroupBy(k => k.WorktypeId).OrderByDescending(g => g.Count())
|
||||
.Select(g => g.Key).FirstOrDefault();
|
||||
|
||||
// 煮茧日报:日 + 机组 → 各庄口今缫桶数(不分班)
|
||||
var zjrbs = (await _zjrbRepo.GetAllAsync())
|
||||
.Where(x => x.Date.Date >= from && x.Date.Date <= to && x.DeptId == dto.DepId).ToList();
|
||||
var zjrbJizus = await _zjrbJizuRepo.GetAllAsync();
|
||||
foreach (var z in zjrbs)
|
||||
{
|
||||
foreach (var jz in zjrbJizus.Where(j => j.ZjrbId == z.Id))
|
||||
{
|
||||
var key = (z.Date.Date, jz.Jizu);
|
||||
if (!ctx.GyzkTongshuByJizuDay.TryGetValue(key, out var list))
|
||||
ctx.GyzkTongshuByJizuDay[key] = list = new List<(long, string, int, int)>();
|
||||
list.Add((z.GyzkId, z.Guige, jz.TongshuJinsao, z.StandardLuositongshu));
|
||||
}
|
||||
}
|
||||
|
||||
// 落丝记录:日 + 机组 + 庄口 → lsjlId 列表
|
||||
var lsjls = (await _lsjlRepo.GetAllAsync())
|
||||
.Where(x => x.WorkDate.Date >= from && x.WorkDate.Date <= to && x.DeptId == dto.DepId).ToList();
|
||||
foreach (var l in lsjls)
|
||||
{
|
||||
var key = (l.WorkDate.Date, l.Jizu, l.GyzkId);
|
||||
if (!ctx.LsjlIdsByJizuDayGyzk.TryGetValue(key, out var list))
|
||||
ctx.LsjlIdsByJizuDayGyzk[key] = list = new List<long>();
|
||||
list.Add(l.Id);
|
||||
}
|
||||
var allLsjlIds = lsjls.Select(l => l.Id).ToHashSet();
|
||||
|
||||
ctx.CdsLsjl = (await _cdsLsjlRepo.GetAllAsync()).Where(x => allLsjlIds.Contains(x.LsjlId))
|
||||
.GroupBy(x => x.LsjlId).ToDictionary(g => g.Key, g => g.First());
|
||||
ctx.CdsChetai = (await _cdsChetaiRepo.GetAllAsync()).Where(x => allLsjlIds.Contains(x.LsjlId))
|
||||
.GroupBy(x => x.LsjlId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
ctx.XdjyByLsjl = (await _xdjyRecordRepo.GetAllAsync()).Where(x => allLsjlIds.Contains(x.LsjlId))
|
||||
.GroupBy(x => x.LsjlId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
ctx.HbjyByLsjl = (await _hbjyRepo.GetAllAsync()).Where(x => allLsjlIds.Contains(x.LsjlId))
|
||||
.GroupBy(x => x.LsjlId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
_ = await _xdjyLsjlRepo.GetAllAsync(); // 纤度汇总(等级参考,保留实体引用)
|
||||
|
||||
ctx.ConfByGyzk = (await _confGyzkRepo.GetAllAsync())
|
||||
.GroupBy(c => c.GyzkId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
ctx.GuigeDict = (await _guigeRepo.GetAllAsync())
|
||||
.GroupBy(g => g.Guige).ToDictionary(g => g.Key, g => g.First());
|
||||
ctx.Djzb = (await _ssdjzbRepo.GetAllAsync()).Where(x => x.Standard == 2).ToList(); // 2=个人
|
||||
ctx.YeXianJk = (await _xdjkRepo.GetAllAsync())
|
||||
.GroupBy(x => x.GuiGe).ToDictionary(g => g.Key, g => g.OrderBy(x => x.XianDu).ToList());
|
||||
ctx.ConfGz = await _confGzRepo.FirstOrDefaultAsync(x => x.WorkTypeId == dto.WorktypeId);
|
||||
ctx.ConfDcg = await _confDcgRepo.FirstOrDefaultAsync(x => x.DepId == dto.DepId)
|
||||
?? new ConfDcg { DepId = dto.DepId };
|
||||
ctx.DcgJjDengJiJkPrice = await PriceAsync(DcgDengjiPriceKey);
|
||||
ctx.CtgJjDengJiJkPrice = await PriceAsync(CtgDengjiPriceKey);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
private async Task<decimal> PriceAsync(string key)
|
||||
{
|
||||
var e = await _xzjgRepo.FirstOrDefaultAsync(x => x.Group == PriceGroup && x.Key == key);
|
||||
return e?.Price ?? 0m;
|
||||
}
|
||||
|
||||
private async Task<CalcLdcctResultDto> PersistAsync(List<CalcLdcct> rows, CalcLdcctCalcDto dto, CalcLdcctResultDto result)
|
||||
{
|
||||
await SaveAsync(new CalcLdcctSaveDto
|
||||
{
|
||||
StartDate = dto.StartDate, EndDate = dto.EndDate, DepId = dto.DepId, WorktypeId = dto.WorktypeId,
|
||||
Items = rows.Select(r => new CalcLdcctSaveItemDto
|
||||
{
|
||||
Date = r.Date, EmployeeId = r.EmployeeId, DepId = r.DepId, WorktypeId = r.WorktypeId,
|
||||
Jizu = r.Jizu, Banci = r.Banci, GyzkId = r.GyzkId, Guige = r.Guige, Chetai = r.Chetai,
|
||||
HoursKantai = r.HoursKantai, Dangcheshu = r.Dangcheshu, Dengji = r.Dengji, Dengjifen = r.Dengjifen,
|
||||
ClDanjiaBase = r.ClDanjiaBase, ClDanjiaDengji = r.ClDanjiaDengji, ClDanjiaActual = r.ClDanjiaActual,
|
||||
ClSiliang = r.ClSiliang,
|
||||
ZlSaozhe = r.ZlSaozhe, ZlCenterxd = r.ZlCenterxd, ZlYexiannum = r.ZlYexiannum,
|
||||
ZlQingjie = r.ZlQingjie, ZlJiejing = r.ZlJiejing, ZlErdu = r.ZlErdu, ZlSandu = r.ZlSandu,
|
||||
JineCl_Original = r.JineCl_Original, Xishu_JineCl = r.Xishu_JineCl, JineCl = r.JineCl,
|
||||
JineZlSaozhe = r.JineZlSaozhe, JineZlCenterxd = r.JineZlCenterxd, JineZlYexian = r.JineZlYexian,
|
||||
JineZlQingjie = r.JineZlQingjie, JineZlJiejing = r.JineZlJiejing,
|
||||
JineZlErdu = r.JineZlErdu, JineZlSandu = r.JineZlSandu
|
||||
}).ToList()
|
||||
});
|
||||
|
||||
result.Count = rows.Count;
|
||||
result.SumSiliang = rows.Sum(r => r.ClSiliang);
|
||||
result.SumJineCl = Math.Round(rows.Sum(r => r.JineCl), 2, MidpointRounding.AwayFromZero);
|
||||
result.SumJineZl = Math.Round(rows.Sum(r => r.JineZlSaozhe + r.JineZlCenterxd + r.JineZlYexian
|
||||
+ r.JineZlQingjie + r.JineZlJiejing + r.JineZlErdu + r.JineZlSandu), 2, MidpointRounding.AwayFromZero);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== 内部:挡车工质量 ====================
|
||||
|
||||
private class DcgQuality
|
||||
{
|
||||
public decimal Saozhe;
|
||||
public decimal CenterNum;
|
||||
public decimal YexianNum;
|
||||
public decimal YexianKouKuan;
|
||||
public decimal QingjiePianshu;
|
||||
public decimal QingjieKouKuan;
|
||||
public decimal JiejingPianshu;
|
||||
public decimal JiejingKouKuan;
|
||||
public decimal Erdu;
|
||||
public decimal Sandu;
|
||||
public double Junfangcha;
|
||||
public double Zongcha;
|
||||
public decimal QingjieFen;
|
||||
public decimal JiejingFen;
|
||||
}
|
||||
|
||||
private DcgQuality CalcDcgQuality(CalcContext ctx, DateTime date, int jizu, long gyzkId, KtjlDcg k,
|
||||
decimal half, ConfGyzk cfg, ShengsiGuige guigeCfg)
|
||||
{
|
||||
var q = new DcgQuality();
|
||||
var lsjlIds = ctx.LsjlIdsByJizuDayGyzk.TryGetValue((date, jizu, gyzkId), out var ids)
|
||||
? ids : new List<long>();
|
||||
|
||||
decimal jianliangNum = 0m, siliangDen = 0m;
|
||||
double junfangchaSum = 0, zongchaSum = 0;
|
||||
int junfangchaCnt = 0;
|
||||
decimal erduSum = 0m, sanduSum = 0m;
|
||||
decimal qjTdc = 0m, qjDc = 0m, qjCj = 0m;
|
||||
decimal jj85 = 0m, jj80 = 0m, jj75 = 0m, jj70 = 0m;
|
||||
decimal pianshuSum = 0m, qingjieDeduct = 0m, jiejingDeduct = 0m;
|
||||
|
||||
foreach (var lid in lsjlIds)
|
||||
{
|
||||
var chetais = ctx.CdsChetai.TryGetValue(lid, out var ct) ? ct : new List<CdsChetai>();
|
||||
var cdsSum = ctx.CdsLsjl.TryGetValue(lid, out var cs) ? cs : null;
|
||||
var xdjy = ctx.XdjyByLsjl.TryGetValue(lid, out var xd) ? xd : new List<XdjyRecord>();
|
||||
var hbjy = ctx.HbjyByLsjl.TryGetValue(lid, out var hb) ? hb : new List<HbjyRecord>();
|
||||
|
||||
foreach (var ctItem in chetais)
|
||||
{
|
||||
if (ctItem.Chetaihao < k.ChetaiStart || ctItem.Chetaihao > k.ChetaiEnd) continue;
|
||||
var rate = ChetaiRate(ctx, date, jizu, ctItem.Chetaihao, k);
|
||||
|
||||
// 缫折:茧量只记在落丝层,按「车台丝量占落丝丝量的比例」摊到车台,再看台比例摊到人
|
||||
var lsjlSiliang = cdsSum?.Siliang ?? 0;
|
||||
var lsjlJianliang = cdsSum?.Jianliang ?? 0;
|
||||
var chetaiShare = lsjlSiliang > 0 ? (decimal)ctItem.Siliang / lsjlSiliang : 0m;
|
||||
jianliangNum += lsjlJianliang * chetaiShare * rate;
|
||||
siliangDen += ctItem.Siliang * rate;
|
||||
|
||||
// 中心纤度 / 野纤(纤度检验明细)
|
||||
foreach (var x in xdjy.Where(x => x.Chetaihao == ctItem.Chetaihao))
|
||||
{
|
||||
var xds = new[] { x.Xd1, x.Xd2, x.Xd3, x.Xd4 }.Where(v => v > 0).ToArray();
|
||||
if (guigeCfg != null)
|
||||
{
|
||||
q.CenterNum += xds.Count(v => Math.Abs(v - guigeCfg.CenterXiandu) < 0.0001) * rate;
|
||||
q.YexianNum += xds.Count(v => v <= guigeCfg.XiaoyeLolimit || v >= guigeCfg.XiaoyeUplimit) * rate;
|
||||
}
|
||||
if (xds.Length > 0)
|
||||
{
|
||||
var avg = xds.Average();
|
||||
var jfc = Math.Sqrt(xds.Sum(v => (v - avg) * (v - avg)) / xds.Length);
|
||||
junfangchaSum += jfc; junfangchaCnt++;
|
||||
var n = Math.Max(1, (int)Math.Ceiling(xds.Length * 0.02));
|
||||
var sorted = xds.OrderBy(v => v).ToArray();
|
||||
var minAvg = sorted.Take(n).Average();
|
||||
var maxAvg = sorted.Skip(xds.Length - n).Average();
|
||||
zongchaSum += Math.Max(Math.Abs(minAvg - avg), Math.Abs(maxAvg - avg));
|
||||
}
|
||||
}
|
||||
|
||||
// 黑板检验:二度/三度/清洁/洁净
|
||||
foreach (var h in hbjy.Where(h => h.Chetaihao == ctItem.Chetaihao))
|
||||
{
|
||||
erduSum += h.YdErdu * rate;
|
||||
sanduSum += h.YdSandu * rate;
|
||||
qjTdc += h.QjZycdTdc * rate;
|
||||
qjDc += h.QjCycdDc * rate;
|
||||
qjCj += h.QjPtcdCj * rate;
|
||||
jj85 += h.Jj85 * rate; jj80 += h.Jj80 * rate;
|
||||
jj75 += h.Jj75 * rate; jj70 += h.Jj70 * rate;
|
||||
|
||||
pianshuSum += h.Pianshu * rate;
|
||||
qingjieDeduct += (h.QjZycdTdc * 1.0m
|
||||
+ (h.QjCycdFs + h.QjCycdDc + h.QjCycdNfc + h.QjCycdDcj + h.QjCycdZlx) * 0.4m
|
||||
+ (h.QjPtcdXc + h.QjPtcdCj + h.QjPtcdLx + h.QjPtcdHjls) * 0.1m) * rate;
|
||||
var jjCounts = new[] { h.Jj95, h.Jj90, h.Jj85, h.Jj80, h.Jj75, h.Jj70, h.Jj65, h.Jj60 };
|
||||
for (var i = 0; i < jjCounts.Length; i++) jiejingDeduct += jjCounts[i] * (i + 1) * rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
q.Saozhe = siliangDen > 0 ? Math.Round(jianliangNum * 100m / siliangDen, 0, MidpointRounding.AwayFromZero)
|
||||
: cfg.SaoZhe;
|
||||
q.Erdu = Math.Round(erduSum * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.Sandu = Math.Round(sanduSum * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.CenterNum = Math.Round(q.CenterNum * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.YexianNum = Math.Round(q.YexianNum * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.QingjiePianshu = Math.Round((qjTdc + qjDc + qjCj) * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.JiejingPianshu = Math.Round((jj85 + jj80 + jj75 + jj70) * half, 2, MidpointRounding.AwayFromZero);
|
||||
q.QingjieKouKuan = (qjTdc * 2m + qjDc * 0.5m + qjCj * 2m) * half;
|
||||
q.JiejingKouKuan = (jj85 * 0.2m + jj80 * 1m + jj75 * 2m + jj70 * 5m) * half;
|
||||
q.YexianKouKuan = CalYeXianKouKuan(ctx, cfg.Guige, q.YexianNum);
|
||||
|
||||
q.Junfangcha = junfangchaCnt > 0 ? Math.Round(junfangchaSum / junfangchaCnt, 2) : 0;
|
||||
q.Zongcha = junfangchaCnt > 0 ? Math.Round(zongchaSum / junfangchaCnt, 2) : 0;
|
||||
q.QingjieFen = pianshuSum > 0
|
||||
? Math.Round((pianshuSum - qingjieDeduct) * 100m / pianshuSum, 2, MidpointRounding.AwayFromZero) : 100m;
|
||||
q.JiejingFen = pianshuSum > 0
|
||||
? Math.Round((pianshuSum * 100m - jiejingDeduct * 5m) / pianshuSum, 2, MidpointRounding.AwayFromZero) : 100m;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/// <summary>车台看台比例 = 本人该台工时 / 该台所有看台人工时之和</summary>
|
||||
private decimal ChetaiRate(CalcContext ctx, DateTime date, int jizu, int chetaihao, KtjlDcg k)
|
||||
{
|
||||
var same = ctx.DcgKtjl.Where(x => x.Date.Date == date && x.Jizu == jizu && x.Banci == k.Banci
|
||||
&& x.ChetaiStart <= chetaihao && x.ChetaiEnd >= chetaihao).ToList();
|
||||
var sum = same.Sum(x => x.Hours);
|
||||
return sum > 0 ? k.Hours / sum : 0m;
|
||||
}
|
||||
|
||||
/// <summary>野纤扣款:按规格取挡车纤度奖扣表,≤2 条取扣款最大的 2 条求和</summary>
|
||||
private decimal CalYeXianKouKuan(CalcContext ctx, string guige, decimal yexianNum)
|
||||
{
|
||||
if (yexianNum <= 0) return 0m;
|
||||
var list = ctx.YeXianJiangKou(guige);
|
||||
if (list.Count == 0) return 0m;
|
||||
var items = ExpandCount(yexianNum, list);
|
||||
if (items.Count >= 2) return items.OrderByDescending(i => i.KouKuan).Take(2).Sum(i => i.KouKuan);
|
||||
return items.Sum(i => i.KouKuan);
|
||||
}
|
||||
|
||||
/// <summary>按数量展开:整数部分逐条取,小数部分按最后一条比例折算</summary>
|
||||
private static List<DangCheXianDuJiangKou> ExpandCount(decimal count, List<DangCheXianDuJiangKou> list)
|
||||
{
|
||||
var result = new List<DangCheXianDuJiangKou>();
|
||||
var intPart = (int)Math.Floor(count);
|
||||
var frac = count - intPart;
|
||||
for (var i = 0; i < intPart; i++) result.Add(list[i % list.Count]);
|
||||
if (frac > 0) result.Add(list[intPart % list.Count]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== 内部:等级 ====================
|
||||
|
||||
/// <summary>挡车工等级:木桶短板法,六项各自定级后取最低分</summary>
|
||||
private (string Dengji, decimal Dengjifen) CalDengJi(CalcContext ctx, string guige, double piancha,
|
||||
double dacha, decimal qingjie, decimal jiejing, decimal erdu, decimal sandu, ConfGyzk cfg)
|
||||
{
|
||||
var zbs = ctx.Djzb.Where(z => z.Guige == guige).ToList();
|
||||
if (zbs.Count == 0) return (cfg.QsDengji, cfg.QsDengjifen);
|
||||
|
||||
var candidates = new List<ShengsiDingjizhibiao>();
|
||||
AddBest(candidates, zbs.Where(z => z.Piancha >= piancha));
|
||||
AddBest(candidates, zbs.Where(z => z.Dacha >= dacha));
|
||||
AddBest(candidates, zbs.Where(z => z.Qingjie <= (double)qingjie));
|
||||
AddBest(candidates, zbs.Where(z => z.Jiejing <= (double)jiejing));
|
||||
AddBest(candidates, zbs.Where(z => z.Erdu >= (double)erdu));
|
||||
AddBest(candidates, zbs.Where(z => z.Sandu >= (double)sandu));
|
||||
|
||||
if (candidates.Count == 0) return (cfg.QsDengji, cfg.QsDengjifen);
|
||||
var worst = candidates.OrderBy(z => z.GradeScore).First();
|
||||
return (worst.Grade, (decimal)worst.GradeScore);
|
||||
}
|
||||
|
||||
private static void AddBest(List<ShengsiDingjizhibiao> target, IEnumerable<ShengsiDingjizhibiao> src)
|
||||
{
|
||||
var best = src.OrderByDescending(z => z.GradeScore).FirstOrDefault();
|
||||
if (best != null) target.Add(best);
|
||||
}
|
||||
|
||||
/// <summary>车头工等级:按挡车工丝量加权平均等级分后回落取整档</summary>
|
||||
private (string Dengji, decimal Dengjifen) CalCtgDengji(CalcContext ctx, List<CalcLdcct> dcgRows,
|
||||
DateTime date, int jizu, long gyzkId, string guige, ConfGyzk cfg)
|
||||
{
|
||||
var related = dcgRows.Where(x => x.Date.Date == date && x.Jizu == jizu && x.GyzkId == gyzkId).ToList();
|
||||
var siliangSum = related.Sum(x => x.ClSiliang);
|
||||
if (siliangSum <= 0) return (cfg.QsDengji, cfg.QsDengjifen);
|
||||
|
||||
var weighted = related.Sum(x => x.ClSiliang * x.Dengjifen) / siliangSum;
|
||||
var zbs = ctx.Djzb.Where(z => z.Guige == guige && (decimal)z.GradeScore <= weighted)
|
||||
.OrderByDescending(z => z.GradeScore).FirstOrDefault();
|
||||
return zbs != null ? (zbs.Grade, (decimal)zbs.GradeScore) : (cfg.QsDengji, cfg.QsDengjifen);
|
||||
}
|
||||
|
||||
// ==================== 内部:单价 / 金额 ====================
|
||||
|
||||
/// <summary>按绪数档取岗位基数金额:<60→50档,<70→60档,<100→70档,否则 100 档</summary>
|
||||
private static decimal GetDcgDanJiaBase(decimal xushu, ConfDcg conf)
|
||||
{
|
||||
if (xushu < 60m) return conf.JineJisuanjishu50;
|
||||
if (xushu < 70m) return conf.JineJisuanjishu60;
|
||||
if (xushu < 100m) return conf.JineJisuanjishu70;
|
||||
return conf.JineJisuanjishu100;
|
||||
}
|
||||
|
||||
/// <summary>缫折考核:±2kg 死区不奖不扣,超出部分按封顶 clamp,每 1kg 每 100kg 丝 奖扣 price 元</summary>
|
||||
private static decimal CalJineSaozhe(decimal saoZheCfg, decimal saozhe, decimal siliang, int cap, decimal price)
|
||||
{
|
||||
if (Math.Abs(saoZheCfg - saozhe) <= SaozheDeadZone) return 0m;
|
||||
var diff = saoZheCfg - saozhe;
|
||||
diff = diff < 0 ? diff + SaozheDeadZone : diff - SaozheDeadZone;
|
||||
if (diff > cap) diff = cap;
|
||||
if (diff < -cap) diff = -cap;
|
||||
return Math.Round(diff * (siliang / 1000m / 100m) * price, 2, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
private static string BanciName(int banci) => banci switch { 1 => "甲", 2 => "乙", _ => banci.ToString() };
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
using F9WebAiTest.Application.Common;
|
||||
using F9WebAiTest.Application.Dtos.PayRoll;
|
||||
using F9WebAiTest.Domain.Common;
|
||||
using F9WebAiTest.Domain.Entities.PayRoll;
|
||||
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
|
||||
using SysEmp = F9WebAiTest.Domain.Entities.SYS.Employees;
|
||||
using SysWt = F9WebAiTest.Domain.Entities.SYS.WorkTypes;
|
||||
|
||||
namespace F9WebAiTest.Application.Services.PayRoll;
|
||||
|
||||
/// <summary>薪资配置-账期(CONFZQ):考勤统计的「前缫出勤天数」来源</summary>
|
||||
public interface IConfZqService
|
||||
{
|
||||
Task<List<ConfZqDto>> GetListAsync(int? year);
|
||||
Task<ConfZqDto> GetByYearMonthAsync(int year, int month);
|
||||
Task<long> SaveAsync(ConfZqDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
/// <summary>薪资配置-职工(CONFEMPLOYEE):法定假小时数 / 是否学工</summary>
|
||||
public interface IConfEmployeeService
|
||||
{
|
||||
Task<List<ConfEmployeeDto>> GetListAsync(long? employeeId, long? worktypeId);
|
||||
Task<long> SaveAsync(ConfEmployeeDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
/// <summary>岗位胜任考核:考核结果决定加班费单价档位</summary>
|
||||
public interface IGwsrkhService
|
||||
{
|
||||
Task<List<GwsrkhDto>> GetListAsync(int year, int month, long depId);
|
||||
Task<long> SaveAsync(GwsrkhDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
public class ConfZqService : IConfZqService
|
||||
{
|
||||
private readonly IRepository<ConfZq> _repo;
|
||||
public ConfZqService(IRepository<ConfZq> repo) => _repo = repo;
|
||||
|
||||
public async Task<List<ConfZqDto>> GetListAsync(int? year)
|
||||
{
|
||||
var all = await _repo.GetAllAsync();
|
||||
var q = all.AsQueryable();
|
||||
if (year.HasValue) q = q.Where(x => x.Year == year.Value);
|
||||
return q.ToList().OrderByDescending(x => x.Year).ThenByDescending(x => x.Month)
|
||||
.Select(x => new ConfZqDto
|
||||
{
|
||||
Id = x.Id, Year = x.Year, Month = x.Month,
|
||||
QsQuanqinDays = x.QsQuanqinDays, Memo = x.Memo ?? ""
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<ConfZqDto> GetByYearMonthAsync(int year, int month)
|
||||
{
|
||||
var hit = await _repo.FirstOrDefaultAsync(x => x.Year == year && x.Month == month);
|
||||
return hit == null
|
||||
? new ConfZqDto { Year = year, Month = month }
|
||||
: new ConfZqDto { Id = hit.Id, Year = hit.Year, Month = hit.Month, QsQuanqinDays = hit.QsQuanqinDays, Memo = hit.Memo ?? "" };
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(ConfZqDto dto)
|
||||
{
|
||||
if (dto.Year <= 0 || dto.Month <= 0) throw new ServiceException("请填写年度与月份");
|
||||
var exist = await _repo.FirstOrDefaultAsync(x => x.Year == dto.Year && x.Month == dto.Month && x.Id != dto.Id);
|
||||
if (exist != null) throw new ServiceException($"{dto.Year} 年 {dto.Month} 月的账期薪资配置已存在");
|
||||
|
||||
ConfZq entity;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
entity = await _repo.GetByIdAsync(dto.Id);
|
||||
if (entity == null) throw new ServiceException("配置不存在", 404);
|
||||
}
|
||||
else entity = new ConfZq();
|
||||
|
||||
entity.Year = dto.Year;
|
||||
entity.Month = dto.Month;
|
||||
entity.QsQuanqinDays = dto.QsQuanqinDays;
|
||||
entity.Memo = dto.Memo ?? "";
|
||||
|
||||
if (dto.Id > 0) await _repo.UpdateAsync(entity); else await _repo.AddAsync(entity);
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("配置不存在", 404);
|
||||
await _repo.DeleteAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfEmployeeService : IConfEmployeeService
|
||||
{
|
||||
private readonly IRepository<ConfEmployee> _repo;
|
||||
private readonly IRepository<SysEmp.Employee> _empRepo;
|
||||
private readonly IRepository<SysWt.WorkType> _wtRepo;
|
||||
|
||||
public ConfEmployeeService(IRepository<ConfEmployee> repo, IRepository<SysEmp.Employee> empRepo,
|
||||
IRepository<SysWt.WorkType> wtRepo)
|
||||
{
|
||||
_repo = repo; _empRepo = empRepo; _wtRepo = wtRepo;
|
||||
}
|
||||
|
||||
public async Task<List<ConfEmployeeDto>> GetListAsync(long? employeeId, long? worktypeId)
|
||||
{
|
||||
var all = await _repo.GetAllAsync();
|
||||
var q = all.AsQueryable();
|
||||
if (employeeId.HasValue && employeeId.Value > 0) q = q.Where(x => x.EmployeeId == employeeId.Value);
|
||||
if (worktypeId.HasValue && worktypeId.Value > 0) q = q.Where(x => x.WorktypeId == worktypeId.Value);
|
||||
var emps = (await _empRepo.GetAllAsync()).ToDictionary(e => e.Id);
|
||||
var wts = (await _wtRepo.GetAllAsync()).ToDictionary(w => w.Id, w => w.WorkName);
|
||||
return q.ToList().OrderBy(x => x.EmployeeId).Select(x => new ConfEmployeeDto
|
||||
{
|
||||
Id = x.Id,
|
||||
EmployeeId = x.EmployeeId,
|
||||
EmployeeCode = emps.TryGetValue(x.EmployeeId, out var e) ? (e.Code ?? "") : "",
|
||||
EmployeeName = emps.TryGetValue(x.EmployeeId, out var e2) ? (e2.Name ?? "") : "",
|
||||
WorktypeId = x.WorktypeId,
|
||||
WorktypeName = wts.TryGetValue(x.WorktypeId, out var wn) ? wn : "",
|
||||
HoursFadingBz = x.HoursFadingBz,
|
||||
HoursFadingGz = x.HoursFadingGz,
|
||||
IsXuegong = x.IsXuegong,
|
||||
Memo = x.Memo ?? ""
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(ConfEmployeeDto dto)
|
||||
{
|
||||
if (dto.EmployeeId <= 0) throw new ServiceException("请选择职工");
|
||||
var exist = await _repo.FirstOrDefaultAsync(x => x.EmployeeId == dto.EmployeeId && x.WorktypeId == dto.WorktypeId && x.Id != dto.Id);
|
||||
if (exist != null) throw new ServiceException("该职工该工种的薪资配置已存在");
|
||||
|
||||
ConfEmployee entity;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
entity = await _repo.GetByIdAsync(dto.Id);
|
||||
if (entity == null) throw new ServiceException("配置不存在", 404);
|
||||
}
|
||||
else entity = new ConfEmployee();
|
||||
|
||||
entity.EmployeeId = dto.EmployeeId;
|
||||
entity.WorktypeId = dto.WorktypeId;
|
||||
entity.HoursFadingBz = dto.HoursFadingBz;
|
||||
entity.HoursFadingGz = dto.HoursFadingGz;
|
||||
entity.IsXuegong = dto.IsXuegong;
|
||||
entity.Memo = dto.Memo ?? "";
|
||||
|
||||
if (dto.Id > 0) await _repo.UpdateAsync(entity); else await _repo.AddAsync(entity);
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("配置不存在", 404);
|
||||
await _repo.DeleteAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class GwsrkhService : IGwsrkhService
|
||||
{
|
||||
private readonly IRepository<Gwsrkh> _repo;
|
||||
private readonly IRepository<SysDept.Department> _depRepo;
|
||||
private readonly IRepository<SysEmp.Employee> _empRepo;
|
||||
|
||||
public GwsrkhService(IRepository<Gwsrkh> repo, IRepository<SysDept.Department> depRepo,
|
||||
IRepository<SysEmp.Employee> empRepo)
|
||||
{
|
||||
_repo = repo; _depRepo = depRepo; _empRepo = empRepo;
|
||||
}
|
||||
|
||||
public async Task<List<GwsrkhDto>> GetListAsync(int year, int month, long depId)
|
||||
{
|
||||
var all = await _repo.GetAllAsync();
|
||||
var q = all.AsQueryable().Where(x => x.Year == year && x.Month == month);
|
||||
if (depId > 0) q = q.Where(x => x.DepId == depId);
|
||||
var depts = (await _depRepo.GetAllAsync()).ToDictionary(d => d.Id, d => d.Name);
|
||||
var emps = (await _empRepo.GetAllAsync()).ToDictionary(e => e.Id);
|
||||
return q.ToList().OrderBy(x => x.EmployeeId).Select(x => new GwsrkhDto
|
||||
{
|
||||
Id = x.Id, Year = x.Year, Month = x.Month,
|
||||
DepId = x.DepId, DepName = depts.TryGetValue(x.DepId, out var dn) ? dn : "",
|
||||
EmployeeId = x.EmployeeId,
|
||||
EmployeeCode = emps.TryGetValue(x.EmployeeId, out var e) ? (e.Code ?? "") : "",
|
||||
EmployeeName = emps.TryGetValue(x.EmployeeId, out var e2) ? (e2.Name ?? "") : "",
|
||||
KhJieguo = x.KhJieguo ?? "",
|
||||
Memo = x.Memo ?? ""
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(GwsrkhDto dto)
|
||||
{
|
||||
if (dto.EmployeeId <= 0) throw new ServiceException("请选择职工");
|
||||
if (string.IsNullOrWhiteSpace(dto.KhJieguo)) throw new ServiceException("请选择考核结果");
|
||||
var exist = await _repo.FirstOrDefaultAsync(x => x.Year == dto.Year && x.Month == dto.Month
|
||||
&& x.EmployeeId == dto.EmployeeId && x.Id != dto.Id);
|
||||
if (exist != null) throw new ServiceException("该职工本月考核结果已存在");
|
||||
|
||||
Gwsrkh entity;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
entity = await _repo.GetByIdAsync(dto.Id);
|
||||
if (entity == null) throw new ServiceException("记录不存在", 404);
|
||||
}
|
||||
else entity = new Gwsrkh();
|
||||
|
||||
entity.Year = dto.Year;
|
||||
entity.Month = dto.Month;
|
||||
entity.DepId = dto.DepId;
|
||||
entity.EmployeeId = dto.EmployeeId;
|
||||
entity.KhJieguo = dto.KhJieguo.Trim();
|
||||
entity.Memo = dto.Memo ?? "";
|
||||
|
||||
if (dto.Id > 0) await _repo.UpdateAsync(entity); else await _repo.AddAsync(entity);
|
||||
return entity.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("记录不存在", 404);
|
||||
await _repo.DeleteAsync(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
using F9WebAiTest.Application.Common;
|
||||
using F9WebAiTest.Application.Dtos.PayRoll;
|
||||
using F9WebAiTest.Domain.Common;
|
||||
using F9WebAiTest.Domain.Entities.Base;
|
||||
using F9WebAiTest.Domain.Entities.PayRoll;
|
||||
using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments;
|
||||
using SysWt = F9WebAiTest.Domain.Entities.SYS.WorkTypes;
|
||||
|
||||
namespace F9WebAiTest.Application.Services.PayRoll;
|
||||
|
||||
// 薪资计算依赖的 5 套配置(对应 F9 PAYROLL 下的 CONFGYZK / CONFGZ / CONFDCG / DCXDJK / XinZiJiaGePeiZhi)
|
||||
|
||||
// ==================== 薪资配置-工艺庄口 ====================
|
||||
|
||||
public interface IConfGyzkService
|
||||
{
|
||||
Task<List<ConfGyzkListItemDto>> GetListAsync(int? year, int? month);
|
||||
Task<ConfGyzkSaveDto> GetForEditAsync(long id);
|
||||
Task<long> SaveAsync(ConfGyzkSaveDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
public class ConfGyzkService : IConfGyzkService
|
||||
{
|
||||
private readonly IRepository<ConfGyzk> _repo;
|
||||
private readonly IRepository<CraftZhuangKou> _zkRepo;
|
||||
|
||||
public ConfGyzkService(IRepository<ConfGyzk> repo, IRepository<CraftZhuangKou> zkRepo)
|
||||
{
|
||||
_repo = repo;
|
||||
_zkRepo = zkRepo;
|
||||
}
|
||||
|
||||
public async Task<List<ConfGyzkListItemDto>> GetListAsync(int? year, int? month)
|
||||
{
|
||||
var all = await _repo.GetAllAsync();
|
||||
var q = all.AsQueryable();
|
||||
if (year.HasValue) q = q.Where(x => x.Year == year.Value);
|
||||
if (month.HasValue) q = q.Where(x => x.Month == month.Value);
|
||||
var items = q.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).ThenBy(x => x.GyzkId).ToList();
|
||||
|
||||
var zks = await _zkRepo.GetAllAsync();
|
||||
var zkDict = zks.ToDictionary(z => z.Id, z => z.ZhuangKouName);
|
||||
|
||||
return items.Select(x => new ConfGyzkListItemDto
|
||||
{
|
||||
Id = x.Id, Year = x.Year, Month = x.Month, GyzkId = x.GyzkId,
|
||||
GyzkName = zkDict.GetValueOrDefault(x.GyzkId, ""),
|
||||
Guige = x.Guige, QsTaichan = x.QsTaichan, QsDengji = x.QsDengji, QsDengjifen = x.QsDengjifen,
|
||||
SaoZhe = x.SaoZhe, MeiTongJianLiang = x.MeiTongJianLiang, LuoSiTongShu = x.LuoSiTongShu,
|
||||
MeiCheSiLiang = x.MeiCheSiLiang, DcgJijianXishu = x.DcgJijianXishu, CtgJijianXishu = x.CtgJijianXishu,
|
||||
GyzkLtwxKs = x.GyzkLtwxKs, GyzkLtwxl = x.GyzkLtwxl, XjChanliangPrice = x.XjChanliangPrice
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<ConfGyzkSaveDto> GetForEditAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("工艺庄口薪资配置不存在或已删除", 404);
|
||||
return new ConfGyzkSaveDto
|
||||
{
|
||||
Id = e.Id, Year = e.Year, Month = e.Month, GyzkId = e.GyzkId, Guige = e.Guige,
|
||||
QsTaichan = e.QsTaichan, QsDengji = e.QsDengji, QsDengjifen = e.QsDengjifen, SaoZhe = e.SaoZhe,
|
||||
MeiTongJianLiang = e.MeiTongJianLiang, LuoSiTongShu = e.LuoSiTongShu, MeiCheSiLiang = e.MeiCheSiLiang,
|
||||
DcgJijianXishu = e.DcgJijianXishu, CtgJijianXishu = e.CtgJijianXishu,
|
||||
GyzkLtwxKs = e.GyzkLtwxKs, GyzkLtwxl = e.GyzkLtwxl, XjChanliangPrice = e.XjChanliangPrice
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(ConfGyzkSaveDto dto)
|
||||
{
|
||||
if (dto.GyzkId == 0) throw new ServiceException("请选择工艺庄口");
|
||||
if (dto.Year <= 0 || dto.Month <= 0) throw new ServiceException("年度/月份无效");
|
||||
|
||||
ConfGyzk e;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
e = await _repo.GetByIdAsync(dto.Id);
|
||||
if (e == null) throw new ServiceException("工艺庄口薪资配置不存在或已删除", 404);
|
||||
var dup = await _repo.FirstOrDefaultAsync(x => x.Id != dto.Id && x.Year == dto.Year
|
||||
&& x.Month == dto.Month && x.GyzkId == dto.GyzkId);
|
||||
if (dup != null) throw new ServiceException("该年度月份已存在此庄口的配置!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dup = await _repo.AnyAsync(x => x.Year == dto.Year && x.Month == dto.Month && x.GyzkId == dto.GyzkId);
|
||||
if (dup) throw new ServiceException("该年度月份已存在此庄口的配置!");
|
||||
e = new ConfGyzk();
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
|
||||
e.Year = dto.Year;
|
||||
e.Month = dto.Month;
|
||||
e.GyzkId = dto.GyzkId;
|
||||
e.Guige = dto.Guige ?? "";
|
||||
e.QsTaichan = dto.QsTaichan;
|
||||
e.QsDengji = dto.QsDengji ?? "";
|
||||
e.QsDengjifen = dto.QsDengjifen;
|
||||
e.SaoZhe = dto.SaoZhe;
|
||||
e.MeiTongJianLiang = dto.MeiTongJianLiang;
|
||||
e.LuoSiTongShu = dto.LuoSiTongShu;
|
||||
e.MeiCheSiLiang = dto.MeiCheSiLiang;
|
||||
e.DcgJijianXishu = dto.DcgJijianXishu;
|
||||
e.CtgJijianXishu = dto.CtgJijianXishu;
|
||||
e.GyzkLtwxKs = dto.GyzkLtwxKs;
|
||||
e.GyzkLtwxl = dto.GyzkLtwxl;
|
||||
e.XjChanliangPrice = dto.XjChanliangPrice;
|
||||
|
||||
await _repo.UpdateAsync(e);
|
||||
return e.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("工艺庄口薪资配置不存在或已删除", 404);
|
||||
await _repo.HardDeleteAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 薪资配置-工种 ====================
|
||||
|
||||
public interface IConfGzService
|
||||
{
|
||||
Task<List<ConfGzListItemDto>> GetListAsync();
|
||||
Task<ConfGzSaveDto> GetForEditAsync(long id);
|
||||
Task<long> SaveAsync(ConfGzSaveDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
public class ConfGzService : IConfGzService
|
||||
{
|
||||
private readonly IRepository<ConfGz> _repo;
|
||||
private readonly IRepository<SysWt.WorkType> _wtRepo;
|
||||
|
||||
public ConfGzService(IRepository<ConfGz> repo, IRepository<SysWt.WorkType> wtRepo)
|
||||
{
|
||||
_repo = repo;
|
||||
_wtRepo = wtRepo;
|
||||
}
|
||||
|
||||
public async Task<List<ConfGzListItemDto>> GetListAsync()
|
||||
{
|
||||
var items = await _repo.GetAllAsync();
|
||||
var wts = await _wtRepo.GetAllAsync();
|
||||
var wtDict = wts.ToDictionary(w => w.Id, w => w.WorkName);
|
||||
return items.Select(x => ToDto(x, wtDict)).ToList();
|
||||
}
|
||||
|
||||
public async Task<ConfGzSaveDto> GetForEditAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("工种薪资配置不存在或已删除", 404);
|
||||
return FromEntity(e);
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(ConfGzSaveDto dto)
|
||||
{
|
||||
if (dto.WorkTypeId == 0) throw new ServiceException("请选择工种");
|
||||
|
||||
ConfGz e;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
e = await _repo.GetByIdAsync(dto.Id);
|
||||
if (e == null) throw new ServiceException("工种薪资配置不存在或已删除", 404);
|
||||
var dup = await _repo.FirstOrDefaultAsync(x => x.Id != dto.Id && x.WorkTypeId == dto.WorkTypeId);
|
||||
if (dup != null) throw new ServiceException("该工种已存在薪资配置!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dup = await _repo.AnyAsync(x => x.WorkTypeId == dto.WorkTypeId);
|
||||
if (dup) throw new ServiceException("该工种已存在薪资配置!");
|
||||
e = new ConfGz();
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
Apply(e, dto);
|
||||
await _repo.UpdateAsync(e);
|
||||
return e.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("工种薪资配置不存在或已删除", 404);
|
||||
await _repo.HardDeleteAsync(e);
|
||||
}
|
||||
|
||||
private static ConfGzListItemDto ToDto(ConfGz x, Dictionary<long, string> wtDict) => new()
|
||||
{
|
||||
Id = x.Id, WorkTypeId = x.WorkTypeId, WorkTypeName = wtDict.GetValueOrDefault(x.WorkTypeId, ""),
|
||||
HoursPerday = x.HoursPerday, QqDaysStandard = x.QqDaysStandard, QqHoursMaxQj = x.QqHoursMaxQj,
|
||||
QqHoursDkMinjiaban = x.QqHoursDkMinjiaban, QqHoursDkQingjia = x.QqHoursDkQingjia,
|
||||
XgJineQuanqin = x.XgJineQuanqin, XgJineGangwei = x.XgJineGangwei, JineNiangong = x.JineNiangong,
|
||||
JineQuanqin = x.JineQuanqin, JineGangwei = x.JineGangwei, JineYuekhJixiao = x.JineYuekhJixiao,
|
||||
JineGwkh = x.JineGwkh, JineYueticheng = x.JineYueticheng, JineJtkhYear = x.JineJtkhYear,
|
||||
JineJisuanjishu = x.JineJisuanjishu, JineYeban = x.JineYeban, JineJiaotongButie = x.JineJiaotongButie,
|
||||
LiudongJineGuding = x.LiudongJineGuding, JiaqiJineKuangongKk = x.JiaqiJineKuangongKk,
|
||||
JiaqiJineFadingGz = x.JiaqiJineFadingGz, JiaqiJineFadingBz = x.JiaqiJineFadingBz,
|
||||
JiaqiJineHunjiaBz = x.JiaqiJineHunjiaBz, JiaqiJineSangjiaBz = x.JiaqiJineSangjiaBz,
|
||||
JiaqiJineBingjiaBz = x.JiaqiJineBingjiaBz, JiaqiJineLunxiuBz = x.JiaqiJineLunxiuBz,
|
||||
JiabanJineBz = x.JiabanJineBz, Jiaqi_Jine_TiaoxiuBz = x.Jiaqi_Jine_TiaoxiuBz,
|
||||
Jiaqi_Jine_NianjiaBz = x.Jiaqi_Jine_NianjiaBz, GwsrkhJineQianhege = x.GwsrkhJineQianhege,
|
||||
GwsrkhJineQiwang = x.GwsrkhJineQiwang, GwsrkhJineHege = x.GwsrkhJineHege,
|
||||
GwsrkhJineShengren = x.GwsrkhJineShengren, GwsrkhJineChaoshengren = x.GwsrkhJineChaoshengren,
|
||||
Jiaban_GwsrkhJineQianhege = x.Jiaban_GwsrkhJineQianhege, Jiaban_GwsrkhJineQiwang = x.Jiaban_GwsrkhJineQiwang,
|
||||
Jiaban_GwsrkhJineHege = x.Jiaban_GwsrkhJineHege, Jiaban_GwsrkhJineShengren = x.Jiaban_GwsrkhJineShengren,
|
||||
Jiaban_GwsrkhJineChaoshengren = x.Jiaban_GwsrkhJineChaoshengren
|
||||
};
|
||||
|
||||
private static ConfGzSaveDto FromEntity(ConfGz x) => new()
|
||||
{
|
||||
Id = x.Id, WorkTypeId = x.WorkTypeId, HoursPerday = x.HoursPerday, QqDaysStandard = x.QqDaysStandard,
|
||||
QqHoursMaxQj = x.QqHoursMaxQj, QqHoursDkMinjiaban = x.QqHoursDkMinjiaban, QqHoursDkQingjia = x.QqHoursDkQingjia,
|
||||
XgJineQuanqin = x.XgJineQuanqin, XgJineGangwei = x.XgJineGangwei, JineNiangong = x.JineNiangong,
|
||||
JineQuanqin = x.JineQuanqin, JineGangwei = x.JineGangwei, JineYuekhJixiao = x.JineYuekhJixiao,
|
||||
JineGwkh = x.JineGwkh, JineYueticheng = x.JineYueticheng, JineJtkhYear = x.JineJtkhYear,
|
||||
JineJisuanjishu = x.JineJisuanjishu, JineYeban = x.JineYeban, JineJiaotongButie = x.JineJiaotongButie,
|
||||
LiudongJineGuding = x.LiudongJineGuding, JiaqiJineKuangongKk = x.JiaqiJineKuangongKk,
|
||||
JiaqiJineFadingGz = x.JiaqiJineFadingGz, JiaqiJineFadingBz = x.JiaqiJineFadingBz,
|
||||
JiaqiJineHunjiaBz = x.JiaqiJineHunjiaBz, JiaqiJineSangjiaBz = x.JiaqiJineSangjiaBz,
|
||||
JiaqiJineBingjiaBz = x.JiaqiJineBingjiaBz, JiaqiJineLunxiuBz = x.JiaqiJineLunxiuBz,
|
||||
JiabanJineBz = x.JiabanJineBz, Jiaqi_Jine_TiaoxiuBz = x.Jiaqi_Jine_TiaoxiuBz,
|
||||
Jiaqi_Jine_NianjiaBz = x.Jiaqi_Jine_NianjiaBz, GwsrkhJineQianhege = x.GwsrkhJineQianhege,
|
||||
GwsrkhJineQiwang = x.GwsrkhJineQiwang, GwsrkhJineHege = x.GwsrkhJineHege,
|
||||
GwsrkhJineShengren = x.GwsrkhJineShengren, GwsrkhJineChaoshengren = x.GwsrkhJineChaoshengren,
|
||||
Jiaban_GwsrkhJineQianhege = x.Jiaban_GwsrkhJineQianhege, Jiaban_GwsrkhJineQiwang = x.Jiaban_GwsrkhJineQiwang,
|
||||
Jiaban_GwsrkhJineHege = x.Jiaban_GwsrkhJineHege, Jiaban_GwsrkhJineShengren = x.Jiaban_GwsrkhJineShengren,
|
||||
Jiaban_GwsrkhJineChaoshengren = x.Jiaban_GwsrkhJineChaoshengren
|
||||
};
|
||||
|
||||
private static void Apply(ConfGz e, ConfGzSaveDto d)
|
||||
{
|
||||
e.WorkTypeId = d.WorkTypeId;
|
||||
e.HoursPerday = d.HoursPerday; e.QqDaysStandard = d.QqDaysStandard;
|
||||
e.QqHoursMaxQj = d.QqHoursMaxQj; e.QqHoursDkMinjiaban = d.QqHoursDkMinjiaban;
|
||||
e.QqHoursDkQingjia = d.QqHoursDkQingjia; e.XgJineQuanqin = d.XgJineQuanqin;
|
||||
e.XgJineGangwei = d.XgJineGangwei; e.JineNiangong = d.JineNiangong;
|
||||
e.JineQuanqin = d.JineQuanqin; e.JineGangwei = d.JineGangwei;
|
||||
e.JineYuekhJixiao = d.JineYuekhJixiao; e.JineGwkh = d.JineGwkh;
|
||||
e.JineYueticheng = d.JineYueticheng; e.JineJtkhYear = d.JineJtkhYear;
|
||||
e.JineJisuanjishu = d.JineJisuanjishu; e.JineYeban = d.JineYeban;
|
||||
e.JineJiaotongButie = d.JineJiaotongButie; e.LiudongJineGuding = d.LiudongJineGuding;
|
||||
e.JiaqiJineKuangongKk = d.JiaqiJineKuangongKk; e.JiaqiJineFadingGz = d.JiaqiJineFadingGz;
|
||||
e.JiaqiJineFadingBz = d.JiaqiJineFadingBz; e.JiaqiJineHunjiaBz = d.JiaqiJineHunjiaBz;
|
||||
e.JiaqiJineSangjiaBz = d.JiaqiJineSangjiaBz; e.JiaqiJineBingjiaBz = d.JiaqiJineBingjiaBz;
|
||||
e.JiaqiJineLunxiuBz = d.JiaqiJineLunxiuBz; e.JiabanJineBz = d.JiabanJineBz;
|
||||
e.Jiaqi_Jine_TiaoxiuBz = d.Jiaqi_Jine_TiaoxiuBz; e.Jiaqi_Jine_NianjiaBz = d.Jiaqi_Jine_NianjiaBz;
|
||||
e.GwsrkhJineQianhege = d.GwsrkhJineQianhege; e.GwsrkhJineQiwang = d.GwsrkhJineQiwang;
|
||||
e.GwsrkhJineHege = d.GwsrkhJineHege; e.GwsrkhJineShengren = d.GwsrkhJineShengren;
|
||||
e.GwsrkhJineChaoshengren = d.GwsrkhJineChaoshengren;
|
||||
e.Jiaban_GwsrkhJineQianhege = d.Jiaban_GwsrkhJineQianhege;
|
||||
e.Jiaban_GwsrkhJineQiwang = d.Jiaban_GwsrkhJineQiwang;
|
||||
e.Jiaban_GwsrkhJineHege = d.Jiaban_GwsrkhJineHege;
|
||||
e.Jiaban_GwsrkhJineShengren = d.Jiaban_GwsrkhJineShengren;
|
||||
e.Jiaban_GwsrkhJineChaoshengren = d.Jiaban_GwsrkhJineChaoshengren;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 薪资配置-挡车/车头岗位 ====================
|
||||
|
||||
public interface IConfDcgService
|
||||
{
|
||||
Task<List<ConfDcgListItemDto>> GetListAsync();
|
||||
Task<ConfDcgSaveDto> GetForEditAsync(long id);
|
||||
Task<long> SaveAsync(ConfDcgSaveDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
public class ConfDcgService : IConfDcgService
|
||||
{
|
||||
private readonly IRepository<ConfDcg> _repo;
|
||||
private readonly IRepository<SysDept.Department> _depRepo;
|
||||
|
||||
public ConfDcgService(IRepository<ConfDcg> repo, IRepository<SysDept.Department> depRepo)
|
||||
{
|
||||
_repo = repo;
|
||||
_depRepo = depRepo;
|
||||
}
|
||||
|
||||
public async Task<List<ConfDcgListItemDto>> GetListAsync()
|
||||
{
|
||||
var items = await _repo.GetAllAsync();
|
||||
var deps = await _depRepo.GetAllAsync();
|
||||
var depDict = deps.ToDictionary(d => d.Id, d => d.Name);
|
||||
return items.Select(x => new ConfDcgListItemDto
|
||||
{
|
||||
Id = x.Id, DepId = x.DepId, DepName = depDict.GetValueOrDefault(x.DepId, ""),
|
||||
JineJisuanjishu50 = x.JineJisuanjishu50, JineJisuanjishu60 = x.JineJisuanjishu60,
|
||||
JineJisuanjishu70 = x.JineJisuanjishu70, JineJisuanjishu100 = x.JineJisuanjishu100,
|
||||
JineCtg = x.JineCtg
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<ConfDcgSaveDto> GetForEditAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("挡车岗位薪资配置不存在或已删除", 404);
|
||||
return new ConfDcgSaveDto
|
||||
{
|
||||
Id = e.Id, DepId = e.DepId, JineJisuanjishu50 = e.JineJisuanjishu50,
|
||||
JineJisuanjishu60 = e.JineJisuanjishu60, JineJisuanjishu70 = e.JineJisuanjishu70,
|
||||
JineJisuanjishu100 = e.JineJisuanjishu100, JineCtg = e.JineCtg
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(ConfDcgSaveDto dto)
|
||||
{
|
||||
if (dto.DepId == 0) throw new ServiceException("请选择部门");
|
||||
|
||||
ConfDcg e;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
e = await _repo.GetByIdAsync(dto.Id);
|
||||
if (e == null) throw new ServiceException("挡车岗位薪资配置不存在或已删除", 404);
|
||||
var dup = await _repo.FirstOrDefaultAsync(x => x.Id != dto.Id && x.DepId == dto.DepId);
|
||||
if (dup != null) throw new ServiceException("该部门已存在挡车岗位薪资配置!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dup = await _repo.AnyAsync(x => x.DepId == dto.DepId);
|
||||
if (dup) throw new ServiceException("该部门已存在挡车岗位薪资配置!");
|
||||
e = new ConfDcg();
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
e.DepId = dto.DepId;
|
||||
e.JineJisuanjishu50 = dto.JineJisuanjishu50;
|
||||
e.JineJisuanjishu60 = dto.JineJisuanjishu60;
|
||||
e.JineJisuanjishu70 = dto.JineJisuanjishu70;
|
||||
e.JineJisuanjishu100 = dto.JineJisuanjishu100;
|
||||
e.JineCtg = dto.JineCtg;
|
||||
await _repo.UpdateAsync(e);
|
||||
return e.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("挡车岗位薪资配置不存在或已删除", 404);
|
||||
await _repo.HardDeleteAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 挡车纤度奖扣 ====================
|
||||
|
||||
public interface IDcxdjkService
|
||||
{
|
||||
Task<List<DcxdjkListItemDto>> GetListAsync(string guige);
|
||||
Task<DcxdjkSaveDto> GetForEditAsync(long id);
|
||||
Task<long> SaveAsync(DcxdjkSaveDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
}
|
||||
|
||||
public class DcxdjkService : IDcxdjkService
|
||||
{
|
||||
private readonly IRepository<DangCheXianDuJiangKou> _repo;
|
||||
|
||||
public DcxdjkService(IRepository<DangCheXianDuJiangKou> repo) => _repo = repo;
|
||||
|
||||
public async Task<List<DcxdjkListItemDto>> GetListAsync(string guige)
|
||||
{
|
||||
var items = await _repo.GetAllAsync();
|
||||
var q = items.AsQueryable();
|
||||
if (!string.IsNullOrWhiteSpace(guige)) q = q.Where(x => x.GuiGe == guige);
|
||||
return q.OrderBy(x => x.GuiGe).ThenBy(x => x.XianDu).ToList()
|
||||
.Select(x => new DcxdjkListItemDto
|
||||
{
|
||||
Id = x.Id, GuiGe = x.GuiGe, XianDu = x.XianDu, JiangLi = x.JiangLi, KouKuan = x.KouKuan
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<DcxdjkSaveDto> GetForEditAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("挡车纤度奖扣不存在或已删除", 404);
|
||||
return new DcxdjkSaveDto { Id = e.Id, GuiGe = e.GuiGe, XianDu = e.XianDu, JiangLi = e.JiangLi, KouKuan = e.KouKuan };
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(DcxdjkSaveDto dto)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dto.GuiGe)) throw new ServiceException("请填写规格");
|
||||
|
||||
DangCheXianDuJiangKou e;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
e = await _repo.GetByIdAsync(dto.Id);
|
||||
if (e == null) throw new ServiceException("挡车纤度奖扣不存在或已删除", 404);
|
||||
var dup = await _repo.FirstOrDefaultAsync(x => x.Id != dto.Id && x.GuiGe == dto.GuiGe && x.XianDu == dto.XianDu);
|
||||
if (dup != null) throw new ServiceException("该规格已存在相同纤度的奖扣配置!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dup = await _repo.AnyAsync(x => x.GuiGe == dto.GuiGe && x.XianDu == dto.XianDu);
|
||||
if (dup) throw new ServiceException("该规格已存在相同纤度的奖扣配置!");
|
||||
e = new DangCheXianDuJiangKou();
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
e.GuiGe = dto.GuiGe.Trim();
|
||||
e.XianDu = dto.XianDu;
|
||||
e.JiangLi = dto.JiangLi;
|
||||
e.KouKuan = dto.KouKuan;
|
||||
await _repo.UpdateAsync(e);
|
||||
return e.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("挡车纤度奖扣不存在或已删除", 404);
|
||||
await _repo.HardDeleteAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 薪资价格配置 ====================
|
||||
|
||||
public interface IXzjgService
|
||||
{
|
||||
Task<List<XzjgListItemDto>> GetListAsync(string group);
|
||||
Task<XzjgSaveDto> GetForEditAsync(long id);
|
||||
Task<long> SaveAsync(XzjgSaveDto dto);
|
||||
Task DeleteAsync(long id);
|
||||
Task<decimal> GetPriceAsync(string group, string key);
|
||||
}
|
||||
|
||||
public class XzjgService : IXzjgService
|
||||
{
|
||||
private readonly IRepository<XinZiJiaGePeiZhi> _repo;
|
||||
|
||||
public XzjgService(IRepository<XinZiJiaGePeiZhi> repo) => _repo = repo;
|
||||
|
||||
public async Task<List<XzjgListItemDto>> GetListAsync(string group)
|
||||
{
|
||||
var items = await _repo.GetAllAsync();
|
||||
var q = items.AsQueryable();
|
||||
if (!string.IsNullOrWhiteSpace(group)) q = q.Where(x => x.Group == group);
|
||||
return q.OrderBy(x => x.Group).ThenBy(x => x.Key).ToList()
|
||||
.Select(x => new XzjgListItemDto
|
||||
{
|
||||
Id = x.Id, Group = x.Group, Key = x.Key, Unit = x.Unit, Price = x.Price, Memo = x.Memo
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public async Task<XzjgSaveDto> GetForEditAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("薪资价格配置不存在或已删除", 404);
|
||||
return new XzjgSaveDto { Id = e.Id, Group = e.Group, Key = e.Key, Unit = e.Unit, Price = e.Price, Memo = e.Memo };
|
||||
}
|
||||
|
||||
public async Task<long> SaveAsync(XzjgSaveDto dto)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dto.Group)) throw new ServiceException("请填写分组");
|
||||
if (string.IsNullOrWhiteSpace(dto.Key)) throw new ServiceException("请填写项目");
|
||||
var grp = dto.Group.Trim();
|
||||
var key = dto.Key.Trim();
|
||||
|
||||
XinZiJiaGePeiZhi e;
|
||||
if (dto.Id > 0)
|
||||
{
|
||||
e = await _repo.GetByIdAsync(dto.Id);
|
||||
if (e == null) throw new ServiceException("薪资价格配置不存在或已删除", 404);
|
||||
var dup = await _repo.FirstOrDefaultAsync(x => x.Id != dto.Id && x.Group == grp && x.Key == key);
|
||||
if (dup != null) throw new ServiceException("该分组已存在相同的项目!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var dup = await _repo.AnyAsync(x => x.Group == grp && x.Key == key);
|
||||
if (dup) throw new ServiceException("该分组已存在相同的项目!");
|
||||
e = new XinZiJiaGePeiZhi();
|
||||
await _repo.AddAsync(e);
|
||||
}
|
||||
e.Group = grp;
|
||||
e.Key = key;
|
||||
e.Unit = dto.Unit ?? "";
|
||||
e.Price = dto.Price;
|
||||
e.Memo = dto.Memo ?? "";
|
||||
await _repo.UpdateAsync(e);
|
||||
return e.Id;
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long id)
|
||||
{
|
||||
var e = await _repo.GetByIdAsync(id);
|
||||
if (e == null) throw new ServiceException("薪资价格配置不存在或已删除", 404);
|
||||
await _repo.HardDeleteAsync(e);
|
||||
}
|
||||
|
||||
/// <summary>取价:无配置返回 0</summary>
|
||||
public async Task<decimal> GetPriceAsync(string group, string key)
|
||||
{
|
||||
var e = await _repo.FirstOrDefaultAsync(x => x.Group == group && x.Key == key);
|
||||
return e?.Price ?? 0m;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user