fix(inventory): записывать автора движения (CauseUserId) для всех документов
CauseUserId в уведомлениях о минусах был null: StockService писал автора только если вызывающий явно передал CreatedByUserId в черновике, а большинство документов (касса/списание/перемещение/приёмка/…) его не передавали. Теперь автор берётся из черновика, иначе — из текущего пользователя (ITenantContext.UserId) в единой точке ApplyMovementAsync, поэтому пишется и в StockMovement, и в алерт для всех типов документов. Тест: минус от списания → causeUserId = текущий юзер. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4aceda3e41
commit
9dc8f6e044
|
|
@ -22,6 +22,10 @@ public StockService(AppDbContext db, ITenantContext tenant, INegativeStockAlertS
|
|||
public async Task<decimal> ApplyMovementAsync(StockMovementDraft d, CancellationToken ct = default)
|
||||
{
|
||||
var orgId = _tenant.OrganizationId ?? throw new InvalidOperationException("Tenant not set.");
|
||||
// Автор движения: берём из черновика, иначе — текущий пользователь (JWT). Так
|
||||
// автор пишется для ВСЕХ документов (касса/списание/перемещение/приёмка/…),
|
||||
// даже если вызывающий его явно не указал — иначе CauseUserId в алертах был null.
|
||||
var userId = d.CreatedByUserId ?? _tenant.UserId;
|
||||
|
||||
_db.StockMovements.Add(new StockMovement
|
||||
{
|
||||
|
|
@ -35,7 +39,7 @@ public async Task<decimal> ApplyMovementAsync(StockMovementDraft d, Cancellation
|
|||
DocumentId = d.DocumentId,
|
||||
DocumentNumber = d.DocumentNumber,
|
||||
OccurredAt = d.OccurredAt ?? DateTime.UtcNow,
|
||||
CreatedByUserId = d.CreatedByUserId,
|
||||
CreatedByUserId = userId,
|
||||
Notes = d.Notes,
|
||||
});
|
||||
|
||||
|
|
@ -61,7 +65,7 @@ public async Task<decimal> ApplyMovementAsync(StockMovementDraft d, Cancellation
|
|||
// Предупреждение об отрицательном остатке: единая точка детекции для всех
|
||||
// документов. Остаток < 0 → открыть/обновить алерт; ≥ 0 → закрыть.
|
||||
await _negAlerts.OnStockLevelAsync(d.StoreId, d.ProductId, stock.Quantity,
|
||||
d.DocumentType, d.DocumentId, d.DocumentNumber, d.CreatedByUserId, d.OccurredAt, ct);
|
||||
d.DocumentType, d.DocumentId, d.DocumentNumber, userId, d.OccurredAt, ct);
|
||||
|
||||
return stock.Quantity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,12 @@ public async Task Loss_into_negative_is_allowed_creates_alert_recount_and_resolv
|
|||
alerts[0].GetProperty("quantity").GetDecimal().Should().Be(-3m);
|
||||
alerts[0].GetProperty("productId").GetString().Should().Be(p);
|
||||
alerts[0].GetProperty("causeDocType").GetString().Should().Be("loss");
|
||||
// Автор документа записан (раньше CauseUserId был null). Сверяем с /api/me.
|
||||
var me = await api.GetJsonAsync("/api/me");
|
||||
var myId = me.GetProperty("sub").GetString();
|
||||
alerts[0].TryGetProperty("causeUserId", out var cu).Should().BeTrue();
|
||||
cu.GetString().Should().NotBeNullOrEmpty("автор минусового документа должен быть записан");
|
||||
cu.GetString().Should().Be(myId, "автор — текущий пользователь");
|
||||
|
||||
// «Пересчитать эти товары» → черновик инвентаризации с этим товаром.
|
||||
var rc = await api.Http.PostAsJsonAsync("/api/negative-stock/recount", new { storeId = refs.StoreId });
|
||||
|
|
|
|||
Loading…
Reference in a new issue