using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto; namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse; /// /// S5 生产领料单 只读 list 服务。 /// /// 数据源:DOP 数据中台标准层 mdp_std_production_issue(头级)。 /// 由 ProductionIssueMdpSyncService 从 aidopdev.NbrMaster Type='SM' 同步标准化而来。 /// /// 本服务仅 SELECT:无新增/编辑/删除/发料确认/库存事务/状态流转/明细。 /// 领料单为头级列表(一单一行),不 JOIN 明细,无重复。 /// [ApiDescriptionSettings(Order = 305, Description = "生产领料单")] [Route("api/ProductionIssue")] [AllowAnonymous] [NonUnify] public class ProductionIssueService : IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; public ProductionIssueService(ISqlSugarClient db) { _db = db; } /// /// 生产领料单列表(只读分页查询)。 /// [DisplayName("生产领料单列表")] [HttpGet("list")] public async Task GetList([FromQuery] ProductionIssueListInput input) { var page = input.Page <= 0 ? 1 : input.Page; var pageSize = input.PageSize <= 0 ? 10 : input.PageSize; var offset = (page - 1) * pageSize; var where = new List { "1=1" }; var pars = new List(); if (input.TenantId is > 0) { where.Add("m.tenant_id = @TenantId"); pars.Add(new SugarParameter("@TenantId", input.TenantId)); } if (!string.IsNullOrWhiteSpace(input.Nbr)) { where.Add("m.nbr LIKE @Nbr"); pars.Add(new SugarParameter("@Nbr", $"%{input.Nbr.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.WorkOrd)) { where.Add("m.work_ord LIKE @WorkOrd"); pars.Add(new SugarParameter("@WorkOrd", $"%{input.WorkOrd.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.Status)) { where.Add("m.status = @Status"); pars.Add(new SugarParameter("@Status", input.Status.Trim())); } if (!string.IsNullOrWhiteSpace(input.ProdLine)) { where.Add("m.prod_line LIKE @ProdLine"); pars.Add(new SugarParameter("@ProdLine", $"%{input.ProdLine.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.DateFrom)) { where.Add("m.issue_date >= @DateFrom"); pars.Add(new SugarParameter("@DateFrom", $"{input.DateFrom.Trim()} 00:00:00")); } if (!string.IsNullOrWhiteSpace(input.DateTo)) { where.Add("m.issue_date <= @DateTo"); pars.Add(new SugarParameter("@DateTo", $"{input.DateTo.Trim()} 23:59:59")); } var whereSql = string.Join(" AND ", where); var total = await _db.Ado.GetIntAsync( $"SELECT COUNT(1) FROM mdp_std_production_issue m WHERE {whereSql}", pars); var list = await _db.Ado.SqlQueryAsync( $""" SELECT m.id AS Id, m.nbr AS Nbr, m.issue_date AS IssueDate, m.status_desc AS StatusDesc, m.work_ord AS WorkOrd, m.department_desc AS DepartmentDesc, m.prod_line AS ProdLine, m.qty_ord AS QtyOrd, m.issue_user AS IssueUser, m.remark AS Remark, m.create_user AS CreateUser, m.source_create_time AS CreateTime FROM mdp_std_production_issue m WHERE {whereSql} ORDER BY {BuildOrderBy(input.OrderBy, input.OrderDir)} LIMIT {pageSize} OFFSET {offset} """, pars); return new { total, page, pageSize, list }; } /// /// 排序白名单:仅允许按已展示列排序,杜绝 SQL 注入;非法字段回落默认。 /// private static string BuildOrderBy(string? orderBy, string? orderDir) { var column = orderBy switch { "nbr" => "m.nbr", "issueDate" => "m.issue_date", "status" => "m.status", "workOrd" => "m.work_ord", "prodLine" => "m.prod_line", "createTime" => "m.source_create_time", _ => "m.issue_date", }; var direction = string.Equals(orderDir, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC"; return $"{column} {direction}, m.id DESC"; } }