AdoS0MfgProductionLinesController.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using Admin.NET.Plugin.AiDOP.Dto.S0.Manufacturing;
  2. using Admin.NET.Plugin.AiDOP.Dto.S0.Sales;
  3. using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing;
  4. using Admin.NET.Plugin.AiDOP.Infrastructure;
  5. namespace Admin.NET.Plugin.AiDOP.Controllers.S0.Manufacturing;
  6. /// <summary>
  7. /// 生产线维护(LineMaster 语义,表 ado_s0_mfg_line_master)。
  8. /// </summary>
  9. [ApiController]
  10. [Route("api/s0/manufacturing/production-lines")]
  11. [NonUnify]
  12. public class AdoS0MfgProductionLinesController : ControllerBase
  13. {
  14. private readonly SqlSugarRepository<AdoS0LineMaster> _rep;
  15. private readonly AdoS0ReferenceChecker _refChecker;
  16. public AdoS0MfgProductionLinesController(SqlSugarRepository<AdoS0LineMaster> rep, AdoS0ReferenceChecker refChecker)
  17. {
  18. _rep = rep;
  19. _refChecker = refChecker;
  20. }
  21. /// <summary>
  22. /// B1-9:LineMaster 6 个 Location 变体的统一 existence check。
  23. /// 全部复用 AdoS0ReferenceChecker.LocationExistsAsync,空值放行。
  24. /// </summary>
  25. private async Task<IActionResult?> ValidateLocationReferencesAsync(AdoS0LineMasterUpsertDto dto, long tenantId)
  26. {
  27. var checks = new (string? Value, string Label)[]
  28. {
  29. (dto.Location, "主库位"),
  30. (dto.VLocation, "虚拟库位"),
  31. (dto.Location2, "辅助库位2"),
  32. (dto.Location3, "辅助库位3"),
  33. (dto.PickingLocation, "拣料库位"),
  34. (dto.MidLocation, "中间库位"),
  35. };
  36. foreach (var (value, label) in checks)
  37. {
  38. if (!await _refChecker.LocationExistsAsync(tenantId, value))
  39. return AdoS0ApiErrors.InvalidReference(AdoS0ErrorCodes.ReferenceNotFound,
  40. $"{label}编码 '{value}' 不存在于库位主数据");
  41. }
  42. return null;
  43. }
  44. [HttpGet]
  45. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0LineMasterQueryDto q)
  46. {
  47. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  48. var page = q.EffectivePage;
  49. var pageSize = q.PageSize;
  50. (page, pageSize) = PagingGuard.Normalize(page, pageSize);
  51. var query = _rep.ScopedTo(tenantId)
  52. .WhereIF(q.CompanyRefId.HasValue, x => x.CompanyRefId == q.CompanyRefId!.Value)
  53. .WhereIF(q.FactoryRefId.HasValue, x => x.FactoryRefId == q.FactoryRefId!.Value)
  54. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword),
  55. x => x.Line.Contains(q.Keyword!) || (x.Describe != null && x.Describe.Contains(q.Keyword!)))
  56. .WhereIF(!string.IsNullOrWhiteSpace(q.Line), x => x.Line.Contains(q.Line!))
  57. .WhereIF(!string.IsNullOrWhiteSpace(q.Workshop),
  58. x => x.Workshop != null && x.Workshop.Contains(q.Workshop!))
  59. .WhereIF(q.IsEnabled.HasValue, x => x.IsActive == q.IsEnabled!.Value);
  60. var total = await query.CountAsync();
  61. var entities = await query
  62. .OrderByDescending(x => x.Id)
  63. .Skip((page - 1) * pageSize)
  64. .Take(pageSize)
  65. .ToListAsync();
  66. // GeneralizedCodeMaster 中文说明:当前库无码表实体,占位供列表展示;后续可 JOIN 补全。
  67. var list = entities.Select(x => new
  68. {
  69. x.Id,
  70. x.CompanyRefId,
  71. x.FactoryRefId,
  72. x.Domain,
  73. x.Line,
  74. describe = x.Describe,
  75. x.LineType,
  76. x.LineCategory,
  77. x.Location,
  78. x.Workshop,
  79. vLocation = x.VLocation,
  80. x.Location2,
  81. x.Location3,
  82. pickingLocation = x.PickingLocation,
  83. midLocation = x.MidLocation,
  84. isActive = x.IsActive,
  85. x.CreateUser,
  86. x.CreateTime,
  87. x.UpdateUser,
  88. x.UpdateTime,
  89. lineCategoryComments = (string?)null,
  90. workshopComments = (string?)null
  91. }).ToList();
  92. return Ok(new { total, page, pageSize, list });
  93. }
  94. [HttpGet("{id:long}")]
  95. public async Task<IActionResult> GetAsync(long id)
  96. {
  97. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  98. var item = await _rep.ByIdScopedAsync(id, tenantId);
  99. return item == null ? NotFound() : Ok(item);
  100. }
  101. [HttpPost]
  102. public async Task<IActionResult> CreateAsync([FromBody] AdoS0LineMasterUpsertDto dto)
  103. {
  104. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  105. var locErr = await ValidateLocationReferencesAsync(dto, tenantId);
  106. if (locErr != null) return locErr;
  107. var now = DateTime.Now;
  108. var entity = new AdoS0LineMaster
  109. {
  110. TenantId = tenantId,
  111. CompanyRefId = dto.CompanyRefId,
  112. FactoryRefId = dto.FactoryRefId,
  113. Domain = dto.Domain.Trim(),
  114. Line = dto.Line.Trim(),
  115. Describe = string.IsNullOrWhiteSpace(dto.Describe) ? null : dto.Describe.Trim(),
  116. LineType = string.IsNullOrWhiteSpace(dto.LineType) ? null : dto.LineType.Trim(),
  117. LineCategory = string.IsNullOrWhiteSpace(dto.LineCategory) ? null : dto.LineCategory.Trim(),
  118. Location = string.IsNullOrWhiteSpace(dto.Location) ? null : dto.Location.Trim(),
  119. Workshop = string.IsNullOrWhiteSpace(dto.Workshop) ? null : dto.Workshop.Trim(),
  120. VLocation = string.IsNullOrWhiteSpace(dto.VLocation) ? null : dto.VLocation.Trim(),
  121. Location2 = string.IsNullOrWhiteSpace(dto.Location2) ? null : dto.Location2.Trim(),
  122. Location3 = string.IsNullOrWhiteSpace(dto.Location3) ? null : dto.Location3.Trim(),
  123. PickingLocation = string.IsNullOrWhiteSpace(dto.PickingLocation) ? null : dto.PickingLocation.Trim(),
  124. MidLocation = string.IsNullOrWhiteSpace(dto.MidLocation) ? null : dto.MidLocation.Trim(),
  125. IsActive = dto.IsActive,
  126. CreateUser = dto.CreateUser,
  127. CreateTime = now,
  128. UpdateUser = null,
  129. UpdateTime = null
  130. };
  131. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  132. return Ok(entity);
  133. }
  134. [HttpPut("{id:long}")]
  135. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0LineMasterUpsertDto dto)
  136. {
  137. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  138. var locErr = await ValidateLocationReferencesAsync(dto, tenantId);
  139. if (locErr != null) return locErr;
  140. var entity = await _rep.ByIdScopedAsync(id, tenantId);
  141. if (entity == null) return NotFound();
  142. entity.CompanyRefId = dto.CompanyRefId;
  143. entity.FactoryRefId = dto.FactoryRefId;
  144. entity.Domain = dto.Domain.Trim();
  145. entity.Line = dto.Line.Trim();
  146. entity.Describe = string.IsNullOrWhiteSpace(dto.Describe) ? null : dto.Describe.Trim();
  147. entity.LineType = string.IsNullOrWhiteSpace(dto.LineType) ? null : dto.LineType.Trim();
  148. entity.LineCategory = string.IsNullOrWhiteSpace(dto.LineCategory) ? null : dto.LineCategory.Trim();
  149. entity.Location = string.IsNullOrWhiteSpace(dto.Location) ? null : dto.Location.Trim();
  150. entity.Workshop = string.IsNullOrWhiteSpace(dto.Workshop) ? null : dto.Workshop.Trim();
  151. entity.VLocation = string.IsNullOrWhiteSpace(dto.VLocation) ? null : dto.VLocation.Trim();
  152. entity.Location2 = string.IsNullOrWhiteSpace(dto.Location2) ? null : dto.Location2.Trim();
  153. entity.Location3 = string.IsNullOrWhiteSpace(dto.Location3) ? null : dto.Location3.Trim();
  154. entity.PickingLocation = string.IsNullOrWhiteSpace(dto.PickingLocation) ? null : dto.PickingLocation.Trim();
  155. entity.MidLocation = string.IsNullOrWhiteSpace(dto.MidLocation) ? null : dto.MidLocation.Trim();
  156. entity.IsActive = dto.IsActive;
  157. entity.UpdateUser = dto.UpdateUser;
  158. entity.UpdateTime = DateTime.Now;
  159. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  160. return Ok(entity);
  161. }
  162. [HttpPatch("{id:long}/toggle-enabled")]
  163. public async Task<IActionResult> ToggleEnabledAsync(long id, [FromBody] AdoS0ToggleEnabledDto dto)
  164. {
  165. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  166. var entity = await _rep.ByIdScopedAsync(id, tenantId);
  167. if (entity == null) return NotFound();
  168. entity.IsActive = dto.IsEnabled;
  169. entity.UpdateTime = DateTime.Now;
  170. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  171. return Ok(new { entity.Id, isActive = entity.IsActive, entity.UpdateTime });
  172. }
  173. [HttpDelete("{id:long}")]
  174. public async Task<IActionResult> DeleteAsync(long id)
  175. {
  176. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  177. var item = await _rep.ByIdScopedAsync(id, tenantId);
  178. if (item == null) return NotFound();
  179. var refInfo = await _refChecker.ProductionLineReferencesAsync(tenantId, item.Id, item.Line);
  180. if (refInfo is { } r)
  181. return AdoS0ApiErrors.Conflict(AdoS0ErrorCodes.DeleteBlocked,
  182. $"存在 {r.Count} 条 {r.Table} 引用该生产线,无法删除");
  183. await _rep.DeleteAsync(item);
  184. return Ok(new { message = "删除成功" });
  185. }
  186. }