using Admin.NET.Plugin.AiDOP.FinishedWarehouse.Dto; namespace Admin.NET.Plugin.AiDOP.FinishedWarehouse; /// /// S7 生产入库单列表 只读 list 服务。 /// /// 数据源(2026-07-30 起):DOP 数据中台标准层 mdp_std_production_receipt(扁平,一行=一条 NbrDetail 明细)。 /// 该 std 由 ProductionReceiptMdpSyncService 从 aidopdev.NbrMaster/NbrDetail Type='WOI'(生产入库)同步标准化而来,且已双源(dopdemorq)。 /// S7 成品入库与 S5 生产收货读同一批 WOI 数据(过滤逐字相同)→ CTO 拍板复用该 std、不另建管线/实体(S5-list 与 S7-list 展示同一 WOI 单据的两个视角)。 /// /// 口径映射(std 列 → 列表列):入库单号=nbr;行号=line;入库日期=receipt_date;状态=status;入库类型=remark; /// 生产线=prod_line;工单号=work_ord;ERP工单号=erp_work_ord;物料编码=item_num;名称=item_name;规格=item_spec; /// 入库库位=location_to;批次=lot_serial;入库数量=qty_rec;单位=um;相关单号=ord_nbr。 /// /// 本服务仅 SELECT:无新增/编辑/删除/入库写入/库存事务/状态流转。租户口径对齐 ProductionReceiptService: /// 仅当 input.TenantId>0 才按 m.tenant_id 过滤(receipt std tenant 由同步入站上下文赋值,默认租户可能空态)。 /// [ApiDescriptionSettings(Order = 310, Description = "生产入库单列表")] [Route("api/S7ProductionInbound")] [AllowAnonymous] [NonUnify] public class ProductionInboundService : IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; public ProductionInboundService(ISqlSugarClient db) { _db = db; } /// /// 生产入库单列表(只读分页查询,扁平:一行=一条明细;读数据中台标准层 mdp_std_production_receipt)。 /// [DisplayName("生产入库单列表")] [HttpGet("list")] public async Task GetList([FromQuery] ProductionInboundListInput 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.InboundNo)) { where.Add("m.nbr LIKE @InboundNo"); pars.Add(new SugarParameter("@InboundNo", $"%{input.InboundNo.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.WorkOrderNo)) { where.Add("m.work_ord LIKE @WorkOrderNo"); pars.Add(new SugarParameter("@WorkOrderNo", $"%{input.WorkOrderNo.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.ErpWorkOrderNo)) { where.Add("m.erp_work_ord LIKE @ErpWorkOrderNo"); pars.Add(new SugarParameter("@ErpWorkOrderNo", $"%{input.ErpWorkOrderNo.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.Batch)) { where.Add("m.lot_serial LIKE @Batch"); pars.Add(new SugarParameter("@Batch", $"%{input.Batch.Trim()}%")); } if (!string.IsNullOrWhiteSpace(input.InboundDateStart)) { where.Add("m.receipt_date >= @InboundDateStart"); pars.Add(new SugarParameter("@InboundDateStart", $"{input.InboundDateStart.Trim()} 00:00:00")); } if (!string.IsNullOrWhiteSpace(input.InboundDateEnd)) { where.Add("m.receipt_date <= @InboundDateEnd"); pars.Add(new SugarParameter("@InboundDateEnd", $"{input.InboundDateEnd.Trim()} 23:59:59")); } var whereSql = string.Join(" AND ", where); var total = await _db.Ado.GetIntAsync( $"SELECT COUNT(1) FROM mdp_std_production_receipt m WHERE {whereSql}", pars); var list = await _db.Ado.SqlQueryAsync( $""" SELECT m.nbr AS InboundNo, m.line AS LineNo, m.receipt_date AS InboundDate, m.status AS Status, m.remark AS InboundType, m.prod_line AS ProductionLine, m.work_ord AS WorkOrderNo, m.erp_work_ord AS ErpWorkOrderNo, m.item_num AS MaterialCode, m.item_name AS MaterialName, m.item_spec AS Spec, m.location_to AS InboundLocation, m.lot_serial AS Batch, m.qty_rec AS Qty, m.um AS Unit, m.ord_nbr AS RelatedBillNo, m.create_time AS CreateTime FROM mdp_std_production_receipt m WHERE {whereSql} ORDER BY m.nbr DESC, m.line LIMIT {pageSize} OFFSET {offset} """, pars); return new { total, page, pageSize, list }; } }