ListFormun birden fazla SubFormların FormReport raporu hatası giderildi.

This commit is contained in:
Sedat ÖZTÜRK 2026-10-02 12:29:22 +03:00
parent d331fb62d4
commit 5e6e3970c5
8 changed files with 29 additions and 10 deletions

View file

@ -378,7 +378,7 @@ Wizard varsayılan olarak `DefaultFieldPermissionJson(permissionName)` üretir.
| `TabType` | Sekmenin görünümü — `ListFormTabTypeEnum`: `List` \| `Card` \| `Tree` \| `Gantt` \| `Scheduler` \| `Todo` \| `Form` \| `Chart` \| `Pivot`. `Form` ana kayda bağlı **tek** kaydı gösterir: kayıt yokken "Yeni" düğmesi (hedef ekranda `AllowAdding` açıksa), kayıt varken yalnızca düzenleme; ikinci kayıt açılmaz |
| `TabTitle` | Dil anahtarı |
| `Code` | Hedef `ListFormCode` |
| `IsRefresh` | Ana kayıt değişince yenilensin |
| `IsRefresh` | Ana kayıt değişince yenilensin. MCP `deploy_wizard` yeni alt form bağlantısını `false` yazar; var olan bağlantıda önceki değer korunur |
| `Relation[]` | `ParentFieldName` → `ChildFieldName` + `DbType` (`System.Data.DbType`, **sayı**; bileşik anahtarda birden çok satır) |
Alt formun kendisi de bir ListForm'dur: `IsSubForm = true` olmalı ve genellikle `CreateMenu:

View file

@ -1849,7 +1849,7 @@ Wizard Manager'daki talep silmesini kullanır.
"TabType": "List", // List|Card|Tree|Gantt|Scheduler|Todo|Form|Chart|Pivot
"TabTitle": "App.Mrp.OrderItems", // dil anahtarı
"Code": "App.Mrp.OrderItems", // hedef ListFormCode
"IsRefresh": true, // ana kayıt değişince yenilensin
"IsRefresh": false, // ana kayıt değişince yenilensin; MCP yeni bağlantıda false yazar
"Relation": [
{ "ParentFieldName": "Id", "ChildFieldName": "OrderId", "DbType": 11 }
]

View file

@ -211,9 +211,18 @@ public class McpDevelopAppService(
// Menu sirasi modelin karari degildir: yeni ekran kardeslerinin sonuna eklenir (deploy
// bagimlilik sirasiyla yapildigi icin lookup kaynagi tuketen ekranin ustunde kalir),
// guncelleme ekranin mevcut yerini korur.
wizard.MenuOrder = wizard.EditFileName is null
? 0
: (await wizardAppService.GetFile(wizard.EditFileName)).Wizard?.MenuOrder ?? 0;
var previous = wizard.EditFileName is null ? null : (await wizardAppService.GetFile(wizard.EditFileName)).Wizard;
wizard.MenuOrder = previous?.MenuOrder ?? 0;
// Alt form sekmesi ana kayit her degistiginde yeniden sorgulanmaz; MCP yeni baglanti
// acarken yenilemeyi kapali yazar. Var olan baglantida kullanicinin ekrandan verdigi
// deger korunur.
var previousRefresh = (previous?.SubForms ?? [])
.Where(subForm => !string.IsNullOrWhiteSpace(subForm.Code))
.GroupBy(subForm => subForm.Code, StringComparer.OrdinalIgnoreCase)
.ToDictionary(group => group.Key, group => group.First().IsRefresh, StringComparer.OrdinalIgnoreCase);
foreach (var subForm in wizard.SubForms ?? [])
subForm.IsRefresh = subForm.Code is not null && previousRefresh.GetValueOrDefault(subForm.Code);
// Tek gruplu duzenleme formunda grup basligi popup basligini tekrarlar; baslik yalnizca
// birden fazla grubu birbirinden ayirmak icin yazilir.

View file

@ -27,6 +27,11 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
private readonly HashSet<string> _registeredConnections;
private readonly object _lock = new object();
// Bağlantı ve transaction bu örneğe aittir ve kapsamı kapanınca dispose edilir; aynı UoW içinde
// ikinci bir DI kapsamı (ör. form raporunun alt form raporları) aynı anahtarla AddTransactionApi
// çağırıp UoW'yi reddettirmesin diye anahtar örneğe özgüdür.
private readonly string _instanceId = Guid.NewGuid().ToString("N");
public bool IsDisposed { get; private set; }
public MsDynamicDataRepository(
@ -45,7 +50,7 @@ public class MsDynamicDataRepository : IDynamicDataRepository, IScopedDependency
private string BuildKey(string cs)
{
var uowId = _unitOfWorkManager.Current?.GetHashCode() ?? 0;
return $"Dapper_{uowId}_{cs}";
return $"Dapper_{uowId}_{_instanceId}_{cs}";
}
private async Task<SqlConnection> GetOrCreateConnectionAsync(string cs)

View file

@ -27,6 +27,11 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
private readonly HashSet<string> _registeredConnections;
private readonly object _lock = new object();
// Bağlantı ve transaction bu örneğe aittir ve kapsamı kapanınca dispose edilir; aynı UoW içinde
// ikinci bir DI kapsamı (ör. form raporunun alt form raporları) aynı anahtarla AddTransactionApi
// çağırıp UoW'yi reddettirmesin diye anahtar örneğe özgüdür.
private readonly string _instanceId = Guid.NewGuid().ToString("N");
public bool IsDisposed { get; private set; }
public PgDynamicDataRepository(
@ -44,7 +49,7 @@ public class PgDynamicDataRepository : IDynamicDataRepository, IScopedDependency
private string BuildKey(string cs)
{
var uowId = _unitOfWorkManager.Current?.GetHashCode() ?? 0;
return $"Dapper_{uowId}_{cs}";
return $"Dapper_{uowId}_{_instanceId}_{cs}";
}
private async Task<NpgsqlConnection> GetOrCreateConnectionAsync(string cs)

View file

@ -701,7 +701,7 @@ public class DynamicFormReport : XtraReport
var lookup = DynamicReportImageHelper.GetLookup(field);
var isMultiValue = IsMultiValueLookupEditor(editorType);
if (lookup == null || selectField?.JoinOptions != null)
if (lookup == null || selectField?.IsJoined == true)
{
return new FormReportField(field, bindingName, editorType, columnSpan, null, null, isMultiValue, DynamicReportImageHelper.IsImageEditor(editorType));
}

View file

@ -44,7 +44,7 @@ internal static class DynamicReportColumnFactory
var isImage = DynamicReportImageHelper.IsImageEditor(editorType);
var isHtml = editorType == PlatformConsts.EditorTypes.dxHtmlEditor;
if (lookup == null || selectField?.JoinOptions != null)
if (lookup == null || selectField?.IsJoined == true)
{
return new DynamicReportColumn(field, bindingName, null, null, isMultiValue, isImage, isHtml, editorType);
}

View file

@ -95,7 +95,7 @@ internal static class DynamicReportImageHelper
public static string GetReportFieldName(SelectField selectField)
{
if (selectField?.JoinOptions != null && !string.IsNullOrWhiteSpace(selectField.JoinOptions.FieldNameAlias))
if (selectField?.IsJoined == true && !string.IsNullOrWhiteSpace(selectField.JoinOptions.FieldNameAlias))
{
return selectField.JoinOptions.FieldNameAlias;
}