using Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto;
namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse;
///
/// S5 盘点结果查询 只读 list 服务。
///
/// 数据源:aidopdev.MissedPrint(盘点标签 IsTag=1),LEFT JOIN ItemMaster(名称/规格/单位)。
/// 证据 sql.txt 原始口径是 m.Domain=@Domain AND m.IsTag=1,本实现改按租户,理由见 GetList 内注释。
/// 盘点口径由 SQL 内定义(非脑补):
/// 账面(标签数量)=Qty;实盘数量=CompQty;差异数量=CompQty-Qty;
/// 盘点状态=CompQty≠Qty?'有差异':'正常';状态=Status='Q'?'冻结':'';实际库位=FirmString2;实际货架=FirmString4。
/// 排序 UpdateTime DESC, RecID DESC。
///
/// 本服务仅 SELECT:无新增/编辑/删除/库存事务/状态流转。
/// 租户边界 = MissedPrint.tenant_id(正式租户列,已由生成标签写入 + 1.0.442 回填,152 行 0 NULL)。
/// 类级已去 [AllowAnonymous]:原先该接口可被**完全未认证**调用(实测匿名 GET 返回 200),已收敛为需认证。
///
[ApiDescriptionSettings(Order = 304, Description = "盘点结果查询")]
[Route("api/S5StocktakeResult")]
[NonUnify]
public class StocktakeResultService : IDynamicApiController, ITransient
{
/// 主/系统租户哨兵:超管未选择目标租户时其 JWT TenantId 即此值,拒绝作为业务租户。
private const long MainTenantId = 1300000000001L;
private readonly ISqlSugarClient _db;
private readonly UserManager _userManager;
public StocktakeResultService(ISqlSugarClient db, UserManager userManager)
{
_db = db;
_userManager = userManager;
}
/// 严格可信租户解析:只来自认证后 JWT;无 Token 或超管未选目标租户 → 拒绝,无默认回退。
private long ResolveTenantOrThrow()
{
var tid = _userManager.TenantId;
if (tid <= 0)
throw Oops.Oh("无法确定当前租户,请重新登录或选择目标租户");
if (_userManager.SuperAdmin && tid == MainTenantId)
throw Oops.Oh("超级管理员操作前必须选择目标租户");
return tid;
}
///
/// 盘点结果查询列表(只读分页查询)。
///
[DisplayName("盘点结果查询列表")]
[HttpGet("list")]
public async Task