AdoS0MfgSopDocumentsController.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using Admin.NET.Plugin.AiDOP.Dto.S0.Manufacturing;
  2. using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing;
  3. using Admin.NET.Plugin.AiDOP.Infrastructure;
  4. namespace Admin.NET.Plugin.AiDOP.Controllers.S0.Manufacturing;
  5. [ApiController]
  6. [Route("api/s0/manufacturing/sop-documents")]
  7. [NonUnify]
  8. public class AdoS0MfgSopDocumentsController : ControllerBase
  9. {
  10. private readonly SqlSugarRepository<AdoS0QualitySegmentImage> _rep;
  11. public AdoS0MfgSopDocumentsController(SqlSugarRepository<AdoS0QualitySegmentImage> rep)
  12. {
  13. _rep = rep;
  14. }
  15. [HttpGet]
  16. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0MfgSopDocumentQueryDto q)
  17. {
  18. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  19. var page = q.Page;
  20. var pageSize = q.PageSize;
  21. (page, pageSize) = PagingGuard.Normalize(page, pageSize);
  22. // 去 domain 化(S0-SOP-DOMAIN-DECOUPLING-FIX):列表可见性只由 tenant_id 决定。
  23. // 原先 `x.Domain == q.Domain` 会把本租户数据挡在外面——前端在无 Type=501 工厂时
  24. // 会把公司雪花 Id 当 Domain 传入,与业务表的 legacy Domain(8010) 永不相等。
  25. var baseQuery = _rep.ScopedTo(tenantId)
  26. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword),
  27. x => (x.Line != null && x.Line.Contains(q.Keyword!))
  28. || (x.ItemNum != null && x.ItemNum.Contains(q.Keyword!))
  29. || (x.Op != null && x.Op.Contains(q.Keyword!))
  30. || (x.Path != null && x.Path.Contains(q.Keyword!))
  31. || (x.Descr != null && x.Descr.Contains(q.Keyword!))
  32. || (x.Rev != null && x.Rev.Contains(q.Keyword!)));
  33. var total = await baseQuery.CountAsync();
  34. // 左联仅用于展示字段(Line/Op/imgType),主表字段仍可 CRUD。
  35. // 关联口径一律 tenant_id + 业务键:Domain 是 legacy 兼容字段,同租户内不同表的 Domain
  36. // 取值可能不一致(如 SOP 用组织 Id、LineMaster 用 8010),用它做关联会导致展示列解析不出来;
  37. // 用 tenant_id 兜住跨租户,业务键保证语义正确。
  38. var list = await baseQuery
  39. .LeftJoin<AdoS0ImageType>((qsi, it) => qsi.TenantId == it.TenantId && qsi.ImageTypeID == it.ImageTypeID)
  40. .LeftJoin<AdoS0LineMaster>((qsi, it, lm) => qsi.TenantId == lm.TenantId && qsi.Line == lm.Line)
  41. .LeftJoin<AdoS0MfgRoutingOpDetail>((qsi, it, lm, rd) => qsi.TenantId == rd.TenantId && qsi.ItemNum == rd.MaterialCode && qsi.Op == rd.OperationCode)
  42. .OrderByDescending((qsi, it, lm, rd) => qsi.Id)
  43. .Select((qsi, it, lm, rd) => new
  44. {
  45. id = qsi.Id,
  46. line = qsi.Line,
  47. lineDisplay = qsi.Line == null ? "" : (lm.Line + " " + (lm.Describe ?? "")),
  48. itemNum = qsi.ItemNum,
  49. op = qsi.Op,
  50. opDisplay = qsi.Op == null ? "" : (rd.OperationCode + " " + (rd.OperationDescription ?? "")),
  51. imageTypeID = qsi.ImageTypeID,
  52. imgType = it.Descr,
  53. path = qsi.Path,
  54. descr = qsi.Descr,
  55. rev = qsi.Rev,
  56. sortID = qsi.SortID,
  57. domain = qsi.Domain
  58. })
  59. .Skip((page - 1) * pageSize)
  60. .Take(pageSize)
  61. .ToListAsync();
  62. return Ok(new { total, page, pageSize, list });
  63. }
  64. [HttpGet("{id:long}")]
  65. public async Task<IActionResult> GetAsync(long id)
  66. {
  67. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  68. var item = await _rep.ByIdScopedAsync(id, tenantId);
  69. return item == null ? NotFound() : Ok(item);
  70. }
  71. [HttpPost]
  72. public async Task<IActionResult> CreateAsync([FromBody] AdoS0MfgSopDocumentUpsertDto dto)
  73. {
  74. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  75. var entity = new AdoS0QualitySegmentImage
  76. {
  77. TenantId = tenantId,
  78. Domain = dto.Domain.Trim(),
  79. Line = dto.Line,
  80. ItemNum = dto.ItemNum,
  81. Op = dto.Op,
  82. ImageTypeID = dto.ImageTypeID,
  83. Path = dto.Path,
  84. Descr = dto.Descr,
  85. Rev = dto.Rev,
  86. SortID = dto.SortID
  87. };
  88. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  89. return Ok(entity);
  90. }
  91. [HttpPut("{id:long}")]
  92. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0MfgSopDocumentUpsertDto dto)
  93. {
  94. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  95. var entity = await _rep.ByIdScopedAsync(id, tenantId);
  96. if (entity == null) return NotFound();
  97. entity.Domain = dto.Domain.Trim();
  98. entity.Line = dto.Line;
  99. entity.ItemNum = dto.ItemNum;
  100. entity.Op = dto.Op;
  101. entity.ImageTypeID = dto.ImageTypeID;
  102. entity.Path = dto.Path;
  103. entity.Descr = dto.Descr;
  104. entity.Rev = dto.Rev;
  105. entity.SortID = dto.SortID;
  106. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  107. return Ok(entity);
  108. }
  109. [HttpDelete("{id:long}")]
  110. public async Task<IActionResult> DeleteAsync(long id)
  111. {
  112. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  113. var item = await _rep.ByIdScopedAsync(id, tenantId);
  114. if (item == null) return NotFound();
  115. await _rep.DeleteAsync(item);
  116. return Ok(new { message = "删除成功" });
  117. }
  118. }