From 7e4cdf4c4fed3b7d181bfcf9e9c026254c173be5 Mon Sep 17 00:00:00 2001 From: nns Date: Fri, 9 Oct 2026 03:23:35 +0500 Subject: [PATCH] =?UTF-8?q?fix(tests):=20=D0=BF=D0=BE=D1=87=D0=B8=D0=BD?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=8E=D0=BD=D0=B8=D1=82-=D1=85=D0=B0=D1=80?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=D1=81=D0=B0,=20=D0=B2=D1=81=D0=BA=D1=80?= =?UTF-8?q?=D1=8B=D1=82=D0=B0=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB?= =?UTF-8?q?=D1=8F=D1=86=D0=B8=D0=B5=D0=B9=20UnitTests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Два предсуществующих бага, незаметных пока UnitTests не компилировался (с pass 1 конструктор StockService требовал новый параметр): - MoneyConfigurations: CHECK ck_money_link_single_target использовал Postgres-only `::int` — SQLite (EnsureCreated в юнит-тестах) падал 'unrecognized token ":"'. Переписан на портируемый CASE WHEN (семантика та же, что в миграции Phase33a). - ApiReferenceDocsJob: regex прав требовал `[RequiresPermission(...)]` в отдельных скобках и пропускал комбинированную форму `[HttpGet, RequiresPermission("X")]` (её используют в т.ч. контроллеры negative-stock). Убраны обязательные скобки. Юнит-сьют снова зелёный: 297/297. Co-Authored-By: Claude Opus 4.8 --- src/food-market.api/Background/ApiReferenceDocsJob.cs | 5 ++++- .../Persistence/Configurations/MoneyConfigurations.cs | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/food-market.api/Background/ApiReferenceDocsJob.cs b/src/food-market.api/Background/ApiReferenceDocsJob.cs index fd5e79d..00a2dc9 100644 --- a/src/food-market.api/Background/ApiReferenceDocsJob.cs +++ b/src/food-market.api/Background/ApiReferenceDocsJob.cs @@ -147,7 +147,10 @@ private static IEnumerable ScanDir(string dir) .Where(s => !string.IsNullOrEmpty(s))).Trim('/'); } - var permMatch = Regex.Match(attrs, @"\[RequiresPermission\(""([^""]+)""\)\]"); + // Без обязательных внешних скобок — атрибут часто комбинируется: + // `[HttpGet, RequiresPermission("StocksView")]`. С `\[...\]` такие + // пропускались (Permission пустел). + var permMatch = Regex.Match(attrs, @"RequiresPermission\(""([^""]+)""\)"); var perm = permMatch.Success ? permMatch.Groups[1].Value : ""; var docRaw = m.Groups["doc"].Value; diff --git a/src/food-market.infrastructure/Persistence/Configurations/MoneyConfigurations.cs b/src/food-market.infrastructure/Persistence/Configurations/MoneyConfigurations.cs index fd3395b..4a1440d 100644 --- a/src/food-market.infrastructure/Persistence/Configurations/MoneyConfigurations.cs +++ b/src/food-market.infrastructure/Persistence/Configurations/MoneyConfigurations.cs @@ -85,10 +85,13 @@ public static void ConfigureMoney(this ModelBuilder b) e.HasOne(x => x.Supply).WithMany().HasForeignKey(x => x.SupplyId).OnDelete(DeleteBehavior.Restrict); e.HasOne(x => x.SupplierReturn).WithMany().HasForeignKey(x => x.SupplierReturnId).OnDelete(DeleteBehavior.Restrict); - // CHECK: ровно одна целевая ссылка должна быть заполнена. + // CHECK: ровно одна целевая ссылка должна быть заполнена. Портируемое + // выражение (CASE WHEN вместо Postgres-only `::int`) — чтобы схему можно + // было построить и на SQLite (юнит-тесты через EnsureCreated), и на + // Postgres. Семантика идентична `::int`-варианту из миграции Phase33a. e.ToTable(t => t.HasCheckConstraint( "ck_money_link_single_target", - "((\"SupplyId\" IS NOT NULL)::int + (\"SupplierReturnId\" IS NOT NULL)::int) = 1")); + "((CASE WHEN \"SupplyId\" IS NOT NULL THEN 1 ELSE 0 END) + (CASE WHEN \"SupplierReturnId\" IS NOT NULL THEN 1 ELSE 0 END)) = 1")); e.HasIndex(x => new { x.OrganizationId, x.SupplyId }) .HasFilter("\"SupplyId\" IS NOT NULL");