using Admin.NET.Plugin.AiDOP.Dto.S0.Manufacturing; using Admin.NET.Plugin.AiDOP.Dto.S0.Sales; using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing; using Admin.NET.Plugin.AiDOP.Entity.S0.Sales; using Admin.NET.Plugin.AiDOP.Infrastructure; namespace Admin.NET.Plugin.AiDOP.Controllers.S0.Manufacturing; [ApiController] [Route("api/s0/manufacturing/routings")] [AllowAnonymous] [NonUnify] public class AdoS0MfgRoutingsController : ControllerBase { private readonly SqlSugarRepository _routingRep; private readonly SqlSugarRepository _opRep; private readonly SqlSugarRepository _materialRep; private readonly SqlSugarRepository _stdOpRep; public AdoS0MfgRoutingsController( SqlSugarRepository routingRep, SqlSugarRepository opRep, SqlSugarRepository materialRep, SqlSugarRepository stdOpRep) { _routingRep = routingRep; _opRep = opRep; _materialRep = materialRep; _stdOpRep = stdOpRep; } [HttpGet] public async Task GetPagedAsync([FromQuery] AdoS0MfgRoutingQueryDto q) { var page = q.EffectivePage; var pageSize = q.PageSize; (page, pageSize) = PagingGuard.Normalize(page, pageSize); var query = _routingRep.AsQueryable() .WhereIF(q.CompanyRefId.HasValue, x => x.CompanyRefId == q.CompanyRefId!.Value) .WhereIF(q.FactoryRefId.HasValue, x => x.FactoryRefId == q.FactoryRefId!.Value) .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x => x.Code.Contains(q.Keyword!) || x.Name.Contains(q.Keyword!)) .WhereIF(q.IsEnabled.HasValue, x => x.IsEnabled == q.IsEnabled!.Value); var total = await query.CountAsync(); var list = await query.OrderByDescending(x => x.CreatedAt).Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(); return Ok(new { total, page, pageSize, list }); } [HttpGet("{id:long}")] public async Task GetDetailAsync(long id) { var header = await _routingRep.GetByIdAsync(id); if (header == null) return NotFound(); var operations = await _opRep.AsQueryable() .Where(x => x.RoutingId == id) .OrderBy(x => x.SortNo) .ToListAsync(); return Ok(new { header, operations }); } [HttpPost] public async Task CreateAsync([FromBody] AdoS0MfgRoutingUpsertDto dto) { var err = ValidateRouting(dto); if (err != null) return BadRequest(new { message = err }); var fkErr = await ValidateRoutingFksAsync(dto); if (fkErr != null) return BadRequest(new { message = fkErr }); var db = _routingRep.Context; await db.Ado.BeginTranAsync(); try { var routing = new AdoS0MfgRouting { CompanyRefId = dto.CompanyRefId, FactoryRefId = dto.FactoryRefId, Code = dto.Code, Name = dto.Name, MaterialId = dto.MaterialId, BizVersion = dto.BizVersion, DocStatus = dto.DocStatus, Remark = dto.Remark, IsEnabled = dto.IsEnabled, CreatedAt = DateTime.Now }; routing = await _routingRep.AsInsertable(routing).ExecuteReturnEntityAsync(); foreach (var line in dto.Operations) { var row = MapRoutingOp(routing.Id, dto.CompanyRefId, dto.FactoryRefId, line); await _opRep.AsInsertable(row).ExecuteCommandAsync(); } await db.Ado.CommitTranAsync(); return await GetDetailAsync(routing.Id); } catch { await db.Ado.RollbackTranAsync(); throw; } } [HttpPut("{id:long}")] public async Task UpdateAsync(long id, [FromBody] AdoS0MfgRoutingUpsertDto dto) { var err = ValidateRouting(dto); if (err != null) return BadRequest(new { message = err }); var header = await _routingRep.GetByIdAsync(id); if (header == null) return NotFound(); var fkErr = await ValidateRoutingFksAsync(dto); if (fkErr != null) return BadRequest(new { message = fkErr }); var db = _routingRep.Context; await db.Ado.BeginTranAsync(); try { header.CompanyRefId = dto.CompanyRefId; header.FactoryRefId = dto.FactoryRefId; header.Code = dto.Code; header.Name = dto.Name; header.MaterialId = dto.MaterialId; header.BizVersion = dto.BizVersion; header.DocStatus = dto.DocStatus; header.Remark = dto.Remark; header.IsEnabled = dto.IsEnabled; header.UpdatedAt = DateTime.Now; await _routingRep.AsUpdateable(header).ExecuteCommandAsync(); await _opRep.AsDeleteable().Where(x => x.RoutingId == id).ExecuteCommandAsync(); foreach (var line in dto.Operations) { var row = MapRoutingOp(id, dto.CompanyRefId, dto.FactoryRefId, line); await _opRep.AsInsertable(row).ExecuteCommandAsync(); } await db.Ado.CommitTranAsync(); return await GetDetailAsync(id); } catch { await db.Ado.RollbackTranAsync(); throw; } } [HttpPatch("{id:long}/toggle-enabled")] public async Task ToggleEnabledAsync(long id, [FromBody] AdoS0ToggleEnabledDto dto) { var entity = await _routingRep.GetByIdAsync(id); if (entity == null) return NotFound(); entity.IsEnabled = dto.IsEnabled; entity.UpdatedAt = DateTime.Now; await _routingRep.AsUpdateable(entity).ExecuteCommandAsync(); return Ok(entity); } [HttpDelete("{id:long}")] public async Task DeleteAsync(long id) { var header = await _routingRep.GetByIdAsync(id); if (header == null) return NotFound(); var db = _routingRep.Context; await db.Ado.BeginTranAsync(); try { await _opRep.AsDeleteable().Where(x => x.RoutingId == id).ExecuteCommandAsync(); await _routingRep.DeleteAsync(header); await db.Ado.CommitTranAsync(); return Ok(new { message = "删除成功" }); } catch { await db.Ado.RollbackTranAsync(); throw; } } private static string? ValidateRouting(AdoS0MfgRoutingUpsertDto dto) { if (dto.Operations == null || dto.Operations.Count == 0) return "工艺路线至少包含一道工序"; return null; } private async Task ValidateRoutingFksAsync(AdoS0MfgRoutingUpsertDto dto) { if (dto.MaterialId.HasValue) { var ok = await _materialRep.IsAnyAsync(m => m.Id == dto.MaterialId!.Value && m.CompanyRefId == dto.CompanyRefId && m.FactoryRefId == dto.FactoryRefId); if (!ok) return "物料主数据引用无效"; } var opIds = dto.Operations.Select(o => o.OperationId).Distinct().ToList(); var opCount = await _stdOpRep.AsQueryable() .Where(o => opIds.Contains(o.Id) && o.CompanyRefId == dto.CompanyRefId && o.FactoryRefId == dto.FactoryRefId) .CountAsync(); return opCount == opIds.Count ? null : "存在无效的标准工序引用"; } private static AdoS0MfgRoutingOperation MapRoutingOp(long routingId, long companyRefId, long factoryRefId, AdoS0MfgRoutingOperationUpsertDto line) { return new AdoS0MfgRoutingOperation { CompanyRefId = companyRefId, FactoryRefId = factoryRefId, RoutingId = routingId, OperationId = line.OperationId, SortNo = line.SortNo, WorkCenterId = line.WorkCenterId, ProductionLineId = line.ProductionLineId, StdTime = line.StdTime, Remark = line.Remark, IsReportOperation = line.IsReportOperation, Activity1 = line.Activity1, Activity1Qty = line.Activity1Qty, Activity1Unit = line.Activity1Unit, Activity2 = line.Activity2, Activity2Qty = line.Activity2Qty, Activity2Unit = line.Activity2Unit, Activity3 = line.Activity3, Activity3Qty = line.Activity3Qty, Activity3Unit = line.Activity3Unit, BaseQty = line.BaseQty, IsOutsourced = line.IsOutsourced, SupplierId = line.SupplierId, OutsourcedLeadTime = line.OutsourcedLeadTime, IsEnabled = line.IsEnabled, CreatedAt = DateTime.Now }; } }