using Yitter.IdGenerator; namespace Admin.NET.Plugin.AiDOP.Production; /// /// 排产异常记录服务 🏭 /// 路由前缀:/api/Production/schedule-exception/... /// [ApiDescriptionSettings(Order = 267, Description = "排产异常记录")] [Route("api/Production")] [AllowAnonymous] [NonUnify] public class ScheduleExceptionService : IDynamicApiController, ITransient { private const string C = "utf8mb4_general_ci"; private readonly ISqlSugarClient _db; private readonly SqlSugarRepository _rep; public ScheduleExceptionService(ISqlSugarClient db, SqlSugarRepository rep) { _db = db; _rep = rep; } // ══════════════════════════════════════════════════════════════ // 列表 GET /api/Production/schedule-exception/list // ══════════════════════════════════════════════════════════════ /// 排产异常分页列表(ScheduleExceptionMaster + ItemMaster.Descr1) [DisplayName("排产异常记录列表")] [HttpGet("schedule-exception/list")] public async Task GetList([FromQuery] ScheduleExceptionListInput input) { var pars = new List(); var inner = new List { "1=1" }; if (!string.IsNullOrWhiteSpace(input.OptTime)) { inner.Add($"(CAST(sm.OptTime AS CHAR(50)) COLLATE {C}) LIKE @OptTimeLike"); pars.Add(new SugarParameter("@OptTimeLike", $"%{input.OptTime.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.WorkOrd)) { inner.Add($"(sm.WorkOrd COLLATE {C}) LIKE @WorkOrd"); pars.Add(new SugarParameter("@WorkOrd", $"%{input.WorkOrd.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.ItemNum)) { inner.Add($"(sm.ItemNum COLLATE {C}) = @ItemNumEq"); pars.Add(new SugarParameter("@ItemNumEq", input.ItemNum.Trim())); } var baseSql = BuildListBaseSql(string.Join(" AND ", inner)); var offset = (input.Page - 1) * input.PageSize; var total = await _db.Ado.GetIntAsync($"SELECT COUNT(*) FROM ({baseSql}) AS t", pars); var list = await _db.Ado.SqlQueryAsync( $"SELECT * FROM ({baseSql}) AS t ORDER BY t.Id DESC LIMIT {input.PageSize} OFFSET {offset}", pars); return new { total, page = input.Page, pageSize = input.PageSize, list }; } private static string BuildListBaseSql(string innerWhere) { const string coll = "utf8mb4_general_ci"; return $""" SELECT sm.RecID AS Id, sm.`Domain` AS Domain, sm.OptTime AS OptTime, sm.WorkOrd AS WorkOrd, sm.ItemNum AS ItemNum, im.Descr1 AS Descr1, sm.Remark AS Remark, sm.Type AS Type FROM ScheduleExceptionMaster sm LEFT JOIN ItemMaster im ON (sm.`Domain` COLLATE {coll}) = (im.`Domain` COLLATE {coll}) AND (sm.ItemNum COLLATE {coll}) = (im.ItemNum COLLATE {coll}) WHERE {innerWhere} """; } // ══════════════════════════════════════════════════════════════ // 详情 GET /api/Production/schedule-exception/{id} // ══════════════════════════════════════════════════════════════ /// 排产异常详情 [DisplayName("排产异常记录详情")] [HttpGet("schedule-exception/{id:long}")] public async Task GetDetail(long id) { var e = await _rep.GetFirstAsync(u => u.RecID == id) ?? throw Oops.Oh("记录不存在"); return new { id = e.RecID, domain = e.Domain, workOrd = e.WorkOrd, itemNum = e.ItemNum, remark = e.Remark, type = e.Type, optTime = e.OptTime, createTime = e.CreateTime }; } // ══════════════════════════════════════════════════════════════ // 保存 POST /api/Production/schedule-exception/save // ══════════════════════════════════════════════════════════════ /// 保存排产异常(新增或编辑) [DisplayName("保存排产异常记录")] [ApiDescriptionSettings(Name = "SaveScheduleException"), HttpPost("schedule-exception/save")] public async Task Save([FromBody] ScheduleExceptionSaveInput input) { if (input.Id is null or 0) { var entity = new ScheduleExceptionMaster { RecID = YitIdHelper.NextId(), Domain = input.Domain.Trim(), WorkOrd = input.WorkOrd.Trim(), ItemNum = input.ItemNum.Trim(), Remark = input.Remark?.Trim(), Type = input.Type?.Trim(), OptTime = input.OptTime ?? DateTime.Now, CreateTime = input.CreateTime ?? DateTime.Now }; await _rep.InsertAsync(entity); return new { id = entity.RecID, message = "新增成功" }; } var exist = await _rep.GetFirstAsync(u => u.RecID == input.Id!.Value) ?? throw Oops.Oh("记录不存在"); exist.Domain = input.Domain.Trim(); exist.WorkOrd = input.WorkOrd.Trim(); exist.ItemNum = input.ItemNum.Trim(); exist.Remark = input.Remark?.Trim(); exist.Type = input.Type?.Trim(); if (input.OptTime.HasValue) exist.OptTime = input.OptTime; if (input.CreateTime.HasValue) exist.CreateTime = input.CreateTime; await _rep.UpdateAsync(exist); return new { id = exist.RecID, message = "编辑成功" }; } // ══════════════════════════════════════════════════════════════ // 删除 POST /api/Production/schedule-exception/delete/{id} // ══════════════════════════════════════════════════════════════ /// 删除排产异常 [DisplayName("删除排产异常记录")] [HttpPost("schedule-exception/delete/{id:long}")] public async Task Delete(long id) { var n = await _db.Ado.ExecuteCommandAsync( "DELETE FROM ScheduleExceptionMaster WHERE RecID = @Id", new List { new("@Id", id) }); if (n == 0) throw Oops.Oh("记录不存在"); return new { message = "删除成功" }; } private sealed class ScheduleExceptionListRow { public long Id { get; set; } public string? Domain { get; set; } public DateTime? OptTime { get; set; } public string? WorkOrd { get; set; } public string? ItemNum { get; set; } public string? Descr1 { get; set; } public string? Remark { get; set; } public string? Type { get; set; } } }