AdoS0QualityBaseDataControllers.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. using Admin.NET.Plugin.AiDOP.Dto.S0.Quality;
  2. using Admin.NET.Plugin.AiDOP.Entity.S0.Quality;
  3. using Admin.NET.Plugin.AiDOP.Infrastructure;
  4. using System.Linq.Expressions;
  5. using static Admin.NET.Plugin.AiDOP.Controllers.S0.Quality.AdoS0QmsControllerHelpers;
  6. namespace Admin.NET.Plugin.AiDOP.Controllers.S0.Quality;
  7. [ApiController]
  8. [Route("api/s0/quality/base-types")]
  9. [NonUnify]
  10. public class AdoS0QmsQualityBaseTypesController : ControllerBase
  11. {
  12. private readonly SqlSugarRepository<AdoS0QmsQualityBaseType> _rep;
  13. public AdoS0QmsQualityBaseTypesController(SqlSugarRepository<AdoS0QmsQualityBaseType> rep)
  14. {
  15. _rep = rep;
  16. }
  17. [HttpGet]
  18. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  19. {
  20. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  21. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  22. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  23. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  24. x.TypeCategory.Contains(q.Keyword!)
  25. || x.TypeCode.Contains(q.Keyword!)
  26. || x.ShortName.Contains(q.Keyword!)
  27. || (x.FullName != null && x.FullName.Contains(q.Keyword!)));
  28. var total = await query.CountAsync();
  29. var list = await query.OrderBy(x => x.TypeCategory).OrderBy(x => x.TypeCode)
  30. .Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  31. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  32. }
  33. [HttpGet("{id:long}")]
  34. public async Task<IActionResult> GetAsync(long id)
  35. {
  36. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  37. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  38. }
  39. [HttpPost]
  40. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsQualityBaseTypeUpsertDto dto)
  41. {
  42. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  43. // C4 唯一性 pre-check:(TypeCategory, TypeCode) 全局唯一
  44. var category = dto.TypeCategory.Trim();
  45. var code = dto.TypeCode.Trim();
  46. if (await _rep.AsQueryable().Where(x => x.TenantId == tenantId).AnyAsync(x => x.TypeCategory == category && x.TypeCode == code))
  47. {
  48. return AdoS0ApiErrors.Conflict(AdoS0ErrorCodes.QualityBaseTypeDuplicate,
  49. $"质量基础类型 '{category} / {code}' 已存在");
  50. }
  51. var entity = new AdoS0QmsQualityBaseType();
  52. ApplyQualityBaseType(entity, dto, true);
  53. entity.TenantId = tenantId;
  54. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  55. return Ok(entity);
  56. }
  57. [HttpPut("{id:long}")]
  58. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsQualityBaseTypeUpsertDto dto)
  59. {
  60. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  61. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  62. if (entity == null) return NotFound();
  63. // C4 唯一性 pre-check:(TypeCategory, TypeCode) 全局唯一,排除自身
  64. var category = dto.TypeCategory.Trim();
  65. var code = dto.TypeCode.Trim();
  66. if (await _rep.AsQueryable().Where(x => x.TenantId == tenantId).AnyAsync(x => x.TypeCategory == category && x.TypeCode == code && x.Id != id))
  67. {
  68. return AdoS0ApiErrors.Conflict(AdoS0ErrorCodes.QualityBaseTypeDuplicate,
  69. $"质量基础类型 '{category} / {code}' 已存在");
  70. }
  71. ApplyQualityBaseType(entity, dto, false);
  72. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  73. return Ok(entity);
  74. }
  75. [HttpDelete("{id:long}")]
  76. public async Task<IActionResult> DeleteAsync(long id)
  77. {
  78. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  79. return await DeleteByIdAsync(_rep, id, tenantId);
  80. }
  81. private static void ApplyQualityBaseType(AdoS0QmsQualityBaseType entity, AdoS0QmsQualityBaseTypeUpsertDto dto, bool isCreate)
  82. {
  83. entity.TypeCategory = dto.TypeCategory.Trim();
  84. entity.TypeCode = dto.TypeCode.Trim();
  85. entity.ShortName = dto.ShortName.Trim();
  86. entity.FullName = NullIfWhiteSpace(dto.FullName);
  87. entity.IsActive = dto.IsActive;
  88. entity.Remark = NullIfWhiteSpace(dto.Remark);
  89. if (isCreate) entity.CreateTime = DateTime.Now;
  90. entity.ModifyTime = DateTime.Now;
  91. }
  92. }
  93. [ApiController]
  94. [Route("api/s0/quality/raw-whitelists")]
  95. [NonUnify]
  96. public class AdoS0QmsRawWhitelistsController : ControllerBase
  97. {
  98. private readonly SqlSugarRepository<AdoS0QmsRawWhitelist> _rep;
  99. public AdoS0QmsRawWhitelistsController(SqlSugarRepository<AdoS0QmsRawWhitelist> rep)
  100. {
  101. _rep = rep;
  102. }
  103. [HttpGet]
  104. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  105. {
  106. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  107. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  108. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  109. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  110. (x.SupplierCode != null && x.SupplierCode.Contains(q.Keyword!)) ||
  111. (x.SupplierName != null && x.SupplierName.Contains(q.Keyword!)) ||
  112. (x.MaterialCode != null && x.MaterialCode.Contains(q.Keyword!)) ||
  113. (x.MaterialName != null && x.MaterialName.Contains(q.Keyword!)));
  114. var total = await query.CountAsync();
  115. var list = await query.OrderBy(x => x.SupplierCode).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  116. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  117. }
  118. [HttpGet("{id:long}")]
  119. public async Task<IActionResult> GetAsync(long id)
  120. {
  121. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  122. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  123. }
  124. [HttpGet("options")]
  125. public async Task<IActionResult> GetOptionsAsync()
  126. {
  127. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  128. var list = await _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  129. .OrderBy(x => x.SupplierCode)
  130. .Select(x => new AdoS0QualitySimpleOptionDto { Value = x.Id, Label = (x.SupplierCode ?? "") + " / " + (x.SupplierName ?? "") })
  131. .ToListAsync();
  132. return Ok(list);
  133. }
  134. [HttpPost]
  135. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsRawWhitelistUpsertDto dto)
  136. {
  137. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  138. var err = ValidateRawWhitelist(dto, out var dimensionType);
  139. if (err != null) return AdoS0ApiErrors.InvalidRequest(err);
  140. var entity = new AdoS0QmsRawWhitelist
  141. {
  142. SupplierCode = NullIfWhiteSpace(dto.SupplierCode),
  143. SupplierName = NullIfWhiteSpace(dto.SupplierName),
  144. MaterialCode = NullIfWhiteSpace(dto.MaterialCode),
  145. MaterialName = NullIfWhiteSpace(dto.MaterialName),
  146. DimensionType = dimensionType
  147. };
  148. entity.TenantId = tenantId;
  149. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  150. return Ok(entity);
  151. }
  152. [HttpPut("{id:long}")]
  153. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsRawWhitelistUpsertDto dto)
  154. {
  155. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  156. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  157. if (entity == null) return NotFound();
  158. var err = ValidateRawWhitelist(dto, out var dimensionType);
  159. if (err != null) return AdoS0ApiErrors.InvalidRequest(err);
  160. entity.SupplierCode = NullIfWhiteSpace(dto.SupplierCode);
  161. entity.SupplierName = NullIfWhiteSpace(dto.SupplierName);
  162. entity.MaterialCode = NullIfWhiteSpace(dto.MaterialCode);
  163. entity.MaterialName = NullIfWhiteSpace(dto.MaterialName);
  164. entity.DimensionType = dimensionType;
  165. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  166. return Ok(entity);
  167. }
  168. [HttpDelete("{id:long}")]
  169. public async Task<IActionResult> DeleteAsync(long id)
  170. {
  171. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  172. return await DeleteByIdAsync(_rep, id, tenantId);
  173. }
  174. private static string? ValidateRawWhitelist(AdoS0QmsRawWhitelistUpsertDto dto, out string dimensionType)
  175. {
  176. dimensionType = string.IsNullOrWhiteSpace(dto.DimensionType)
  177. ? "supplier"
  178. : dto.DimensionType.Trim().ToLowerInvariant();
  179. if (dimensionType is not ("supplier" or "material" or "material_supplier"))
  180. return "维度类型仅支持 supplier/material/material_supplier";
  181. if ((dimensionType == "supplier" || dimensionType == "material_supplier")
  182. && string.IsNullOrWhiteSpace(dto.SupplierCode))
  183. return "供应商维度下,供应商编码不能为空";
  184. if ((dimensionType == "supplier" || dimensionType == "material_supplier")
  185. && string.IsNullOrWhiteSpace(dto.SupplierName))
  186. return "供应商维度下,供应商名称不能为空";
  187. if ((dimensionType == "material" || dimensionType == "material_supplier")
  188. && string.IsNullOrWhiteSpace(dto.MaterialCode))
  189. return "物料维度下,物料编码不能为空";
  190. return null;
  191. }
  192. }
  193. [ApiController]
  194. [Route("api/s0/quality/sampling-schemes")]
  195. [NonUnify]
  196. public class AdoS0QmsSamplingSchemesController : ControllerBase
  197. {
  198. private readonly SqlSugarRepository<AdoS0QmsSamplingScheme> _rep;
  199. public AdoS0QmsSamplingSchemesController(SqlSugarRepository<AdoS0QmsSamplingScheme> rep)
  200. {
  201. _rep = rep;
  202. }
  203. [HttpGet]
  204. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  205. {
  206. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  207. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  208. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  209. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  210. (x.Number != null && x.Number.Contains(q.Keyword!)) ||
  211. (x.Name != null && x.Name.Contains(q.Keyword!)));
  212. var total = await query.CountAsync();
  213. var list = await query.OrderBy(x => x.Number).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  214. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  215. }
  216. [HttpGet("{id:long}")]
  217. public async Task<IActionResult> GetAsync(long id)
  218. {
  219. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  220. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  221. }
  222. [HttpGet("options")]
  223. public async Task<IActionResult> GetOptionsAsync()
  224. {
  225. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  226. return Ok(await BuildOptionsAsync(_rep.AsQueryable().Where(x => x.TenantId == tenantId), x => x.Id, x => $"{x.Number} / {x.Name}"));
  227. }
  228. [HttpPost]
  229. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsSamplingSchemeUpsertDto dto)
  230. {
  231. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  232. var entity = new AdoS0QmsSamplingScheme();
  233. ApplySamplingScheme(entity, dto, true);
  234. entity.TenantId = tenantId;
  235. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  236. return Ok(entity);
  237. }
  238. [HttpPut("{id:long}")]
  239. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsSamplingSchemeUpsertDto dto)
  240. {
  241. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  242. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  243. if (entity == null) return NotFound();
  244. ApplySamplingScheme(entity, dto, false);
  245. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  246. return Ok(entity);
  247. }
  248. [HttpDelete("{id:long}")]
  249. public async Task<IActionResult> DeleteAsync(long id)
  250. {
  251. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  252. return await DeleteByIdAsync(_rep, id, tenantId);
  253. }
  254. private static void ApplySamplingScheme(AdoS0QmsSamplingScheme entity, AdoS0QmsSamplingSchemeUpsertDto dto, bool isCreate)
  255. {
  256. entity.Number = dto.Number.Trim();
  257. entity.Name = dto.Name.Trim();
  258. entity.SamplingType = NullIfWhiteSpace(dto.SamplingType);
  259. entity.InspectionLevel = NullIfWhiteSpace(dto.InspectionLevel);
  260. entity.Strictness = NullIfWhiteSpace(dto.Strictness);
  261. entity.AqlValue = NullIfWhiteSpace(dto.AqlValue);
  262. entity.InspectionType = NullIfWhiteSpace(dto.InspectionType);
  263. entity.InspectOrgId = dto.InspectOrgId;
  264. entity.InspectUserId = NullIfWhiteSpace(dto.InspectUserId);
  265. entity.Status = NullIfWhiteSpace(dto.Status);
  266. entity.EnableStatus = NullIfWhiteSpace(dto.EnableStatus);
  267. entity.Comment = NullIfWhiteSpace(dto.Comment);
  268. entity.FixedSamplingRate = dto.FixedSamplingRate;
  269. if (isCreate) entity.CreateTime = DateTime.Now;
  270. entity.ModifyTime = DateTime.Now;
  271. }
  272. }
  273. [ApiController]
  274. [Route("api/s0/quality/instruments")]
  275. [NonUnify]
  276. public class AdoS0QmsInspectionInstrumentsController : ControllerBase
  277. {
  278. private readonly SqlSugarRepository<AdoS0QmsInspectionInstrument> _rep;
  279. public AdoS0QmsInspectionInstrumentsController(SqlSugarRepository<AdoS0QmsInspectionInstrument> rep)
  280. {
  281. _rep = rep;
  282. }
  283. [HttpGet]
  284. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  285. {
  286. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  287. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  288. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  289. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  290. (x.Number != null && x.Number.Contains(q.Keyword!)) ||
  291. (x.Name != null && x.Name.Contains(q.Keyword!)) ||
  292. (x.Model != null && x.Model.Contains(q.Keyword!)));
  293. var total = await query.CountAsync();
  294. var list = await query.OrderBy(x => x.Number).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  295. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  296. }
  297. [HttpGet("{id:long}")]
  298. public async Task<IActionResult> GetAsync(long id)
  299. {
  300. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  301. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  302. }
  303. [HttpGet("options")]
  304. public async Task<IActionResult> GetOptionsAsync()
  305. {
  306. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  307. return Ok(await BuildOptionsAsync(_rep.AsQueryable().Where(x => x.TenantId == tenantId), x => x.Id, x => $"{x.Number} / {x.Name}"));
  308. }
  309. [HttpPost]
  310. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsInspectionInstrumentUpsertDto dto)
  311. {
  312. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  313. var entity = new AdoS0QmsInspectionInstrument();
  314. ApplyInspectionInstrument(entity, dto, true);
  315. entity.TenantId = tenantId;
  316. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  317. return Ok(entity);
  318. }
  319. [HttpPut("{id:long}")]
  320. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsInspectionInstrumentUpsertDto dto)
  321. {
  322. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  323. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  324. if (entity == null) return NotFound();
  325. ApplyInspectionInstrument(entity, dto, false);
  326. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  327. return Ok(entity);
  328. }
  329. [HttpDelete("{id:long}")]
  330. public async Task<IActionResult> DeleteAsync(long id)
  331. {
  332. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  333. return await DeleteByIdAsync(_rep, id, tenantId);
  334. }
  335. private static void ApplyInspectionInstrument(AdoS0QmsInspectionInstrument entity, AdoS0QmsInspectionInstrumentUpsertDto dto, bool isCreate)
  336. {
  337. entity.Number = dto.Number.Trim();
  338. entity.Name = dto.Name.Trim();
  339. entity.Model = NullIfWhiteSpace(dto.Model);
  340. entity.Specification = NullIfWhiteSpace(dto.Specification);
  341. entity.Manufacturer = NullIfWhiteSpace(dto.Manufacturer);
  342. entity.Status = NullIfWhiteSpace(dto.Status);
  343. entity.EnableStatus = NullIfWhiteSpace(dto.EnableStatus);
  344. entity.Comment = NullIfWhiteSpace(dto.Comment);
  345. entity.GaugeCategory = NullIfWhiteSpace(dto.GaugeCategory);
  346. entity.CalibrationCycleDays = dto.CalibrationCycleDays;
  347. entity.NextCalibrationDate = NullIfWhiteSpace(dto.NextCalibrationDate);
  348. if (isCreate) entity.CreateTime = DateTime.Now;
  349. entity.ModifyTime = DateTime.Now;
  350. }
  351. }
  352. [ApiController]
  353. [Route("api/s0/quality/inspection-methods")]
  354. [NonUnify]
  355. public class AdoS0QmsInspectionMethodsController : ControllerBase
  356. {
  357. private readonly SqlSugarRepository<AdoS0QmsInspectionMethod> _rep;
  358. public AdoS0QmsInspectionMethodsController(SqlSugarRepository<AdoS0QmsInspectionMethod> rep)
  359. {
  360. _rep = rep;
  361. }
  362. [HttpGet]
  363. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  364. {
  365. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  366. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  367. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  368. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  369. (x.Number != null && x.Number.Contains(q.Keyword!)) ||
  370. (x.Name != null && x.Name.Contains(q.Keyword!)));
  371. var total = await query.CountAsync();
  372. var list = await query.OrderBy(x => x.Number).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  373. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  374. }
  375. [HttpGet("{id:long}")]
  376. public async Task<IActionResult> GetAsync(long id)
  377. {
  378. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  379. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  380. }
  381. [HttpGet("options")]
  382. public async Task<IActionResult> GetOptionsAsync()
  383. {
  384. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  385. return Ok(await BuildOptionsAsync(_rep.AsQueryable().Where(x => x.TenantId == tenantId), x => x.Id, x => $"{x.Number} / {x.Name}"));
  386. }
  387. [HttpPost]
  388. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsInspectionMethodUpsertDto dto)
  389. {
  390. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  391. var entity = new AdoS0QmsInspectionMethod();
  392. ApplyInspectionMethod(entity, dto, true);
  393. entity.TenantId = tenantId;
  394. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  395. return Ok(entity);
  396. }
  397. [HttpPut("{id:long}")]
  398. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsInspectionMethodUpsertDto dto)
  399. {
  400. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  401. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  402. if (entity == null) return NotFound();
  403. ApplyInspectionMethod(entity, dto, false);
  404. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  405. return Ok(entity);
  406. }
  407. [HttpDelete("{id:long}")]
  408. public async Task<IActionResult> DeleteAsync(long id)
  409. {
  410. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  411. return await DeleteByIdAsync(_rep, id, tenantId);
  412. }
  413. private static void ApplyInspectionMethod(AdoS0QmsInspectionMethod entity, AdoS0QmsInspectionMethodUpsertDto dto, bool isCreate)
  414. {
  415. entity.Number = dto.Number.Trim();
  416. entity.Name = dto.Name.Trim();
  417. entity.ControlStrategy = NullIfWhiteSpace(dto.ControlStrategy);
  418. entity.Status = NullIfWhiteSpace(dto.Status);
  419. entity.EnableStatus = NullIfWhiteSpace(dto.EnableStatus);
  420. entity.Comment = NullIfWhiteSpace(dto.Comment);
  421. if (isCreate) entity.CreateTime = DateTime.Now;
  422. entity.ModifyTime = DateTime.Now;
  423. }
  424. }
  425. [ApiController]
  426. [Route("api/s0/quality/inspection-items")]
  427. [NonUnify]
  428. public class AdoS0QmsInspectionItemsController : ControllerBase
  429. {
  430. private readonly SqlSugarRepository<AdoS0QmsInspectionItem> _rep;
  431. public AdoS0QmsInspectionItemsController(SqlSugarRepository<AdoS0QmsInspectionItem> rep)
  432. {
  433. _rep = rep;
  434. }
  435. [HttpGet]
  436. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  437. {
  438. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  439. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  440. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  441. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  442. (x.Number != null && x.Number.Contains(q.Keyword!)) ||
  443. (x.Name != null && x.Name.Contains(q.Keyword!)));
  444. var total = await query.CountAsync();
  445. var list = await query.OrderBy(x => x.Number).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  446. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  447. }
  448. [HttpGet("{id:long}")]
  449. public async Task<IActionResult> GetAsync(long id)
  450. {
  451. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  452. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  453. }
  454. [HttpGet("options")]
  455. public async Task<IActionResult> GetOptionsAsync()
  456. {
  457. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  458. return Ok(await BuildOptionsAsync(_rep.AsQueryable().Where(x => x.TenantId == tenantId), x => x.Id, x => $"{x.Number} / {x.Name}"));
  459. }
  460. [HttpPost]
  461. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsInspectionItemUpsertDto dto)
  462. {
  463. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  464. var entity = new AdoS0QmsInspectionItem();
  465. ApplyInspectionItem(entity, dto, true);
  466. entity.TenantId = tenantId;
  467. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  468. return Ok(entity);
  469. }
  470. [HttpPut("{id:long}")]
  471. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsInspectionItemUpsertDto dto)
  472. {
  473. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  474. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  475. if (entity == null) return NotFound();
  476. ApplyInspectionItem(entity, dto, false);
  477. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  478. return Ok(entity);
  479. }
  480. [HttpDelete("{id:long}")]
  481. public async Task<IActionResult> DeleteAsync(long id)
  482. {
  483. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  484. return await DeleteByIdAsync(_rep, id, tenantId);
  485. }
  486. private static void ApplyInspectionItem(AdoS0QmsInspectionItem entity, AdoS0QmsInspectionItemUpsertDto dto, bool isCreate)
  487. {
  488. entity.Number = dto.Number.Trim();
  489. entity.Name = dto.Name.Trim();
  490. entity.CheckMethodId = dto.CheckMethodId;
  491. entity.CheckBasisId = dto.CheckBasisId;
  492. entity.CheckInstructId = dto.CheckInstructId;
  493. entity.RadioGroupField = NullIfWhiteSpace(dto.RadioGroupField);
  494. entity.RadioGroupField1 = NullIfWhiteSpace(dto.RadioGroupField1);
  495. entity.MetricType = dto.MetricType;
  496. entity.Status = NullIfWhiteSpace(dto.Status);
  497. entity.EnableStatus = NullIfWhiteSpace(dto.EnableStatus);
  498. entity.Comment = NullIfWhiteSpace(dto.Comment);
  499. if (isCreate) entity.CreateTime = DateTime.Now;
  500. entity.ModifyTime = DateTime.Now;
  501. }
  502. }
  503. [ApiController]
  504. [Route("api/s0/quality/inspection-frequencies")]
  505. [NonUnify]
  506. public class AdoS0QmsInspectionFrequenciesController : ControllerBase
  507. {
  508. private readonly SqlSugarRepository<AdoS0QmsInspectionFrequency> _rep;
  509. public AdoS0QmsInspectionFrequenciesController(SqlSugarRepository<AdoS0QmsInspectionFrequency> rep)
  510. {
  511. _rep = rep;
  512. }
  513. [HttpGet]
  514. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  515. {
  516. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  517. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  518. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  519. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  520. (x.Number != null && x.Number.Contains(q.Keyword!)) ||
  521. (x.Name != null && x.Name.Contains(q.Keyword!)));
  522. var total = await query.CountAsync();
  523. var list = await query.OrderBy(x => x.Number).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  524. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  525. }
  526. [HttpGet("{id:long}")]
  527. public async Task<IActionResult> GetAsync(long id)
  528. {
  529. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  530. return OkOrNotFound(await _rep.ByIdScopedByColumnAsync(id, tenantId));
  531. }
  532. [HttpGet("options")]
  533. public async Task<IActionResult> GetOptionsAsync()
  534. {
  535. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  536. return Ok(await BuildOptionsAsync(_rep.AsQueryable().Where(x => x.TenantId == tenantId), x => x.Id, x => $"{x.Number} / {x.Name}"));
  537. }
  538. [HttpPost]
  539. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsInspectionFrequencyUpsertDto dto)
  540. {
  541. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  542. var entity = new AdoS0QmsInspectionFrequency();
  543. ApplyInspectionFrequency(entity, dto, true);
  544. entity.TenantId = tenantId;
  545. await _rep.AsInsertable(entity).ExecuteReturnEntityAsync();
  546. return Ok(entity);
  547. }
  548. [HttpPut("{id:long}")]
  549. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsInspectionFrequencyUpsertDto dto)
  550. {
  551. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  552. var entity = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  553. if (entity == null) return NotFound();
  554. ApplyInspectionFrequency(entity, dto, false);
  555. await _rep.AsUpdateable(entity).ExecuteCommandAsync();
  556. return Ok(entity);
  557. }
  558. [HttpDelete("{id:long}")]
  559. public async Task<IActionResult> DeleteAsync(long id)
  560. {
  561. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  562. return await DeleteByIdAsync(_rep, id, tenantId);
  563. }
  564. private static void ApplyInspectionFrequency(AdoS0QmsInspectionFrequency entity, AdoS0QmsInspectionFrequencyUpsertDto dto, bool isCreate)
  565. {
  566. entity.Number = dto.Number.Trim();
  567. entity.Name = dto.Name.Trim();
  568. entity.Remark = NullIfWhiteSpace(dto.Remark);
  569. entity.Status = NullIfWhiteSpace(dto.Status);
  570. entity.EnableStatus = NullIfWhiteSpace(dto.EnableStatus);
  571. if (isCreate) entity.CreateTime = DateTime.Now;
  572. entity.ModifyTime = DateTime.Now;
  573. }
  574. }
  575. internal static partial class AdoS0QmsControllerHelpers
  576. {
  577. /// <summary>租户内按主键删除:越租户的 id 一律按 NotFound 处理,不泄露存在性。</summary>
  578. internal static async Task<IActionResult> DeleteByIdAsync<TEntity>(SqlSugarRepository<TEntity> rep, long id, long tenantId) where TEntity : class, new()
  579. {
  580. var item = await rep.ByIdScopedByColumnAsync(id, tenantId);
  581. if (item == null) return new NotFoundResult();
  582. await rep.DeleteAsync(item);
  583. return new OkObjectResult(new { message = "删除成功" });
  584. }
  585. internal static IActionResult OkOrNotFound<TEntity>(TEntity? entity) where TEntity : class => entity == null ? new NotFoundResult() : new OkObjectResult(entity);
  586. internal static string? NullIfWhiteSpace(string? value) => string.IsNullOrWhiteSpace(value) ? null : value.Trim();
  587. internal static async Task<List<AdoS0QualitySimpleOptionDto>> BuildOptionsAsync<TEntity>(
  588. ISugarQueryable<TEntity> query,
  589. Expression<Func<TEntity, long>> valueExp,
  590. Expression<Func<TEntity, string>> labelExp) where TEntity : class, new()
  591. {
  592. var rows = await query.ToListAsync();
  593. var valueGetter = valueExp.Compile();
  594. var labelGetter = labelExp.Compile();
  595. return rows.Select(x => new AdoS0QualitySimpleOptionDto
  596. {
  597. Value = valueGetter(x),
  598. Label = labelGetter(x)
  599. }).OrderBy(x => x.Label).ToList();
  600. }
  601. }