Görünüm
Modül eklenti mimarisi
Kimin içinBT
CukoZ Suite’e yeni işlevler, çekirdeğe dokunmadan eklenti modülü olarak eklenebilir. Bu sayfa CukoZ.Suite/ARCHITECTURE.md §12 ve §12.1’in özetidir.
Nasıl çalışır?
- Eklenti modülleri ayrı projelerdir:
modules/<Ad>/CukoZ.Suite.Modules.<Ad>.csproj. - Yalnızca
CukoZ.Suite.ModuleKit’e başvururlar; API projesine asla başvurmazlar. - Başlangıçta
Composition/SuiteModules.cs,CukoZ.Suite.Modules.*.dlldosyalarını tarar (derleme zamanı başvurusu olmadan) ve her biri için:IModuleDefinition’ı kaydeder,AddServices’i çağırır,- denetleyicileri
AddApplicationPartile ekler, - modülün kendi şemasını migrate eder.
- DLL’i silmek modülü kaldırır. Dockerfile
modules/*altındaki her şeyi yayınlar.
ModuleKit sözleşmeleri
| Tür | Görev |
|---|---|
ISuiteModule { Definition; AddServices(services, config) } | Modülün giriş noktası |
ModuleDbContext | Kendi şeması, kendi __migrations tablosu, aynı kiracı filtresi; SuiteModel.Std; çekirdek işleme katılmak için EnlistAsync |
AddModuleDbContext<T>(config, schema) | DbContext kaydı |
IDomainEventHandler<T> | Çekirdek olaylarını dinleme |
ModuleGateAttribute, FeatureGateAttribute, PermissionGateAttribute | Modül / özellik / izin kapıları |
İletişim tek yönlüdür: çekirdek olay yayınlar (örn. OrderClosed), modüller dinler. Modüller birbirini çağırmaz.
Örnek modül
Şablon: tests/CukoZ.Suite.Modules.Ornek/OrnekModule.cs
- Tanım:
Key = "ornek", bir menü öğesi vekayitözelliği - Kendi varlığı ve DbContext’i
OrderClosedişleyicisi[ModuleGate("ornek")]+[PermissionGate("reports.view")]ile korunan bir denetleyici
csharp
// Kısaltılmış alıntı — tests/CukoZ.Suite.Modules.Ornek/OrnekModule.cs
public sealed class OrnekModule : ISuiteModule
{
public IModuleDefinition Definition { get; } = new OrnekDefinition();
public void AddServices(IServiceCollection services, IConfiguration configuration)
{
services.AddModuleDbContext<OrnekDbContext>(configuration, "ornek");
// Restorana olaylarla bağlanır; restoran bu modülün varlığını bilmez.
services.AddScoped<IDomainEventHandler<OrderClosed>, OrderClosedHandler>();
}
}
public sealed class OrnekDefinition : IModuleDefinition
{
public string Key => "ornek";
public string DisplayName => "Örnek modül";
public IReadOnlyList<ModuleNavItem> NavItems => [new("Örnek", "/ornek", "box", 900)];
public IReadOnlyList<ModuleFeature> Features => [new("kayit", "Kapanan adisyon kaydı", "Kapanan her adisyonun örnek kaydı.")];
// …
}
public sealed class OrderClosedHandler(OrnekDbContext db, CukozSuiteDbContext core, ModuleRegistry modules)
: IDomainEventHandler<OrderClosed>
{
public async Task HandleAsync(OrderClosed e, CancellationToken ct)
{
if (!await modules.IsEnabledAsync(e.OrganizationId, "ornek", ct)) return;
await db.EnlistAsync(core, ct); // çekirdekle aynı işlem
db.Notes.Add(ClosedOrderNote.Create(e.OrganizationId, e.OrderId, e.TableId));
await db.SaveChangesAsync(ct);
}
}
[ApiController, Route("api/v1/ornek"), ModuleGate("ornek")]
public sealed class OrnekController(OrnekDbContext db) : ControllerBase { /* … */ }Modül yazım kuralları (§12)
- Her varlık
OrganizationEntity’den türer. - Ham SQL’de kiracı koşulu açıkça eklenir.
- Bellek içi paylaşılan durum yoktur (yalnızca veritabanı veya
IDistributedCache). - Dış yan etkiler outbox üzerinden; işleyiciler idempotent.
- Modülden modüle doğrudan çağrı yoktur (olay veya outbox).
- Listeler sayfalıdır (en fazla 200).
- Numaralandırmada
SequenceGeneratorkullanılır. - Rol adı değil izin dizesi kontrol edilir.
- Tüm zamanlar UTC.
- Para, kuruş cinsinden
long. - Kapalı modül gerçekten
402döndürür. subyerineUser.GetUserId()kullanılır.- Konuma bağlı varlıklar
IBranchScoped+RequireBranchId().
Mimari testler
tests/CukoZ.Suite.ArchitectureTests/ModuleIsolationTests.cs (NetArchTest):
Core_never_depends_on_add_on_modulesAdd_on_modules_never_depend_on_the_apiAdd_on_modules_do_not_depend_on_each_otherDomain_modules_are_isolated_from_each_otherLayers_point_inwardsSample_module_is_discovered_and_tenant_isolated
Belgelenmiş tarihsel istisnalar: Adisyon ↔ Cari/Sadakat, Rezervasyon → Adisyon, Muhasebe birçok modülü okur, Raporlar tasarım gereği salt okunurdur.
Modülü satışa açmak
Modülün bir işletmede açılması CukoZ One yetkilendirmesiyle olur: Suite planının yetkilendirmelerine "module.<key>": "true" ekleyin veya modül anahtarıyla aynı anahtara sahip bir eklenti ürünü (add-on) olarak satın. Kapalı modüle yapılan istekler 402 module_not_enabled döner ve menüde görünmez.

