ResourceOvertimeService.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. namespace Admin.NET.Plugin.AiDOP.Production;
  2. /// <summary>
  3. /// 产线加班(ResourceOccupancyTime)
  4. /// 路由前缀:/api/Production/overtime/...
  5. /// </summary>
  6. [ApiDescriptionSettings(Order = 270, Description = "产线加班")]
  7. [Route("api/Production")]
  8. [AllowAnonymous]
  9. [NonUnify]
  10. public class ResourceOvertimeService : IDynamicApiController, ITransient
  11. {
  12. private readonly ISqlSugarClient _db;
  13. private readonly UserManager _userManager;
  14. public ResourceOvertimeService(ISqlSugarClient db, UserManager userManager)
  15. {
  16. _db = db;
  17. _userManager = userManager;
  18. }
  19. [DisplayName("产线加班列表")]
  20. [HttpGet("overtime/list")]
  21. public async Task<object> GetList([FromQuery] ResourceOvertimeListInput input)
  22. {
  23. var tenantId = _userManager.TenantId;
  24. var pars = new List<SugarParameter> { new("@TenantId", tenantId) };
  25. var where = "r.IsActive = 1 AND r.tenant_id = @TenantId";
  26. if (!string.IsNullOrWhiteSpace(input.Resource))
  27. {
  28. where += " AND r.Resource = @Resource";
  29. pars.Add(new SugarParameter("@Resource", input.Resource.Trim()));
  30. }
  31. if (!string.IsNullOrWhiteSpace(input.StartTimeFrom))
  32. {
  33. where += " AND r.StartTime >= @StartTimeFrom";
  34. pars.Add(new SugarParameter("@StartTimeFrom", input.StartTimeFrom.Trim()));
  35. }
  36. if (!string.IsNullOrWhiteSpace(input.EndTimeFrom))
  37. {
  38. where += " AND r.EndTime >= @EndTimeFrom";
  39. pars.Add(new SugarParameter("@EndTimeFrom", input.EndTimeFrom.Trim()));
  40. }
  41. if (!string.IsNullOrWhiteSpace(input.ResourceType))
  42. {
  43. where += " AND r.ResourceType LIKE @ResourceType";
  44. pars.Add(new SugarParameter("@ResourceType", $"%{input.ResourceType.Trim()}%"));
  45. }
  46. var orderClause = ResolveOrder(input.OrderBy, input.Sort);
  47. var offset = (input.Page - 1) * input.PageSize;
  48. var baseSql = $"""
  49. SELECT
  50. r.RecID AS Id,
  51. r.`Domain`,
  52. r.Site,
  53. r.BusinessID,
  54. r.ResourceType,
  55. r.Resource,
  56. r.StartTime,
  57. r.EndTime,
  58. r.Descr,
  59. r.IsRest,
  60. r.IsActive,
  61. r.IsConfirm,
  62. r.IsChanged,
  63. r.Ufld1,
  64. r.Ufld2,
  65. ROUND(CAST(IFNULL(r.Ufld1, 0) AS DECIMAL(20, 10)) * 60, 0) AS Time1,
  66. ROUND(CAST(IFNULL(r.Ufld2, 0) AS DECIMAL(20, 10)) * 60, 0) AS Time2,
  67. r.CreateUser,
  68. r.UpdateUser,
  69. r.CreateTime,
  70. r.UpdateTime
  71. FROM ResourceOccupancyTime r
  72. WHERE {where}
  73. """;
  74. var total = await _db.Ado.GetIntAsync($"SELECT COUNT(*) FROM ({baseSql}) AS t", pars);
  75. var list = await _db.Ado.SqlQueryAsync<ResourceOvertimeListRow>(
  76. $"SELECT * FROM ({baseSql}) AS t ORDER BY {orderClause} LIMIT {input.PageSize} OFFSET {offset}", pars);
  77. return new { total, page = input.Page, pageSize = input.PageSize, list };
  78. }
  79. [DisplayName("产线加班详情")]
  80. [HttpGet("overtime/{id:long}")]
  81. public async Task<object> GetDetail(long id)
  82. {
  83. var tenantId = _userManager.TenantId;
  84. var row = (await _db.Ado.SqlQueryAsync<ResourceOvertimeDetailRow>(
  85. """
  86. SELECT RecID AS Id, `Domain`, Site, ResourceType, Resource, StartTime, EndTime, Descr,
  87. Ufld1, Ufld2,
  88. ROUND(CAST(IFNULL(Ufld1, 0) AS DECIMAL(20, 10)) * 60, 0) AS WorkMinutes,
  89. ROUND(CAST(IFNULL(Ufld2, 0) AS DECIMAL(20, 10)) * 60, 0) AS RestMinutes
  90. FROM ResourceOccupancyTime
  91. WHERE RecID = @Id AND tenant_id = @TenantId
  92. """,
  93. new List<SugarParameter> { new("@Id", id), new("@TenantId", tenantId) })).FirstOrDefault()
  94. ?? throw Oops.Oh("记录不存在");
  95. return row;
  96. }
  97. [DisplayName("保存产线加班")]
  98. [HttpPost("overtime/save")]
  99. public async Task<object> Save([FromBody] ResourceOvertimeSaveInput input)
  100. {
  101. var account = Truncate(_userManager.Account ?? "system", 8);
  102. var now = DateTime.Now;
  103. var domain = Truncate(input.Domain.Trim(), 8);
  104. var site = string.IsNullOrWhiteSpace(input.Site) ? null : Truncate(input.Site.Trim(), 8);
  105. var resource = Truncate(input.Resource.Trim(), 20);
  106. var resType = string.IsNullOrWhiteSpace(input.ResourceType) ? "" : Truncate(input.ResourceType.Trim(), 20);
  107. var descr = string.IsNullOrWhiteSpace(input.Descr) ? "-" : Truncate(input.Descr.Trim(), 60);
  108. var ufld1Hours = input.WorkMinutes.HasValue ? input.WorkMinutes.Value / 60m : (decimal?)null;
  109. var ufld2Hours = input.RestMinutes.HasValue ? input.RestMinutes.Value / 60m : (decimal?)null;
  110. var tenantId = _userManager.TenantId;
  111. if (input.Id is null or 0)
  112. {
  113. await _db.Ado.ExecuteCommandAsync(
  114. """
  115. INSERT INTO ResourceOccupancyTime (
  116. `Domain`, Site, BusinessID, ResourceType, Resource, StartTime, EndTime, Descr,
  117. IsRest, IsActive, IsConfirm, IsChanged, Ufld1, Ufld2,
  118. CreateUser, CreateTime, UpdateUser, UpdateTime, tenant_id
  119. ) VALUES (
  120. @Domain, @Site, 0, @ResourceType, @Resource, @StartTime, @EndTime, @Descr,
  121. 0, 1, 0, 0, @Ufld1, @Ufld2,
  122. @User, @Now, @User, @Now, @TenantId
  123. )
  124. """,
  125. new List<SugarParameter>
  126. {
  127. new("@Domain", domain),
  128. new("@Site", (object?)site ?? DBNull.Value),
  129. new("@ResourceType", resType),
  130. new("@Resource", resource),
  131. new("@StartTime", (object?)input.StartTime ?? DBNull.Value),
  132. new("@EndTime", (object?)input.EndTime ?? DBNull.Value),
  133. new("@Descr", descr),
  134. new("@Ufld1", (object?)ufld1Hours ?? DBNull.Value),
  135. new("@Ufld2", (object?)ufld2Hours ?? DBNull.Value),
  136. new("@User", account),
  137. new("@Now", now),
  138. new("@TenantId", tenantId)
  139. });
  140. var newId = await _db.Ado.GetIntAsync("SELECT LAST_INSERT_ID()");
  141. return new { id = (long)newId, message = "新增成功" };
  142. }
  143. var n = await _db.Ado.ExecuteCommandAsync(
  144. """
  145. UPDATE ResourceOccupancyTime
  146. SET `Domain` = @Domain,
  147. Site = @Site,
  148. ResourceType = @ResourceType,
  149. Resource = @Resource,
  150. StartTime = @StartTime,
  151. EndTime = @EndTime,
  152. Descr = @Descr,
  153. Ufld1 = @Ufld1,
  154. Ufld2 = @Ufld2,
  155. UpdateUser = @User,
  156. UpdateTime = @Now
  157. WHERE RecID = @Id AND tenant_id = @TenantId
  158. """,
  159. new List<SugarParameter>
  160. {
  161. new("@Id", input.Id!.Value),
  162. new("@Domain", domain),
  163. new("@Site", (object?)site ?? DBNull.Value),
  164. new("@ResourceType", resType),
  165. new("@Resource", resource),
  166. new("@StartTime", (object?)input.StartTime ?? DBNull.Value),
  167. new("@EndTime", (object?)input.EndTime ?? DBNull.Value),
  168. new("@Descr", descr),
  169. new("@Ufld1", (object?)ufld1Hours ?? DBNull.Value),
  170. new("@Ufld2", (object?)ufld2Hours ?? DBNull.Value),
  171. new("@User", account),
  172. new("@Now", now),
  173. new("@TenantId", tenantId)
  174. });
  175. if (n == 0)
  176. throw Oops.Oh("记录不存在或未变更");
  177. return new { id = input.Id, message = "保存成功" };
  178. }
  179. [DisplayName("删除产线加班")]
  180. [HttpPost("overtime/delete/{id:long}")]
  181. public async Task<object> Delete(long id)
  182. {
  183. var tenantId = _userManager.TenantId;
  184. var n = await _db.Ado.ExecuteCommandAsync(
  185. "UPDATE ResourceOccupancyTime SET IsActive = 0, UpdateTime = @Now WHERE RecID = @Id AND tenant_id = @TenantId",
  186. new List<SugarParameter> { new("@Id", id), new("@Now", DateTime.Now), new("@TenantId", tenantId) });
  187. if (n == 0)
  188. throw Oops.Oh("记录不存在");
  189. return new { message = "已删除" };
  190. }
  191. [DisplayName("生产线列表")]
  192. [HttpGet("overtime/lines")]
  193. public async Task<object> GetLines([FromQuery] string? domain)
  194. {
  195. var tenantId = _userManager.TenantId;
  196. var pars = new List<SugarParameter> { new("@TenantId", tenantId) };
  197. var where = "IsActive = 1 AND tenant_id = @TenantId";
  198. if (!string.IsNullOrWhiteSpace(domain))
  199. {
  200. where += " AND `Domain` = @Domain";
  201. pars.Add(new SugarParameter("@Domain", domain.Trim()));
  202. }
  203. var rows = await _db.Ado.SqlQueryAsync<LineKvOvertime>(
  204. $"SELECT `Line` AS Value, `Line` AS Label, `Domain` AS Extra FROM LineMaster WHERE {where} ORDER BY `Line`", pars);
  205. return new { list = rows };
  206. }
  207. private static string Truncate(string s, int maxLen) =>
  208. s.Length <= maxLen ? s : s[..maxLen];
  209. private static string ResolveOrder(string? orderBy, string? sort)
  210. {
  211. var desc = string.Equals(sort?.Trim(), "desc", StringComparison.OrdinalIgnoreCase);
  212. var dir = desc ? "DESC" : "ASC";
  213. var key = orderBy?.Trim().ToLowerInvariant();
  214. var col = key switch
  215. {
  216. "resource" => "t.Resource",
  217. "starttime" => "t.StartTime",
  218. "endtime" => "t.EndTime",
  219. "resourcetype" => "t.ResourceType",
  220. _ => "t.Id"
  221. };
  222. return $"{col} {dir}";
  223. }
  224. private sealed class ResourceOvertimeListRow
  225. {
  226. public long Id { get; set; }
  227. public string? Domain { get; set; }
  228. public string? Site { get; set; }
  229. public long BusinessID { get; set; }
  230. public string? ResourceType { get; set; }
  231. public string? Resource { get; set; }
  232. public DateTime? StartTime { get; set; }
  233. public DateTime? EndTime { get; set; }
  234. public string? Descr { get; set; }
  235. public bool IsRest { get; set; }
  236. public bool IsActive { get; set; }
  237. public bool IsConfirm { get; set; }
  238. public bool IsChanged { get; set; }
  239. public string? Ufld1 { get; set; }
  240. public string? Ufld2 { get; set; }
  241. public decimal? Time1 { get; set; }
  242. public decimal? Time2 { get; set; }
  243. public string? CreateUser { get; set; }
  244. public string? UpdateUser { get; set; }
  245. public DateTime? CreateTime { get; set; }
  246. public DateTime? UpdateTime { get; set; }
  247. }
  248. private sealed class ResourceOvertimeDetailRow
  249. {
  250. public long Id { get; set; }
  251. public string? Domain { get; set; }
  252. public string? Site { get; set; }
  253. public string? ResourceType { get; set; }
  254. public string? Resource { get; set; }
  255. public DateTime? StartTime { get; set; }
  256. public DateTime? EndTime { get; set; }
  257. public string? Descr { get; set; }
  258. public string? Ufld1 { get; set; }
  259. public string? Ufld2 { get; set; }
  260. public decimal? WorkMinutes { get; set; }
  261. public decimal? RestMinutes { get; set; }
  262. }
  263. private sealed class LineKvOvertime
  264. {
  265. public string? Value { get; set; }
  266. public string? Label { get; set; }
  267. public string? Extra { get; set; }
  268. }
  269. }