AdoS0QualityFqcOqcControllers.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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 static Admin.NET.Plugin.AiDOP.Controllers.S0.Quality.AdoS0QmsControllerHelpers;
  5. namespace Admin.NET.Plugin.AiDOP.Controllers.S0.Quality;
  6. [ApiController]
  7. [Route("api/s0/quality/fqc-inspection-specs")]
  8. [NonUnify]
  9. public class AdoS0QmsFqcInspectionSpecsController : ControllerBase
  10. {
  11. private readonly SqlSugarRepository<AdoS0QmsFqcInspectionSpec> _rep;
  12. private readonly SqlSugarRepository<AdoS0QmsFqcInspectionSpecEntry> _entryRep;
  13. public AdoS0QmsFqcInspectionSpecsController(
  14. SqlSugarRepository<AdoS0QmsFqcInspectionSpec> rep,
  15. SqlSugarRepository<AdoS0QmsFqcInspectionSpecEntry> entryRep)
  16. {
  17. _rep = rep;
  18. _entryRep = entryRep;
  19. }
  20. [HttpGet]
  21. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  22. {
  23. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  24. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  25. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  26. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  27. (x.FileNumber != null && x.FileNumber.Contains(q.Keyword!))
  28. || (x.ApplicableModel != null && x.ApplicableModel.Contains(q.Keyword!))
  29. || (x.MaterialCode != null && x.MaterialCode.Contains(q.Keyword!)));
  30. var total = await query.CountAsync();
  31. var list = await query.OrderByDescending(x => x.Id).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  32. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  33. }
  34. [HttpGet("{id:long}")]
  35. public async Task<IActionResult> GetDetailAsync(long id)
  36. {
  37. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  38. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  39. if (master == null) return NotFound();
  40. var items = await _entryRep.AsQueryable().Where(x => x.MasterId == id).OrderBy(x => x.Id).ToListAsync();
  41. return Ok(new { master, items });
  42. }
  43. [HttpPost]
  44. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsFqcInspectionSpecUpsertDto dto)
  45. {
  46. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  47. var items = AdoS0QmsSpecAggregateGuard.Meaningful(dto.Items);
  48. var guardError = AdoS0QmsSpecAggregateGuard.ValidateCreate(FqcRequiredFields(dto), items.Count);
  49. if (guardError != null) return AdoS0ApiErrors.InvalidRequest(guardError);
  50. var db = _rep.Context;
  51. await db.Ado.BeginTranAsync();
  52. try
  53. {
  54. var master = new AdoS0QmsFqcInspectionSpec();
  55. ApplyFqcSpec(master, dto);
  56. master.TenantId = tenantId;
  57. await _rep.AsInsertable(master).ExecuteReturnEntityAsync();
  58. await SyncFqcEntriesAsync(master.Id, items, tenantId);
  59. await db.Ado.CommitTranAsync();
  60. return await GetDetailAsync(master.Id);
  61. }
  62. catch
  63. {
  64. await db.Ado.RollbackTranAsync();
  65. throw;
  66. }
  67. }
  68. [HttpPut("{id:long}")]
  69. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsFqcInspectionSpecUpsertDto dto)
  70. {
  71. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  72. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  73. if (master == null) return NotFound();
  74. var existingItemCount = await _entryRep.AsQueryable().Where(x => x.MasterId == id).CountAsync();
  75. var items = AdoS0QmsSpecAggregateGuard.Meaningful(dto.Items);
  76. var guardError = AdoS0QmsSpecAggregateGuard.ValidateUpdate(
  77. [
  78. ("文件编号", master.FileNumber, dto.FileNumber),
  79. ("物料编码", master.MaterialCode, dto.MaterialCode),
  80. ("版本", master.VersionNo, dto.VersionNo)
  81. ],
  82. existingItemCount,
  83. items.Count);
  84. if (guardError != null) return AdoS0ApiErrors.InvalidRequest(guardError);
  85. var db = _rep.Context;
  86. await db.Ado.BeginTranAsync();
  87. try
  88. {
  89. ApplyFqcSpec(master, dto);
  90. await _rep.AsUpdateable(master).ExecuteCommandAsync();
  91. await _entryRep.AsDeleteable().Where(x => x.MasterId == id).ExecuteCommandAsync();
  92. await SyncFqcEntriesAsync(id, items, tenantId);
  93. await db.Ado.CommitTranAsync();
  94. return await GetDetailAsync(id);
  95. }
  96. catch
  97. {
  98. await db.Ado.RollbackTranAsync();
  99. throw;
  100. }
  101. }
  102. [HttpDelete("{id:long}")]
  103. public async Task<IActionResult> DeleteAsync(long id)
  104. {
  105. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  106. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  107. if (master == null) return NotFound();
  108. var db = _rep.Context;
  109. await db.Ado.BeginTranAsync();
  110. try
  111. {
  112. await _entryRep.AsDeleteable().Where(x => x.MasterId == id).ExecuteCommandAsync();
  113. await _rep.DeleteAsync(master);
  114. await db.Ado.CommitTranAsync();
  115. return Ok(new { message = "删除成功" });
  116. }
  117. catch
  118. {
  119. await db.Ado.RollbackTranAsync();
  120. throw;
  121. }
  122. }
  123. /// <summary>FQC 检规必填集(UAT-S0-10 拍板;本轮不含「适用型号」,缺业务依据)。</summary>
  124. private static IReadOnlyList<(string, string?)> FqcRequiredFields(AdoS0QmsFqcInspectionSpecUpsertDto dto) =>
  125. [
  126. ("文件编号", dto.FileNumber),
  127. ("物料编码", dto.MaterialCode),
  128. ("版本", dto.VersionNo),
  129. ];
  130. private static void ApplyFqcSpec(AdoS0QmsFqcInspectionSpec entity, AdoS0QmsFqcInspectionSpecUpsertDto dto)
  131. {
  132. entity.ApplicableModel = NullIfWhiteSpace(dto.ApplicableModel);
  133. entity.FileNumber = NullIfWhiteSpace(dto.FileNumber);
  134. entity.VersionNo = NullIfWhiteSpace(dto.VersionNo);
  135. entity.EffectiveDate = NullIfWhiteSpace(dto.EffectiveDate);
  136. entity.Attachment = NullIfWhiteSpace(dto.Attachment);
  137. entity.MaterialCode = NullIfWhiteSpace(dto.MaterialCode);
  138. entity.Attachment2 = NullIfWhiteSpace(dto.Attachment2);
  139. entity.Version = dto.Version;
  140. }
  141. private async Task SyncFqcEntriesAsync(long masterId, IEnumerable<AdoS0QmsFqcInspectionSpecEntryDto> items, long tenantId)
  142. {
  143. foreach (var item in items)
  144. {
  145. var entity = new AdoS0QmsFqcInspectionSpecEntry
  146. {
  147. TenantId = tenantId,
  148. MasterId = masterId,
  149. OperationCode = NullIfWhiteSpace(item.OperationCode),
  150. OperationName = NullIfWhiteSpace(item.OperationName),
  151. InspectionItem = NullIfWhiteSpace(item.InspectionItem),
  152. InspectionMethod = NullIfWhiteSpace(item.InspectionMethod),
  153. InspectionSpec = NullIfWhiteSpace(item.InspectionSpec),
  154. ImageCategory = NullIfWhiteSpace(item.ImageCategory),
  155. InspectionFrequency = NullIfWhiteSpace(item.InspectionFrequency),
  156. TechnicalStandard = NullIfWhiteSpace(item.TechnicalStandard),
  157. PeelingForce = item.PeelingForce,
  158. UpperLimit = NullIfWhiteSpace(item.UpperLimit),
  159. LowerLimit = NullIfWhiteSpace(item.LowerLimit)
  160. };
  161. await _entryRep.AsInsertable(entity).ExecuteCommandAsync();
  162. }
  163. }
  164. }
  165. [ApiController]
  166. [Route("api/s0/quality/oqc-inspection-specs")]
  167. [NonUnify]
  168. public class AdoS0QmsOqcInspectionSpecsController : ControllerBase
  169. {
  170. private readonly SqlSugarRepository<AdoS0QmsOqcInspectionSpec> _rep;
  171. private readonly SqlSugarRepository<AdoS0QmsOqcInspectionSpecEntry> _entryRep;
  172. public AdoS0QmsOqcInspectionSpecsController(
  173. SqlSugarRepository<AdoS0QmsOqcInspectionSpec> rep,
  174. SqlSugarRepository<AdoS0QmsOqcInspectionSpecEntry> entryRep)
  175. {
  176. _rep = rep;
  177. _entryRep = entryRep;
  178. }
  179. [HttpGet]
  180. public async Task<IActionResult> GetPagedAsync([FromQuery] AdoS0QualityPagedQueryDto q)
  181. {
  182. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  183. (q.Page, q.PageSize) = PagingGuard.Normalize(q.Page, q.PageSize);
  184. var query = _rep.AsQueryable().Where(x => x.TenantId == tenantId)
  185. .WhereIF(!string.IsNullOrWhiteSpace(q.Keyword), x =>
  186. (x.FileNumber != null && x.FileNumber.Contains(q.Keyword!))
  187. || (x.ApplicableModel != null && x.ApplicableModel.Contains(q.Keyword!))
  188. || (x.MaterialCode != null && x.MaterialCode.Contains(q.Keyword!)));
  189. var total = await query.CountAsync();
  190. var list = await query.OrderByDescending(x => x.Id).Skip((q.Page - 1) * q.PageSize).Take(q.PageSize).ToListAsync();
  191. return Ok(new { total, page = q.Page, pageSize = q.PageSize, list });
  192. }
  193. [HttpGet("{id:long}")]
  194. public async Task<IActionResult> GetDetailAsync(long id)
  195. {
  196. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  197. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  198. if (master == null) return NotFound();
  199. var items = await _entryRep.AsQueryable().Where(x => x.MasterId == id).OrderBy(x => x.Id).ToListAsync();
  200. return Ok(new { master, items });
  201. }
  202. [HttpPost]
  203. public async Task<IActionResult> CreateAsync([FromBody] AdoS0QmsOqcInspectionSpecUpsertDto dto)
  204. {
  205. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  206. var items = AdoS0QmsSpecAggregateGuard.Meaningful(dto.Items);
  207. var guardError = AdoS0QmsSpecAggregateGuard.ValidateCreate(OqcRequiredFields(dto), items.Count);
  208. if (guardError != null) return AdoS0ApiErrors.InvalidRequest(guardError);
  209. var db = _rep.Context;
  210. await db.Ado.BeginTranAsync();
  211. try
  212. {
  213. var master = new AdoS0QmsOqcInspectionSpec();
  214. ApplyOqcSpec(master, dto);
  215. master.TenantId = tenantId;
  216. await _rep.AsInsertable(master).ExecuteReturnEntityAsync();
  217. await SyncOqcEntriesAsync(master.Id, items, tenantId);
  218. await db.Ado.CommitTranAsync();
  219. return await GetDetailAsync(master.Id);
  220. }
  221. catch
  222. {
  223. await db.Ado.RollbackTranAsync();
  224. throw;
  225. }
  226. }
  227. [HttpPut("{id:long}")]
  228. public async Task<IActionResult> UpdateAsync(long id, [FromBody] AdoS0QmsOqcInspectionSpecUpsertDto dto)
  229. {
  230. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  231. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  232. if (master == null) return NotFound();
  233. var existingItemCount = await _entryRep.AsQueryable().Where(x => x.MasterId == id).CountAsync();
  234. var items = AdoS0QmsSpecAggregateGuard.Meaningful(dto.Items);
  235. var guardError = AdoS0QmsSpecAggregateGuard.ValidateUpdate(
  236. [
  237. ("文件编号", master.FileNumber, dto.FileNumber),
  238. ("物料编码", master.MaterialCode, dto.MaterialCode),
  239. ("版本", master.VersionNo, dto.VersionNo)
  240. ],
  241. existingItemCount,
  242. items.Count);
  243. if (guardError != null) return AdoS0ApiErrors.InvalidRequest(guardError);
  244. var db = _rep.Context;
  245. await db.Ado.BeginTranAsync();
  246. try
  247. {
  248. ApplyOqcSpec(master, dto);
  249. await _rep.AsUpdateable(master).ExecuteCommandAsync();
  250. await _entryRep.AsDeleteable().Where(x => x.MasterId == id).ExecuteCommandAsync();
  251. await SyncOqcEntriesAsync(id, items, tenantId);
  252. await db.Ado.CommitTranAsync();
  253. return await GetDetailAsync(id);
  254. }
  255. catch
  256. {
  257. await db.Ado.RollbackTranAsync();
  258. throw;
  259. }
  260. }
  261. [HttpDelete("{id:long}")]
  262. public async Task<IActionResult> DeleteAsync(long id)
  263. {
  264. if (!AdoS0TenantScope.TryResolveRequired(out var tenantId, out var tenantError)) return tenantError!;
  265. var master = await _rep.ByIdScopedByColumnAsync(id, tenantId);
  266. if (master == null) return NotFound();
  267. var db = _rep.Context;
  268. await db.Ado.BeginTranAsync();
  269. try
  270. {
  271. await _entryRep.AsDeleteable().Where(x => x.MasterId == id).ExecuteCommandAsync();
  272. await _rep.DeleteAsync(master);
  273. await db.Ado.CommitTranAsync();
  274. return Ok(new { message = "删除成功" });
  275. }
  276. catch
  277. {
  278. await db.Ado.RollbackTranAsync();
  279. throw;
  280. }
  281. }
  282. /// <summary>OQC 检规必填集(UAT-S0-10 拍板;本轮不含「适用型号」,缺业务依据)。</summary>
  283. private static IReadOnlyList<(string, string?)> OqcRequiredFields(AdoS0QmsOqcInspectionSpecUpsertDto dto) =>
  284. [
  285. ("文件编号", dto.FileNumber),
  286. ("物料编码", dto.MaterialCode),
  287. ("版本", dto.VersionNo),
  288. ];
  289. private static void ApplyOqcSpec(AdoS0QmsOqcInspectionSpec entity, AdoS0QmsOqcInspectionSpecUpsertDto dto)
  290. {
  291. entity.ApplicableModel = NullIfWhiteSpace(dto.ApplicableModel);
  292. entity.FileNumber = NullIfWhiteSpace(dto.FileNumber);
  293. entity.VersionNo = NullIfWhiteSpace(dto.VersionNo);
  294. entity.EffectiveDate = NullIfWhiteSpace(dto.EffectiveDate);
  295. entity.Attachment = NullIfWhiteSpace(dto.Attachment);
  296. entity.MaterialCode = NullIfWhiteSpace(dto.MaterialCode);
  297. entity.Attachment2 = NullIfWhiteSpace(dto.Attachment2);
  298. entity.Version = dto.Version;
  299. }
  300. private async Task SyncOqcEntriesAsync(long masterId, IEnumerable<AdoS0QmsOqcInspectionSpecEntryDto> items, long tenantId)
  301. {
  302. foreach (var item in items)
  303. {
  304. var entity = new AdoS0QmsOqcInspectionSpecEntry
  305. {
  306. TenantId = tenantId,
  307. MasterId = masterId,
  308. OperationCode = NullIfWhiteSpace(item.OperationCode),
  309. OperationName = NullIfWhiteSpace(item.OperationName),
  310. InspectionItem = NullIfWhiteSpace(item.InspectionItem),
  311. InspectionMethod = NullIfWhiteSpace(item.InspectionMethod),
  312. InspectionSpec = NullIfWhiteSpace(item.InspectionSpec),
  313. ImageCategory = NullIfWhiteSpace(item.ImageCategory),
  314. InspectionFrequency = NullIfWhiteSpace(item.InspectionFrequency),
  315. TechnicalStandard = NullIfWhiteSpace(item.TechnicalStandard),
  316. PeelingForce = item.PeelingForce,
  317. UpperLimit = NullIfWhiteSpace(item.UpperLimit),
  318. LowerLimit = NullIfWhiteSpace(item.LowerLimit)
  319. };
  320. await _entryRep.AsInsertable(entity).ExecuteCommandAsync();
  321. }
  322. }
  323. }