using Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Entity;
namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting.Idempotency;
///
/// IQC 过账头幂等存储抽象。唯一性由 (tenant_id, domain_code, fbillno) 的 DB UNIQUE 保证;
/// TryInsertAsync 依赖唯一约束原子占位——**不是** SELECT-不存在-INSERT(无并发窗口)。
/// 生产实现走 SqlSugar + duplicate-key(1062) 捕获;测试实现走线程安全内存。
///
public interface IIqcPostingStore
{
/// 尝试插入过账头(PROCESSING)。UNIQUE 冲突 → Inserted=false 并尽量带出既有记录。
Task TryInsertAsync(AdoIqcInventoryPosting posting);
/// 按幂等键读取既有过账头。
Task GetAsync(long tenantId, string domainCode, string fbillNo);
/// 业务提交成功/失败后回写过账状态(POSTED / FAILED)。
Task UpdateStatusAsync(AdoIqcInventoryPosting posting, string status);
///
/// 原子抢占 stale PROCESSING(Phase 7C):仅当 status=PROCESSING 且 update_time <
/// 时把 update_time 刷新为 并返回 true(心跳续租=抢占成功)。**单条件更新原子完成**,
/// 不做 SELECT-then-UPDATE,杜绝竞态窗口——并发多路仅一路 rows=1。lease 未过期或已被他路抢占 → false。
///
Task TryRecoverStaleAsync(long tenantId, string domainCode, string fbillNo, DateTime staleBefore, DateTime now);
}