using Admin.NET.Plugin.AiDOP.ProcurementExecution.Dto;
using Admin.NET.Plugin.AiDOP.ProcurementExecution.Entity;
using Admin.NET.Plugin.AiDOP.Supply;
namespace Admin.NET.Plugin.AiDOP.ProcurementExecution;
///
/// S4 采购退货单(PurOrdRctMaster / PurOrdRctDetail,RctType=pt)
/// 路由:/api/ProcurementExecution/purchase-return/...
///
/// 【租户安全边界】租户一律经 从认证后 JWT 解析,
/// 无有效租户即拒绝,不读前端 tenantId、无默认回退。
///
/// 原实现:类级 [AllowAnonymous] + 全类 AidopTenantHelper.Resolve(App.HttpContext)。
/// 后者的解析顺序为 requestTenantId > JWT claim > query 参数 tenantId > DefaultTenantId 兜底,
/// 其自身注释即写明「允许前端指定租户且有默认回退,不得用于业务数据的查询与写入」。
/// 两者叠加的后果:匿名(无 Token、无 Cookie)?tenantId=<任意租户> 即可读写该租户的采购退货单
/// (含 purchase-return/save、purchase-return/delete 写端点)。
///
///
[ApiDescriptionSettings(Order = 321, Description = "S4采购退货单")]
[Route("api/ProcurementExecution")]
[NonUnify]
public class PurchaseReturnService : IDynamicApiController, ITransient
{
/// 采购退货单号:PT + yyyyMMdd + 4 位流水,如 PT202605190001。
private const int PtReceiverSerialWidth = 4;
private readonly ISqlSugarClient _db;
private readonly SqlSugarRepository _masterRep;
private readonly SqlSugarRepository _detailRep;
private readonly UserManager _userManager;
public PurchaseReturnService(
ISqlSugarClient db,
SqlSugarRepository masterRep,
SqlSugarRepository detailRep,
UserManager userManager)
{
_db = db;
_masterRep = masterRep;
_detailRep = detailRep;
_userManager = userManager;
}
private static string NormalizeOrderBy(string field, string order)
{
var col = (field ?? "").Trim();
var ord = string.Equals(order?.Trim(), "desc", StringComparison.OrdinalIgnoreCase) ? "DESC" : "ASC";
var map = new Dictionary(StringComparer.OrdinalIgnoreCase)
{
// 注意:列表 SQL 外层包了 SELECT * FROM (...) t,因此 ORDER BY 只能引用外层可见列名
["receiver"] = "Receiver",
["rctdate"] = "RctDate",
["ordnbr"] = "OrdNbr",
["itemnum"] = "ItemNum",
["rctqty"] = "RctQty",
["suppname"] = "SuppName",
};
if (!map.TryGetValue(col, out var sqlCol))
return "ORDER BY RctDate DESC, DetailRecId ASC";
return $"ORDER BY {sqlCol} {ord}, DetailRecId ASC";
}
[DisplayName("采购退货单分页列表")]
[HttpGet("purchase-return/list")]
public async Task