fix(money): список счетов 500 на непустых данных (EF.Property xmin в памяти)
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions

MoneyAccountsController.List проецировал xmin через EF.Property ПОСЛЕ
ToListAsync на AsNoTracking-сущности → InvalidOperationException (shadow-
свойство вне трекера). С пустым списком не всплывало (нет строк), с данными —
500, и ломались ВСЕ money-страницы, дёргающие useMoneyAccounts (счета/смены/
платежи) — поймал menu-walk на stage. Переносим xmin в server-side Select.
Регресс закрыт: date-only тест теперь ещё и GET-ит список с данными.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nns 2026-10-07 22:40:25 +05:00
parent 174cb563bf
commit 4a064de96b
2 changed files with 21 additions and 3 deletions

View file

@ -103,7 +103,16 @@ public record MoneyAccountInput(
var items = await q
.OrderBy(x => x.a.Kind).ThenBy(x => x.a.Name)
.Skip(req.Skip).Take(req.Take)
.Select(x => new { x.a, x.cu, StoreName = x.st != null ? x.st.Name : null })
// xmin проецируем ВНУТРИ запроса (через SQL) — иначе EF.Property на
// AsNoTracking-сущности в памяти кидает (shadow-свойство не хранится
// вне трекера). С пустым списком не всплывало (нет строк); с данными
// — 500 на каждой money-странице, использующей список счетов.
.Select(x => new
{
x.a, x.cu,
StoreName = x.st != null ? x.st.Name : null,
Xmin = Microsoft.EntityFrameworkCore.EF.Property<uint>(x.a, "xmin"),
})
.ToListAsync(ct);
var rows = items.Select(x =>
@ -116,7 +125,7 @@ public record MoneyAccountInput(
x.cu.Id, x.cu.Code,
x.a.OpeningBalance, x.a.OpeningDate, current,
x.a.IsActive, x.a.IsDefault,
Microsoft.EntityFrameworkCore.EF.Property<uint>(x.a, "xmin"));
x.Xmin);
}).ToList();
return new PagedResult<MoneyAccountRow>

View file

@ -59,7 +59,16 @@ public async Task Account_create_accepts_date_only_opening_date_from_ui()
isActive = true, isDefault = false,
});
resp.IsSuccessStatusCode.Should().BeTrue($"date-only openingDate должен приниматься: {(int)resp.StatusCode} {await resp.Content.ReadAsStringAsync()}");
(await resp.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("currentBalance").GetDecimal().Should().Be(50_000m);
var created = await resp.Content.ReadFromJsonAsync<JsonElement>();
created.GetProperty("currentBalance").GetDecimal().Should().Be(50_000m);
// Регресс: список счетов С ДАННЫМИ не должен падать (xmin проецировался
// в памяти на AsNoTracking → 500; с пустым списком не всплывало).
using var list = await api.Http.GetAsync("/api/money/accounts?pageSize=50");
list.IsSuccessStatusCode.Should().BeTrue($"список счетов с данными должен отдаваться: {(int)list.StatusCode}");
var listed = await api.ListAsync("/api/money/accounts?pageSize=50");
listed.Select(x => x.GetProperty("id").GetString())
.Should().Contain(created.GetProperty("id").GetString());
}
[Fact]