İşe Alım modülü

This commit is contained in:
Sedat ÖZTÜRK 2026-10-04 11:14:38 +03:00
parent 130e23bc67
commit 16fd5df0c7
39 changed files with 31355 additions and 18 deletions

View file

@ -1263,7 +1263,7 @@ soneklerini alır.
| **Public › Sales Orders** | `App.Orders.SalesOrders` (alt form Sales Order Item) | `Sas_H_Order` + `Sas_H_OrderItem` | host | **Onay akışı + alt kalem + toplam + diyalog** birlikte kullanılan tam örnek (§12.7). |
| **Public › Blog Category / Posts** | `App.BlogManagement.Category` · `.Posts` | `Sas_H_BlogCategory` · `Sas_H_BlogPost` | host | Çok dilli içerik (`ContentTr`/`ContentEn`), slug, yayın durumu, sayaç alanları; public `/blog` bu tablolardan okur, yayınlanmış yazılar sitemap'e girer. |
| **Public › Demos** | `App.Demos` | `Sas_H_Demo` | host | Public `/demo` formundan gelen talepler — public form → tablo akışının örneği. |
| **Dev Requests** | `App.DevRequests` | `Sas_H_DevRequest` | host | **Kanban/Todo düzeninin** referansı (`DefaultLayout: todo`): `Status`, `Priority`, `SortOrder`, `Tags`, `Assignees`, `SubTasks`, `Timesheets`; detayda `Description` yanında `Analysis` sekmesi (`AnalysisExpr`). MCP geliştirme döngüsünün kuyruğudur (`Backlog` → `Analysis` MCP analiz eder, `Ready to Start`'a kullanıcı alır; `Ready to Start` → `Testing`, `Staging`'e kullanıcı alır; araç çubuğunda DB Migrate butonu vardır — `UiEvalService.ApiDbMigrate()`, `App.Setup.Migrate`; yalnızca `start_dev_request` başlatır; açıklamadaki base64 görseller MCP'ye resim içeriği olarak gider, analiz `save_dev_request_analysis` ile yazılır, üretim notu `append_dev_request_note` ile `Analysis`'e eklenir — `Description` talebin yazıldığı hâliyle kalır; `lowcode.instructions.md` §0.11–§0.12). |
| **Dev Requests** | `App.DevRequests` | `Sas_H_DevRequest` | host | **Kanban/Todo düzeninin** referansı (`DefaultLayout: todo`): `Status`, `Priority`, `SortOrder`, `Tags`, `Assignees`, `SubTasks`, `Timesheets`; detayda `Description` yanında `Analysis` sekmesi (`AnalysisExpr`). MCP geliştirme döngüsünün kuyruğudur (`Backlog` → `Analysis` MCP analiz eder, `Ready to Start`'a kullanıcı alır; `Ready to Start` → `Testing`, `Staging`'e kullanıcı alır; araç çubuğunda DB Migrate butonu vardır — `UiEvalService.ApiDbMigrate()`, önce onay sorar, `App.Setup.Migrate`; yalnızca `start_dev_request` başlatır; açıklamadaki base64 görseller MCP'ye resim içeriği olarak gider, analiz `save_dev_request_analysis` ile yazılır, üretim notu `append_dev_request_note` ile `Analysis`'e eklenir — `Description` talebin yazıldığı hâliyle kalır; `lowcode.instructions.md` §0.11–§0.12). |
| **Tenants** | `AbpTenantManagement.Tenants` | `AbpTenants` | host | Kiracı kaydı, bağlantı dizesi diyaloğu (`TenantsConnectionString`), alt form olarak şubeler; yazma `list-form-dynamic-api/tenant-*`. Ekranların `IsTenant` davranışının kaynağı. |
| **Branches** | `App.Branches` | `Sas_T_Branch` | tenant | Şube listesi. Ekranı `IsBranch = true` yaparsan filtre bu tablodan gelir; `BranchSeed` diyaloğu şube verisini kurar. |
| **Setting Definitions** | `App.SettingDefinitions` | `Sas_H_SettingDefinition` | host | Yeni uygulama ayarı: `Code`, `MainGroupKey`/`SubGroupKey`, `DataType`, `SelectOptions`, `DefaultValue`, `Providers`, `RequiredPermissionName`, `IsEncrypted`, `IsVisibleToClients`. Hazır tanımlar `data/App.SettingDefinitions.json`'dan gelir. Ayarlanabilir olması gereken değeri koda gömme. |
@ -1388,6 +1388,13 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `
| **Vehicles › Vehicle Movement** | `App.Hr.VehicleMovement` | `Hr_T_VehicleMovement` | tenant | Araç çıkış/giriş kaydı: çıkışta şube, tarih/saat, km, gönderen/güvenlik/şoför kullanıcıları, araç, gidilecek yer, sebep; girişte güvenlik, şube, tarih/saat, km; `TravelledKm`, `DurationMinutes`, `ExpectedKm` hesaplanır, `Status` (`Arrived`/`Left`). Wizard. |
| **Definitions › Penalty Type** | `App.Hr.DisciplinaryPenaltyType` | `Hr_T_DisciplinaryPenaltyType` | tenant | Disiplin cezası türü: `Name`, `Severity` (1–5), `Description`, `IsActive`. Karar alt formunun lookup'ı (aktifler, ağırlık sırasıyla). Wizard; seed `data/App.Hr.DisciplinaryPenaltyType.json` (sözlü/yazılı uyarı, ihtar, kınama, ücret kesintisi, fesih). |
| **Disciplinary Case** | `App.Hr.DisciplinaryCase` (alt formlar `App.Hr.DisciplinaryDefense`, `.DisciplinaryDecision`, `.DisciplinaryFile`) | `Hr_T_DisciplinaryCase` · `Hr_T_DisciplinaryDefense` · `Hr_T_DisciplinaryDecision` · `Hr_T_DisciplinaryFile` | tenant | Olay tutanağı: personel (`UserId` → `AbpUsers`, `DepartmentId`/`JobPositionId` kopyalanır), olay tarihi/saati/yeri, `Subject`, `IncidentDescription` (`dxHtmlEditor`), tanıklar (`WitnessUserIds` — `dxTagBox`), `ReportedById`, `Status` (`Open`/`AwaitingDefense`/`Decided`/`Closed`; Todo panosu bu kolonla). `CaseNo` (`DSP-{yyyy}-{00001}`, kiracı ve yıl bazında) `InsertAfterCommand` ile SQL'de üretilir — `Sequence` kiracıya kopyalanmadığı için numaratör kullanılmaz. Alt formlar: savunma (`RequestDate`, `DueDate` = talep + 2 gün, `ResponseDate`, `DefenseText`, `Status`), karar (`PenaltyTypeId`, karar/yürürlük/tebliğ tarihi, `DeductionAmount`, `Status` `Draft`/`Final`, onay süreci yok), belge (`DocumentTypeId` → `Hr_T_DocumentType`, dosya). Alt form yetkileri `App.Hr.DisciplinaryCase` altındadır. Wizard. |
| **Definitions › Candidate Source / Rejection Reason / Evaluation Criterion** | `App.Hr.CandidateSource` · `App.Hr.RejectionReason` · `App.Hr.EvaluationCriterion` | `Hr_T_CandidateSource` · `Hr_T_RejectionReason` · `Hr_T_EvaluationCriterion` | tenant | İşe alım tanımları: aday kaynağı (`Name`), ret sebebi (`Name`, `RejectedBy` = `Company`/`Candidate`), değerlendirme kriteri (`Name`, `Weight` — mülakat puanının ağırlığı). Hepsi `IsActive` + Toplam/Aktif/Pasif widget'ı, `SeedData` açık (`data/App.Hr.{CandidateSource,RejectionReason,EvaluationCriterion}.json`). Wizard. |
| **Recruitment › Staff Request** | `App.Hr.StaffRequest` | `Hr_T_StaffRequest` | tenant | Kadro talebi: `RequestNo` (`KT-YYYY-00001`, insert sonrası SQL), şube → departman → pozisyon cascade, `Headcount`, `EmploymentType`, `Reason` (`NewPosition`/`Replacement` + `ReplacedUserId`), ücret aralığı. **Grid Workflow** onayı: Start → Approval (`Onay Bekliyor`) → Inform → End `Onaylandı`/`Reddedildi`; durum `ApprovalStatus`, onaycı `ApprovalUser`. Onaycı düğümün `Approver` değeridir (seed'de platform admin e-postası — ListForm › Workflow sekmesinden değiştirilir); motor onaycıyı kayıttaki alandan okumaz. Wizard. |
| **Recruitment › Job Posting** | `App.Hr.JobPosting` (alt form `App.Hr.JobApplication`) | `Hr_T_JobPosting` | tenant | İlan: `PostingNo` (`ILN-…`), `StaffRequestId` (yalnızca `ApprovalStatus = 'Onaylandı'` talepler; seçilince şube/departman/pozisyon/adet/çalışma şekli `copy` ile dolar), `Status` (`Draft`/`Published`/`Closed`/`Cancelled`), yayın kanalları (`SourceIds`, `dxTagBox`), açıklama/nitelikler HTML. Wizard. |
| **Recruitment › Candidate** | `App.Hr.Candidate` (alt form `App.Hr.JobApplication`) | `Hr_T_Candidate` | tenant | Aday havuzu: kişisel bilgiler, eğitim/deneyim, `SkillIds` (`Hr_T_Skill`), fotoğraf, `CvDocument` (`dxImageUpload`, PDF/DOC kabul eder — görsel olmayan dosyada belge ikonu, tıklanınca blob olarak açılır), **KVKK**: `KvkkConsent` zorunlu (form + tabloda `CHECK (KvkkConsent = 1)`), `KvkkConsentDate`, `KvkkConsentMethod`, imzalı belge. E-posta kiracı içinde tekildir (filtreli unique index). `UserId` personel kaydıdır: kullanıcıyı BT elle açar, İK aday kaydını ona bağlar ("Personele Dönüşen" kartı bunu sayar). Satır butonu KVKK Açık Rıza Formu (`DynamicReport`). Wizard. |
| **Recruitment › Application** | `App.Hr.JobApplication` (alt formlar `App.Hr.Interview`, `App.Hr.JobOffer`) | `Hr_T_JobApplication` | tenant | Aday × ilan başvurusu (çift tekil). `Stage`: `Applied` → `Screening` → `Interview` → `Offer` → `Hired` / `Rejected`; **Todo (kanban) görünümü** aşama sütunlarıyla. Mülakat eklenince `Interview`, teklif eklenince `Offer`, teklif `Accepted` olunca `Hired`'a ilerler (after-command SQL, geri gitmez; insert sonrası komutlar yalnızca eklenen satıra `@Id` ile çalışır). `CandidateName`/`PostingTitle` kopyalanır (kanban başlığı). Ret sebebi yalnızca `Rejected` aşamasında düzenlenir. Alt form olduğu için widget yok. Wizard. |
| **Recruitment › Interview** | `App.Hr.Interview` (alt form `App.Hr.InterviewScore`) | `Hr_T_Interview` · `Hr_T_InterviewScore` | tenant | Mülakat planlama: tür, başlangıç/bitiş (**Scheduler** görünümü), mülakatçı, durum, öneri. Kayıt eklenince mülakatçıya `IseAlimMulakatAtandi` bildirimi SQL ile yazılır (tipin `Custom` kuralları kanalı belirler, metin `App.Hr.Interview.Notification.*`). Puan alt formu kriter başına 1–5; `OverallScore` = Σ(puan × ağırlık) / Σ ağırlık, başvurunun `AverageScore`'u mülakatların ortalaması. Wizard. |
| **Recruitment › Job Offer** | `App.Hr.JobOffer` | `Hr_T_JobOffer` | tenant | Teklif: `OfferNo` (`TKL-…`), başvuru seçilince pozisyon bilgileri ilandan `copy` ile dolar, brüt ücret + para birimi, yan haklar (`Hr_T_BenefitType` kodları), `Status` (`Draft`/`Sent`/`Accepted`/`Declined`/`Expired`, yanıt tarihi otomatik). İç onay **Grid Workflow** (Kadro Talebi ile aynı akış). Onaylı satırda **Teklif Mektubu** butonu (`DynamicReport`, `Raporlar` kategorisi). Wizard. |
| **Org Chart** | `App.Hr.OrgChart` · `/admin/organization` | `Hr_T_Department` · `Hr_T_JobPosition` | tenant | Departman/ünvan verisinin organizasyon şeması görünümü (özel React sayfası `hr/OrgChart`, veri `api/app/org-chart`). Menü ve route aynı yetkiyi ister. |
| **Intranet › Announcement** | `App.Hr.Intranet.Announcement` (alt formlar Like/Comment) | `Hr_T_Announcement` · `Hr_T_AnnouncementLike` · `Hr_T_AnnouncementComment` | tenant | Duyuru + beğeni + yorum: **ana kayıt / alt etkileşim** kalıbının hazır örneği. |
| **Intranet › Survey** | `App.Hr.Intranet.Survey` (alt form Question → Option; Response → Answer) | `Hr_T_Survey` · `Hr_T_SurveyQuestion` · `Hr_T_SurveyQuestionOption` · `Hr_T_SurveyResponse` · `Hr_T_SurveyAnswer` | tenant | Anket motoru; soru–seçenek–yanıt zinciri **iki seviyeli alt form** ihtiyacının referansıdır. |
@ -1504,6 +1511,7 @@ alanları da doldurur (`lowcode` §0.9).
| "departman, pozisyon/ünvan, yetkinlik, organizasyon şeması" | İK › Definitions · İK › Org Chart | Var olan `Hr_*` tablosuna lookup bağla (departman lookup'ı şubeye göre süzülebilir — `BranchDepartmentValues`); yenisini üretme |
| "izin türü, masraf türü, yan hak türü, vardiya, resmi tatil / çalışma takvimi" | İK › Definitions · İK › Work Calendar · İK › Shift | Var olan `Hr_T_WorkCalendar` / `Hr_T_LeaveType` / `Hr_T_ExpenseType` / `Hr_T_BenefitType` / `Hr_T_Shift` tablosuna lookup bağla; yenisini üretme |
| "eğitim / katılımcı, araç / şoför / araç masrafı / araç çıkış-giriş, olay günlüğü, disiplin / tutanak / savunma / ihtar" | İK › Trainings · İK › Vehicles · İK › Event Log · İK › Disciplinary Case | Var olan `Hr_T_Training*` / `Hr_T_Vehicle*` / `Hr_T_Driver*` / `Hr_T_EventLog` / `Hr_T_Disciplinary*` ekranını genişlet ya da lookup bağla; paralel tablo üretme |
| "işe alım, kadro talebi, ilan, aday / CV, mülakat, teklif" | İK › Recruitment | Var olan `Hr_T_StaffRequest` / `Hr_T_JobPosting` / `Hr_T_Candidate` / `Hr_T_JobApplication` / `Hr_T_Interview` / `Hr_T_JobOffer` ekranını genişlet; personel kullanıcısını BT elle açar, aday kaydına `UserId` ile bağlanır |
| "yapay zekâ cevaplasın" | Saas › Definitions › AiBot | Bot tanımı; `/admin/ai` bu tanımı kullanır |
### 12.7 Canlı referans uygulamalar

View file

@ -1276,7 +1276,7 @@ anahtarları listeler; ortak anahtarlar (§4.3.3) her editörde geçerlidir.
| `dxSlider` | Tek değerli kaydırıcı | Sayı | `min`, `max`, `tooltip.showMode` |
| `dxRangeSlider` | Aralık kaydırıcı | Sayı | `min`, `max`, `showRange` |
| `dxHtmlEditor` | Zengin metin | String (16) | `toolbar.items`, `toolbar.multiline`, `valueType` (`html`/`markdown`), `mediaResizing.enabled`, `imageUpload.tabs`, `imageUpload.uploadUrl`, `imageUpload.fileUploadMode`, `tableResizing.enabled`, `tableContextMenu.enabled`. Boş `editorOptions` da tam araç çubuğu, dosyadan/URL'den resim, resim boyutlandırma ve tablo araçlarıyla gelir (`ui/src/views/shared/htmlEditorOptions.ts`); yazılan değer varsayılanın üstüne tek seviye birleştirilir, yalnızca farkı yaz. |
| `dxImageUpload` | Görsel yükleme (platform); görsel tutan her kolonun editörü. `uploadUrl` yoksa dosya **base64** metin olarak kolona yazılır → kolon `nvarchar(MAX)`; sınırlı boylu kolonla deploy reddedilir. `uploadUrl` varsa kolona dönen adres yazılır | String (16) | `uploadUrl`\*, `accept`\*, `capture`\*, `multiple`\*, `maxFileSize`\*, `width`\*, `height`\* |
| `dxImageUpload` | Görsel yükleme (platform); görsel tutan her kolonun editörü. `accept` belge türlerini de içerirse (`application/pdf,.doc,.docx` — CV, imzalı form) görsel olmayan `data:` değeri listede ve formda belge ikonuyla çizilir, tıklanınca blob olarak yeni sekmede açılır (`imageHoverPreview.thumbnailSource`). `uploadUrl` yoksa dosya **base64** metin olarak kolona yazılır → kolon `nvarchar(MAX)`; sınırlı boylu kolonla deploy reddedilir. `uploadUrl` varsa kolona dönen adres yazılır | String (16) | `uploadUrl`\*, `accept`\*, `capture`\*, `multiple`\*, `maxFileSize`\*, `width`\*, `height`\* |
| `dxImageViewer` | Görsel gösterimi (platform), yükleme yapmaz. Tablo kolonuna bağlı alanda kullanılmaz — görsel kolonu `dxImageUpload`'dır, deploy `dxImageViewer`'ı reddeder | String (16) | `width`, `height` |
`\*` ile işaretli anahtarlar backend'de **tipli DTO'ya** çözülür:
@ -3791,6 +3791,19 @@ namespace DynamicServices
`IRepository<TEntity, TKey>`, `ICurrentTenant`, `ICurrentUser`, platform servisleri —
derleme referansları yüklü tüm `Volo.Abp`, `Sozsoft.Platform` ve `Microsoft.AspNetCore`
assembly'leridir, yani platform entity ve servislerinin tamamı görünürdür.
- **Derleme referansları dardır:** temel runtime (`System.Private.CoreLib`, `System.Runtime`,
`System.Linq`, `System.Collections`, `netstandard`) + yüklü assembly'lerden adı `Volo.Abp`,
`Sozsoft.Platform` ya da `Microsoft.AspNetCore` içerenler (`DynamicServiceCompiler.GetDefaultReferences`).
`Microsoft.Extensions.*` (Logging, Localization, Identity.Core), `System.Data`, `System.Linq.Expressions`
ve `Sozsoft.Notifications.*` görünmez; imzasında bunlardan bir tip geçen üye `CS0012` ile derlenmez.
Bu yüzden `UserFriendlyException`/`BusinessException` (`LogLevel`), `L`/`Logger`, ifade ağacı alan
repository metotları (`AnyAsync(predicate)`, `IRepository<T>.GetAsync` overload'ları),
`UnitOfWorkManager.Begin(...)` (`IsolationLevel`), `UserManager` ve `INotificationManager`
kullanılamaz. Yerine: kullanıcı için `IIdentityUserAppService` (yetkisini kendisi arar), entity
okuma/yazma için `IIdentityUserRepository` / `IBasicRepository`, tablo ve dil metni için
`IDynamicDataManager` ile parametreli SQL; iş kuralı reddi istisna yerine sonuç DTO'sunda döner.
EF ile yazılan satırı aynı istekte SQL'den okuyan sorgu `WITH (READPAST)` kullanır — commit
edilmemiş satırın kilidini beklemez.
- **Route türetimi** (ABP konvansiyonu): sınıf adından `AppService` eki atılır → kebab-case;
metot adından `Async` eki atılır → kebab-case. `DynamicCustomerAppService.GetCustomersAsync`
→ `GET /api/app/dynamic-customer/get-customers`.
@ -3835,10 +3848,12 @@ Yönetim yetkileri:
bırakma, gerekiyorsa `data/Abp.Identity.Permissions.json`'a yeni yetki tanımla (CLAUDE.md kesişen değişiklik
kuralı).
**Seed:** `data/App.DeveloperKit.DynamicServices.json` (§9.15; seed bayrakları açık — dosya ilk
kayıtta oluşur). Veritabanı sıfırlanınca kayıt bu dosyadan döner; açılışta yalnızca
`IsActive && CompilationStatus == Success` olanlar derlendiği için dosyadaki satır bu iki değeri
taşımalıdır. `Code` tam C# kaynağıdır, JSON string olarak kaçışlanır.
**Seed:** listenin seed bayrakları açıktır (`data/App.DeveloperKit.DynamicServices.json`, dosya ilk
kayıtta oluşur), ama bu dosya **kodu taşıyamaz**: `ListFormSeedDataApplier` yalnızca ekranın alan
olarak tanımlı kolonlarını yazar; `Code` listede alan değildir (diyalogda düzenlenir), bu yüzden
dosyaya elle yazılan bir servis satırı migrate'te `Code` NULL hatasıyla reddedilir. Dynamic Service
seed dosyasıyla teslim edilen bir artefakt olarak üretilmez; ekrandan yazılıp yayınlanır.
Açılışta yalnızca `IsActive && CompilationStatus == Success` olanlar derlenir.
Yazarken `dotnet.instructions.md` §5 geçerlidir: tenant bağlamını `ICurrentTenant` üzerinden
kullan, SQL'i parametreli çalıştır, kullanıcıya görünen metni dil anahtarından ver,
@ -4346,7 +4361,7 @@ platformun hazır aksiyonları buradan çağrılır. Uydurma metot yazma; kullan
| `UiEvalService.ApiClearRedisCache()` | Dağıtık önbelleği temizler | — |
| `UiEvalService.ApiKickUser(userId, gridRef)` | Kullanıcının oturumunu düşürür, grid'i yeniler | — |
| `UiEvalService.ApiDeleteDynamicService(id, gridRef)` | Dynamic Service kaydını onay alarak siler (yüklü assembly de düşer), grid'i yeniler | `App.DeveloperKit.DynamicServices.Delete` |
| `UiEvalService.ApiDbMigrate()` | Migration + seed akışını başlatır, log panelini açar | `App.Setup.Migrate` |
| `UiEvalService.ApiDbMigrate()` | Önce onay sorar (`App.DbMigrate.ConfirmMessage`), sonra migration + seed akışını başlatır, log panelini açar. Kendi onay diyaloğu olan `DbMigrateButton` (SQL Query Manager, Wizard Manager) ikinci parametreyle (`confirmed: true`) bu adımı atlar | `App.Setup.Migrate` |
### 9.14 Platformun hazır gelen diğer konfigürasyon ekranları
@ -4374,6 +4389,7 @@ kullanılacağı** `lowcode-reference.instructions.md` §12'dedir.
| "Para birimi, ülke/il/ilçe, birim, sektör…" | Definitions ekranları | `/admin/list/App.Definitions.*` |
| "Departman, pozisyon/ünvan, yetkinlik, organizasyon şeması" | İK › Definitions · Org Chart (şube bazlı departman/pozisyon) | `/admin/list/App.Hr.*` · `/admin/organization` |
| "Eğitim, araç/şoför/araç masrafı, vardiya, olay günlüğü, disiplin dosyası" | İK › Trainings · Vehicles · Shift · Event Log · Disciplinary Case | `/admin/list/App.Hr.{Training,Vehicle,Driver,VehicleExpense,VehicleMovement,Shift,EventLog,DisciplinaryCase}` |
| "İşe alım: kadro talebi, ilan, aday, başvuru, mülakat, teklif" | İK › Recruitment | `/admin/list/App.Hr.{StaffRequest,JobPosting,Candidate,JobApplication,Interview,JobOffer}` |
| "Menü düzeni" | Menu Manager (§9.7) | `/admin/menuManager` |
| "Genel siteye sayfa" | Custom Component (`Pub` modülü) — Visual Designer'dan yeni component + `Pub` menü kaydı | `/admin/developerkit/components/design/:id` (README.md §10.4) |
| "Yapay zekâ asistanı" | AI Bot tanımları | `/admin/list/App.Definitions.AiBot` |

View file

@ -932,7 +932,12 @@ kimlikle kurulur (`PlatformConsts.Branches.BranchIdDefaultValue`) ve
entity'ler `Entities/Tenant/Hr/Intranet`, seed `data/App.Hr.Intranet.*.json`; pano widget kaydı
(`Sas_T_IntranetWidget`) Saas'ta kalır. Vardiya, çalışma takvimi, olay günlüğü, Eğitimler
(`App.Hr.Trainings`), Araçlar (`App.Hr.Vehicles`), disiplin dosyaları ile izin/masraf/yan hak/disiplin cezası türleri wizard ile
üretilmiştir — entity yoktur, ekran `wizard/{Ad}.json`, tablo `sql/object/Hr_T_*.sql`. Ayrıntı:
üretilmiştir — entity yoktur, ekran `wizard/{Ad}.json`, tablo `sql/object/Hr_T_*.sql`. **İşe Alım**
(`App.Hr.Recruitment`) da wizard ile üretilmiştir: kadro talebi (Grid Workflow onayı) → ilan → aday (CV,
KVKK açık rızası zorunlu — tabloda `CHECK`) → başvuru (aşama kanbanı) → mülakat (takvim, kriter
ağırlıklı puan) → teklif (Grid Workflow onayı, teklif mektubu `DynamicReport`). Aday kaynağı, ret
sebebi ve değerlendirme kriteri tanımları İK › Tanımlar (`App.Hr.Definitions`) altındadır. İşe alınan adayın
kullanıcı (personel) kaydını BT elle açar; İK aday kaydını `UserId` ile o kullanıcıya bağlar. Ayrıntı:
`lowcode-reference.instructions.md` §12.4.
**Yetki kodları** `PlatformConsts.AppCodes` içinde merkezî olarak tanımlıdır ve
@ -2044,6 +2049,7 @@ configs/seeds/
│ │ # App.Hr.{SkillType,SkillLevel,Skill}.json — İK yetkinlik tanımları
│ │ # App.Hr.{Department,JobPosition}.json — İK departman → pozisyon (BranchId ile şubeye bağlı)
│ │ # App.Hr.Intranet.*.json — İK › Intranet (duyuru, anket, sosyal akış, etkinlik)
│ │ # App.Hr.{CandidateSource,RejectionReason,EvaluationCriterion}.json — İK › Tanımlar altındaki işe alım tanımları
│ │ # App.Notifications.Notification{Templates,Types,Rules}.json — bildirim şablonu, tipi → kuralı
│ │ # App.Languages.{Language,LanguageText}.json — dil → metin (eksik LanguageKey metinle üretilir)
│ │ # App.SettingDefinitions.json, App.BackgroundWorkers.RecurringJobs.json — ayar tanımları, zamanlanmış işler

View file

@ -9013,6 +9013,716 @@
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Recruitment",
"ParentName": null,
"DisplayName": "App.Hr.Recruitment",
"Order": 18,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource",
"ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.CandidateSource",
"Order": 16,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Create",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Update",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Delete",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Export",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Import",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.CandidateSource.Note",
"ParentName": "App.Hr.CandidateSource",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason",
"ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.RejectionReason",
"Order": 17,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Create",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Update",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Delete",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Export",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Import",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.RejectionReason.Note",
"ParentName": "App.Hr.RejectionReason",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion",
"ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.EvaluationCriterion",
"Order": 18,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Create",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Update",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Delete",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Export",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Import",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.EvaluationCriterion.Note",
"ParentName": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Hr.InterviewScore",
"Order": 7,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Create",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Update",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Delete",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Export",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Import",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.InterviewScore.Note",
"ParentName": "App.Hr.InterviewScore",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.Interview",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Create",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Update",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Delete",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Export",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Import",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Interview.Note",
"ParentName": "App.Hr.Interview",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.JobOffer",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Create",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Update",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Delete",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Export",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Import",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobOffer.Note",
"ParentName": "App.Hr.JobOffer",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.JobApplication",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Create",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Update",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Delete",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Export",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Import",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobApplication.Note",
"ParentName": "App.Hr.JobApplication",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.Candidate",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Create",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Update",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Delete",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Export",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Import",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Candidate.Note",
"ParentName": "App.Hr.Candidate",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.JobPosting",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Create",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Update",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Delete",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Export",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Import",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.JobPosting.Note",
"ParentName": "App.Hr.JobPosting",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest",
"ParentName": "App.Hr.Recruitment",
"DisplayName": "App.Hr.StaffRequest",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Create",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Update",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Delete",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Export",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Import",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.StaffRequest.Note",
"ParentName": "App.Hr.StaffRequest",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
}
]
}

View file

@ -0,0 +1,50 @@
{
"ListFormCode": "App.Hr.CandidateSource",
"KeyFieldName": "Id",
"GeneratedAt": "2026-10-04T07:52:25.4450219Z",
"Order": 0,
"Rows": [
{
"Name": "LinkedIn",
"Description": "LinkedIn ilanı ya da doğrudan mesaj",
"Id": "8d49c0bc-a1b9-549e-8614-fac001736a25",
"IsActive": true
},
{
"Name": "Kariyer.net",
"Description": "Kariyer.net ilanı",
"Id": "72cbc3f3-e558-53d3-9235-d1fd55deede4",
"IsActive": true
},
{
"Name": "Yenibiris",
"Description": "Yenibiris ilanı",
"Id": "1c769a46-bd29-5ba0-ae70-826d30db2a4d",
"IsActive": true
},
{
"Name": "Şirket Web Sitesi",
"Description": "Kurumsal web sitesindeki kariyer sayfası",
"Id": "f2aa9e34-44f2-52a6-8fb2-863a1ead7b03",
"IsActive": true
},
{
"Name": "Referans",
"Description": "Çalışan ya da iş ortağı referansı",
"Id": "fc187e8e-0e5a-5ed7-8681-ee6755e84dd5",
"IsActive": true
},
{
"Name": "Kariyer Fuarı",
"Description": "Üniversite ve sektör kariyer fuarları",
"Id": "a8382656-d2d8-51a5-b1a3-5be2955d83b9",
"IsActive": true
},
{
"Name": "Doğrudan Başvuru",
"Description": "E-posta ya da elden yapılan başvuru",
"Id": "d7d55798-47c2-564b-85b9-58aed09a3617",
"IsActive": true
}
]
}

View file

@ -0,0 +1,44 @@
{
"ListFormCode": "App.Hr.EvaluationCriterion",
"KeyFieldName": "Id",
"GeneratedAt": "2026-10-04T07:52:25.4481708Z",
"Order": 0,
"Rows": [
{
"Name": "İletişim Becerisi",
"Weight": 1,
"Id": "a66d3d4d-b7de-57fc-a8d9-be93a9eaf6fc",
"IsActive": true
},
{
"Name": "Teknik Yetkinlik",
"Weight": 2,
"Id": "e854a2b7-b32c-5c32-b262-cd5beac5f744",
"IsActive": true
},
{
"Name": "Problem Çözme",
"Weight": 1.5,
"Id": "1438e21f-3352-50d5-873a-a7a9edc100f2",
"IsActive": true
},
{
"Name": "Takım Çalışması",
"Weight": 1,
"Id": "805ff482-1654-56c4-88e5-e6060cb030ad",
"IsActive": true
},
{
"Name": "Motivasyon",
"Weight": 1,
"Id": "1c7006bc-4058-5e98-ac94-84d4c6e2c432",
"IsActive": true
},
{
"Name": "Kurum Kültürüne Uyum",
"Weight": 1,
"Id": "5374df0e-11ae-50db-9d76-19c42c9725cf",
"IsActive": true
}
]
}

View file

@ -0,0 +1,56 @@
{
"ListFormCode": "App.Hr.RejectionReason",
"KeyFieldName": "Id",
"GeneratedAt": "2026-10-04T07:52:25.4467408Z",
"Order": 0,
"Rows": [
{
"Name": "Deneyim yetersiz",
"RejectedBy": "Company",
"Id": "02de4d0f-b287-5cbc-befe-98fbe020c10c",
"IsActive": true
},
{
"Name": "Teknik yetkinlik yetersiz",
"RejectedBy": "Company",
"Id": "173e8166-239c-57a1-88e2-88bc92671333",
"IsActive": true
},
{
"Name": "Ücret beklentisi bütçe dışında",
"RejectedBy": "Company",
"Id": "955f5cbe-59b0-5e58-9c4d-e24f6a805325",
"IsActive": true
},
{
"Name": "Pozisyon kapandı / dolduruldu",
"RejectedBy": "Company",
"Id": "109977e2-8382-5984-932b-018c929319b9",
"IsActive": true
},
{
"Name": "Referans kontrolü olumsuz",
"RejectedBy": "Company",
"Id": "218bd09d-b46f-53a4-87e6-c57bcea42158",
"IsActive": true
},
{
"Name": "Aday teklifi reddetti",
"RejectedBy": "Candidate",
"Id": "d7f194e2-7ef7-5912-82d5-3a4ff2b25cb8",
"IsActive": true
},
{
"Name": "Aday başka bir teklifi kabul etti",
"RejectedBy": "Candidate",
"Id": "1fb4af98-46c0-5e5c-a4ec-e79dc6665012",
"IsActive": true
},
{
"Name": "Aday süreçten çekildi",
"RejectedBy": "Candidate",
"Id": "a65df0f4-ff8a-5314-8f8b-cfeb938e2631",
"IsActive": true
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -1923,6 +1923,116 @@
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr",
"Code": "App.Hr.Recruitment",
"DisplayName": "App.Hr.Recruitment",
"Order": 12,
"Url": null,
"Icon": "FcManager",
"RequiredPermissionName": null,
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Definitions",
"Code": "App.Hr.CandidateSource",
"DisplayName": "App.Hr.CandidateSource",
"Order": 13,
"Url": "/admin/list/App.Hr.CandidateSource",
"Icon": "FcFeedback",
"RequiredPermissionName": "App.Hr.CandidateSource",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Definitions",
"Code": "App.Hr.RejectionReason",
"DisplayName": "App.Hr.RejectionReason",
"Order": 14,
"Url": "/admin/list/App.Hr.RejectionReason",
"Icon": "FcCancel",
"RequiredPermissionName": "App.Hr.RejectionReason",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Definitions",
"Code": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Hr.EvaluationCriterion",
"Order": 15,
"Url": "/admin/list/App.Hr.EvaluationCriterion",
"Icon": "FcRating",
"RequiredPermissionName": "App.Hr.EvaluationCriterion",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.Interview",
"DisplayName": "App.Hr.Interview",
"Order": 5,
"Url": "/admin/list/App.Hr.Interview",
"Icon": "FcVideoCall",
"RequiredPermissionName": "App.Hr.Interview",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.JobOffer",
"DisplayName": "App.Hr.JobOffer",
"Order": 6,
"Url": "/admin/list/App.Hr.JobOffer",
"Icon": "FcApproval",
"RequiredPermissionName": "App.Hr.JobOffer",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.JobApplication",
"DisplayName": "App.Hr.JobApplication",
"Order": 4,
"Url": "/admin/list/App.Hr.JobApplication",
"Icon": "FcFlowChart",
"RequiredPermissionName": "App.Hr.JobApplication",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.Candidate",
"DisplayName": "App.Hr.Candidate",
"Order": 3,
"Url": "/admin/list/App.Hr.Candidate",
"Icon": "FcPortraitMode",
"RequiredPermissionName": "App.Hr.Candidate",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.JobPosting",
"DisplayName": "App.Hr.JobPosting",
"Order": 2,
"Url": "/admin/list/App.Hr.JobPosting",
"Icon": "FcAdvertising",
"RequiredPermissionName": "App.Hr.JobPosting",
"IsDisabled": false,
"ModuleId": "Hr"
},
{
"ParentCode": "App.Hr.Recruitment",
"Code": "App.Hr.StaffRequest",
"DisplayName": "App.Hr.StaffRequest",
"Order": 1,
"Url": "/admin/list/App.Hr.StaffRequest",
"Icon": "FcPlanner",
"RequiredPermissionName": "App.Hr.StaffRequest",
"IsDisabled": false,
"ModuleId": "Hr"
}
]
}

View file

@ -53,6 +53,26 @@
"IsActive": false,
"IsFixed": false,
"IsCustomized": false
},
{
"Id": "ece0e7bd-24a8-57f6-8dec-d5207135a587",
"NotificationTypeId": "de4c139f-dfa3-5bea-8a49-b3658e74336b",
"RecipientType": "Custom",
"RecipientId": null,
"Channel": "UiActivity",
"IsActive": true,
"IsFixed": false,
"IsCustomized": false
},
{
"Id": "d84a193a-09e6-5d85-948f-93463c2ef6b4",
"NotificationTypeId": "de4c139f-dfa3-5bea-8a49-b3658e74336b",
"RecipientType": "Custom",
"RecipientId": null,
"Channel": "Mail",
"IsActive": true,
"IsFixed": false,
"IsCustomized": false
}
]
}

View file

@ -28,6 +28,11 @@
"Id": "3f6c8b41-9d27-5a63-8f1e-4b0a9c6d2e11",
"Name": "Manuel",
"Description": "Manuel Bildirim ekranindan elle yapilan gonderimlerin tipi. Kural motorundan gecmez: alicilar ve kanallar ekranda secilir, her gonderim bu tiple kuyruga yazilir."
},
{
"Id": "de4c139f-dfa3-5bea-8a49-b3658e74336b",
"Name": "IseAlimMulakatAtandi",
"Description": "İşe alımda bir mülakat planlandığında mülakatçıya gider. Alıcı mülakat kaydındaki mülakatçıdır; bu tipin Custom kuralları yalnızca kanalı belirler (Mülakatlar ekranının ekleme sonrası komutu yazar)."
}
]
}

View file

@ -35,6 +35,22 @@
"Status": "active",
"Description": "Eğitime katılan personel için katılım belgesi (App.Hr.TrainingParticipant)",
"HtmlContent": "<div style=\"width:100%;min-height:180mm;padding:20mm 25mm;box-sizing:border-box;font-family:Calibri,'Segoe UI',Arial,sans-serif;color:#000;\"><h1 style=\"text-align:center;color:#e00000;font-size:44pt;font-weight:bold;margin:20mm 0 12mm 0;\">KATILIM BELGESİ</h1><p style=\"font-family:'Monotype Corsiva','Palatino Linotype',serif;font-style:italic;font-size:22pt;margin:0 0 3mm 0;\"><b>Sayın:</b> {{UserId}}</p><p style=\"font-size:15pt;line-height:1.5;margin:0;\">Firmamızda {{TrainingId}} eğitimine katılmıştır.</p><table style=\"width:100%;margin-top:35mm;font-size:14pt;\"><tr><td style=\"width:50%;text-align:center;font-weight:bold;\">Eğitmen</td><td style=\"width:50%;text-align:center;font-weight:bold;\">İşveren / İşveren Vekili</td></tr><tr><td style=\"height:20mm;\"></td><td></td></tr></table></div>"
},
{
"Id": "80d38666-423d-5e1d-8766-01f2c46be768",
"Name": "Teklif Mektubu",
"CategoryId": "c872e32b-e598-5432-a938-5826ffeb0d79",
"Status": "active",
"Description": "İşe alım sürecinde onaylanan teklif için aday mektubu (App.Hr.JobOffer)",
"HtmlContent": "<div style=\"width:100%;padding:18mm 22mm;box-sizing:border-box;font-family:Calibri,'Segoe UI',Arial,sans-serif;font-size:11.5pt;line-height:1.55;color:#1f2937;\"><table style=\"width:100%;border-collapse:collapse;margin-bottom:10mm;\"><tr><td style=\"font-size:20pt;font-weight:bold;color:#0f3d6e;\">İŞ TEKLİF MEKTUBU</td><td style=\"text-align:right;font-size:10pt;color:#4b5563;\">Teklif No: <b>{{OfferNo}}</b><br/>Tarih: {{OfferDate}}</td></tr></table><p>Sayın <b>{{CandidateName}}</b>,</p><p>İşe alım sürecimizde gösterdiğiniz ilgi için teşekkür ederiz. Yapılan değerlendirmeler sonucunda size aşağıdaki koşullarla iş teklifinde bulunmaktan memnuniyet duyarız.</p><table style=\"width:100%;border-collapse:collapse;margin:6mm 0;font-size:11pt;\"><tr><td style=\"width:38%;padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Pozisyon</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{JobPositionId}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Departman</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{DepartmentId}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Şube / Lokasyon</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{BranchId}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Çalışma Şekli / Modeli</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{EmploymentType}} / {{WorkModel}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">İşe Başlama Tarihi</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{StartDate}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Aylık Brüt Ücret</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{GrossSalary}} {{CurrencyId}}</td></tr><tr><td style=\"padding:6px 8px;background:#f1f5f9;border:1px solid #cbd5e1;font-weight:bold;\">Yan Haklar</td><td style=\"padding:6px 8px;border:1px solid #cbd5e1;\">{{BenefitCodes}}</td></tr></table><p>Bu teklif <b>{{ValidUntil}}</b> tarihine kadar geçerlidir. Teklifi kabul etmeniz hâlinde işe giriş belgelerinizi İnsan Kaynakları birimine iletmenizi rica ederiz. İş sözleşmesinin diğer hükümleri, imza aşamasında ayrıca paylaşılacaktır.</p><p>Ekibimize katılmanızı dört gözle bekliyoruz.</p><table style=\"width:100%;border-collapse:collapse;margin-top:18mm;font-size:11pt;\"><tr><td style=\"width:50%;vertical-align:top;\">Saygılarımızla,<br/><br/><b>İnsan Kaynakları</b><br/>İmza:</td><td style=\"width:50%;vertical-align:top;text-align:right;\">Teklifi kabul ediyorum.<br/><br/><b>{{CandidateName}}</b><br/>Tarih / İmza:</td></tr></table><p style=\"margin-top:12mm;font-size:8.5pt;color:#6b7280;text-align:center;\">Bu belge @@date tarihinde oluşturulmuştur.</p></div>"
},
{
"Id": "475c1ab4-4600-5ef2-a43e-1366ed89b0ed",
"Name": "KVKK Açık Rıza Formu",
"CategoryId": "c872e32b-e598-5432-a938-5826ffeb0d79",
"Status": "active",
"Description": "Aday kişisel verilerinin işe alım sürecinde işlenmesi için aydınlatma ve açık rıza formu (App.Hr.Candidate)",
"HtmlContent": "<div style=\"width:100%;padding:16mm 20mm;box-sizing:border-box;font-family:Calibri,'Segoe UI',Arial,sans-serif;font-size:10.5pt;line-height:1.5;color:#111827;\"><h2 style=\"text-align:center;font-size:15pt;margin:0 0 2mm 0;\">ÇALIŞAN ADAYI KİŞİSEL VERİLERİNİN İŞLENMESİNE İLİŞKİN</h2><h3 style=\"text-align:center;font-size:12.5pt;margin:0 0 8mm 0;font-weight:normal;\">AYDINLATMA METNİ VE AÇIK RIZA BEYANI</h3><p><b>1. Veri Sorumlusu:</b> 6698 sayılı Kişisel Verilerin Korunması Kanunu (\"KVKK\") uyarınca kişisel verileriniz, veri sorumlusu sıfatıyla Şirketimiz tarafından aşağıda açıklanan kapsamda işlenecektir.</p><p><b>2. İşlenen Kişisel Veriler:</b> Kimlik (ad, soyad, doğum tarihi, cinsiyet), iletişim (e-posta, telefon, adres), özgeçmiş ve mesleki deneyim, eğitim bilgileri, mülakat değerlendirme notları, ücret beklentisi ve başvuru sürecinde tarafımızla paylaştığınız diğer bilgiler.</p><p><b>3. İşleme Amaçları:</b> Açık pozisyonlara uygunluğunuzun değerlendirilmesi, mülakat süreçlerinin planlanması ve yürütülmesi, referans kontrolü, iş teklifinin hazırlanması ve işe alım kararı verilmesi halinde işe giriş işlemlerinin başlatılması.</p><p><b>4. Aktarım:</b> Kişisel verileriniz yalnızca yukarıdaki amaçlarla sınırlı olarak; yetkili kamu kurum ve kuruluşlarına, hukuki yükümlülüklerin yerine getirilmesi kapsamında ve hizmet aldığımız iş ortaklarına KVKK'nın 8. ve 9. maddelerine uygun olarak aktarılabilecektir.</p><p><b>5. Toplama Yöntemi ve Hukuki Sebep:</b> Verileriniz başvuru formu, özgeçmiş, e-posta, kariyer siteleri ve mülakatlar aracılığıyla; KVKK m.5/2 kapsamındaki hukuki sebeplere ve bu formla vereceğiniz açık rızaya dayanılarak toplanmaktadır.</p><p><b>6. Haklarınız:</b> KVKK'nın 11. maddesi uyarınca verilerinizin işlenip işlenmediğini öğrenme, bilgi talep etme, düzeltilmesini, silinmesini ya da yok edilmesini isteme ve işlemeye itiraz etme haklarına sahipsiniz. Başvurularınızı yazılı olarak Şirketimize iletebilirsiniz.</p><div style=\"margin-top:8mm;padding:5mm;border:1px solid #9ca3af;border-radius:3px;\"><p style=\"margin-top:0;\"><b>AÇIK RIZA BEYANI</b></p><p>Yukarıdaki aydınlatma metnini okudum ve anladım. Kişisel verilerimin işe alım süreci kapsamında belirtilen amaçlarla işlenmesine ve saklanmasına özgür irademle <b>açık rıza veriyorum</b>.</p><table style=\"width:100%;border-collapse:collapse;margin-top:4mm;\"><tr><td style=\"width:30%;padding:4px 0;\">Adı Soyadı</td><td>: <b>{{FirstName}} {{LastName}}</b></td></tr><tr><td style=\"padding:4px 0;\">E-posta</td><td>: {{Email}}</td></tr><tr><td style=\"padding:4px 0;\">Telefon</td><td>: {{PhoneNumber}}</td></tr><tr><td style=\"padding:4px 0;\">Rıza Tarihi</td><td>: {{KvkkConsentDate}}</td></tr><tr><td style=\"padding:4px 0;\">Rıza Yöntemi</td><td>: {{KvkkConsentMethod}}</td></tr><tr><td style=\"padding:14px 0 4px 0;\">İmza</td><td style=\"padding-top:14px;\">: ..............................................</td></tr></table></div><p style=\"margin-top:8mm;font-size:8.5pt;color:#6b7280;text-align:center;\">Bu belge @@date tarihinde oluşturulmuştur.</p></div>"
}
]
}

View file

@ -0,0 +1,58 @@
IF OBJECT_ID(N'[dbo].[Hr_T_Candidate]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_Candidate]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[FirstName] nvarchar(128) NOT NULL,
[LastName] nvarchar(128) NOT NULL,
[Email] nvarchar(256) NOT NULL,
[PhoneNumber] nvarchar(32) NULL,
[Gender] nvarchar(16) NULL,
[BirthDate] date NULL,
[Country] nvarchar(64) NULL,
[City] nvarchar(128) NULL,
[Address] nvarchar(512) NULL,
[EducationLevel] nvarchar(32) NULL,
[School] nvarchar(256) NULL,
[Major] nvarchar(256) NULL,
[GraduationYear] int NULL,
[ExperienceYears] decimal(4,1) NULL,
[CurrentCompany] nvarchar(256) NULL,
[CurrentTitle] nvarchar(256) NULL,
[ExpectedSalary] decimal(18,2) NULL,
[CurrencyId] nvarchar(64) NULL,
[SourceId] uniqueidentifier NULL,
[LinkedInUrl] nvarchar(512) NULL,
[SkillIds] nvarchar(2048) NULL,
[Photo] nvarchar(MAX) NULL,
[CvDocument] nvarchar(MAX) NULL,
[Notes] nvarchar(MAX) NULL,
[KvkkConsent] bit NOT NULL,
[KvkkConsentDate] datetime NOT NULL,
[KvkkConsentMethod] nvarchar(32) NOT NULL DEFAULT 'Written',
[KvkkConsentDocument] nvarchar(MAX) NULL,
[UserId] uniqueidentifier NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_Candidate] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF OBJECT_ID(N'[dbo].[CK_Hr_T_Candidate_KvkkConsent]', 'C') IS NULL
ALTER TABLE [dbo].[Hr_T_Candidate] ADD CONSTRAINT [CK_Hr_T_Candidate_KvkkConsent] CHECK ([KvkkConsent] = 1)
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'UX_Hr_T_Candidate_Email' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_Candidate]'))
CREATE UNIQUE NONCLUSTERED INDEX [UX_Hr_T_Candidate_Email] ON [dbo].[Hr_T_Candidate] ([TenantId], [Email]) WHERE [IsDeleted] = 0
GO

View file

@ -0,0 +1,23 @@
IF OBJECT_ID(N'[dbo].[Hr_T_CandidateSource]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_CandidateSource]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[Name] nvarchar(128) NOT NULL,
[Description] nvarchar(512) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_CandidateSource] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,24 @@
IF OBJECT_ID(N'[dbo].[Hr_T_EvaluationCriterion]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_EvaluationCriterion]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[Name] nvarchar(128) NOT NULL,
[Weight] decimal(5,2) NOT NULL DEFAULT 1,
[Description] nvarchar(512) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_EvaluationCriterion] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,33 @@
IF OBJECT_ID(N'[dbo].[Hr_T_Interview]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_Interview]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[ApplicationId] uniqueidentifier NOT NULL,
[Title] nvarchar(256) NULL,
[InterviewType] nvarchar(32) NOT NULL DEFAULT 'FaceToFace',
[StartDate] datetime NOT NULL,
[EndDate] datetime NOT NULL,
[Location] nvarchar(256) NULL,
[MeetingUrl] nvarchar(512) NULL,
[InterviewerUserId] uniqueidentifier NOT NULL,
[Status] nvarchar(32) NOT NULL DEFAULT 'Planned',
[Recommendation] nvarchar(32) NULL,
[OverallScore] decimal(5,2) NULL,
[Notes] nvarchar(MAX) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_Interview] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,33 @@
IF OBJECT_ID(N'[dbo].[Hr_T_InterviewScore]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_InterviewScore]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[InterviewId] uniqueidentifier NOT NULL,
[CriterionId] uniqueidentifier NOT NULL,
[Score] int NOT NULL,
[Comment] nvarchar(1024) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_InterviewScore] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF OBJECT_ID(N'[dbo].[CK_Hr_T_InterviewScore_Score]', 'C') IS NULL
ALTER TABLE [dbo].[Hr_T_InterviewScore] ADD CONSTRAINT [CK_Hr_T_InterviewScore_Score] CHECK ([Score] BETWEEN 1 AND 5)
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'UX_Hr_T_InterviewScore_Criterion' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_InterviewScore]'))
CREATE UNIQUE NONCLUSTERED INDEX [UX_Hr_T_InterviewScore_Criterion] ON [dbo].[Hr_T_InterviewScore] ([InterviewId], [CriterionId]) WHERE [IsDeleted] = 0
GO

View file

@ -0,0 +1,38 @@
IF OBJECT_ID(N'[dbo].[Hr_T_JobApplication]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_JobApplication]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[CandidateId] uniqueidentifier NOT NULL,
[JobPostingId] uniqueidentifier NOT NULL,
[CandidateName] nvarchar(256) NULL,
[PostingTitle] nvarchar(256) NULL,
[ApplicationDate] date NOT NULL,
[SourceId] uniqueidentifier NULL,
[OwnerUserId] uniqueidentifier NULL,
[Stage] nvarchar(32) NOT NULL DEFAULT 'Applied',
[RejectionReasonId] uniqueidentifier NULL,
[RejectionNote] nvarchar(1024) NULL,
[AverageScore] decimal(5,2) NULL,
[SortOrder] int NOT NULL DEFAULT 0,
[Notes] nvarchar(MAX) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_JobApplication] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'UX_Hr_T_JobApplication_CandidatePosting' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_JobApplication]'))
CREATE UNIQUE NONCLUSTERED INDEX [UX_Hr_T_JobApplication_CandidatePosting] ON [dbo].[Hr_T_JobApplication] ([TenantId], [CandidateId], [JobPostingId]) WHERE [IsDeleted] = 0
GO

View file

@ -0,0 +1,46 @@
IF OBJECT_ID(N'[dbo].[Hr_T_JobOffer]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_JobOffer]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[OfferNo] nvarchar(32) NULL,
[ApplicationId] uniqueidentifier NOT NULL,
[CandidateName] nvarchar(256) NULL,
[OfferDate] date NOT NULL,
[ValidUntil] date NULL,
[BranchId] uniqueidentifier NOT NULL,
[DepartmentId] uniqueidentifier NOT NULL,
[JobPositionId] uniqueidentifier NOT NULL,
[EmploymentType] nvarchar(32) NOT NULL DEFAULT 'FullTime',
[WorkModel] nvarchar(32) NOT NULL DEFAULT 'Office',
[StartDate] date NULL,
[GrossSalary] decimal(18,2) NOT NULL,
[CurrencyId] nvarchar(64) NULL,
[BenefitCodes] nvarchar(1024) NULL,
[Status] nvarchar(32) NOT NULL DEFAULT 'Draft',
[ResponseDate] date NULL,
[Notes] nvarchar(MAX) NULL,
[ApprovalUser] nvarchar(256) NULL,
[ApprovalStatus] nvarchar(128) NULL,
[ApprovalDate] datetime NULL,
[ApprovalDescription] nvarchar(1024) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_JobOffer] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF OBJECT_ID(N'[dbo].[CK_Hr_T_JobOffer_GrossSalary]', 'C') IS NULL
ALTER TABLE [dbo].[Hr_T_JobOffer] ADD CONSTRAINT [CK_Hr_T_JobOffer_GrossSalary] CHECK ([GrossSalary] >= 0)
GO

View file

@ -0,0 +1,37 @@
IF OBJECT_ID(N'[dbo].[Hr_T_JobPosting]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_JobPosting]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[PostingNo] nvarchar(32) NULL,
[StaffRequestId] uniqueidentifier NULL,
[Title] nvarchar(256) NOT NULL,
[BranchId] uniqueidentifier NOT NULL,
[DepartmentId] uniqueidentifier NOT NULL,
[JobPositionId] uniqueidentifier NOT NULL,
[Headcount] int NOT NULL DEFAULT 1,
[EmploymentType] nvarchar(32) NOT NULL DEFAULT 'FullTime',
[WorkModel] nvarchar(32) NOT NULL DEFAULT 'Office',
[Location] nvarchar(256) NULL,
[PublishDate] date NULL,
[ClosingDate] date NULL,
[SourceIds] nvarchar(1024) NULL,
[Description] nvarchar(MAX) NULL,
[Requirements] nvarchar(MAX) NULL,
[Status] nvarchar(32) NOT NULL DEFAULT 'Draft',
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_JobPosting] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,24 @@
IF OBJECT_ID(N'[dbo].[Hr_T_RejectionReason]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_RejectionReason]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[Name] nvarchar(128) NOT NULL,
[RejectedBy] nvarchar(32) NOT NULL DEFAULT 'Company',
[Description] nvarchar(512) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_RejectionReason] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,41 @@
IF OBJECT_ID(N'[dbo].[Hr_T_StaffRequest]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_StaffRequest]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[RequestNo] nvarchar(32) NULL,
[RequestDate] date NOT NULL,
[BranchId] uniqueidentifier NOT NULL,
[DepartmentId] uniqueidentifier NOT NULL,
[JobPositionId] uniqueidentifier NOT NULL,
[Headcount] int NOT NULL DEFAULT 1,
[EmploymentType] nvarchar(32) NOT NULL DEFAULT 'FullTime',
[Reason] nvarchar(32) NOT NULL DEFAULT 'NewPosition',
[ReplacedUserId] uniqueidentifier NULL,
[ExpectedStartDate] date NULL,
[MinSalary] decimal(18,2) NULL,
[MaxSalary] decimal(18,2) NULL,
[CurrencyId] nvarchar(64) NULL,
[Qualifications] nvarchar(MAX) NULL,
[Description] nvarchar(MAX) NULL,
[RequestedById] uniqueidentifier NULL,
[ApprovalUser] nvarchar(256) NULL,
[ApprovalStatus] nvarchar(128) NULL,
[ApprovalDate] datetime NULL,
[ApprovalDescription] nvarchar(1024) NULL,
[IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_StaffRequest] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -60,7 +60,7 @@ const DbMigrateButton = ({
onClose={() => setIsConfirmOpen(false)}
onConfirm={() => {
setIsConfirmOpen(false)
UiEvalService.ApiDbMigrate(onCompleted)
UiEvalService.ApiDbMigrate(onCompleted, true)
}}
>
<p className="text-gray-600 dark:text-gray-400">

View file

@ -92,8 +92,14 @@ export abstract class UiEvalService {
* Canlı sistemde migration tetikler (SQL Query Manager ve Wizard dosya yöneticisi ortak kullanır).
* Yetki sunucu tarafında `App.Setup.Migrate` izniyle doğrulanır. `onSuccess`, migrate hatasız
* bittiğinde çağrılır; migrate'in kurduğu kayıtları gösteren ekran kendini yeniler.
* Migrate seed'leri canlı veritabanına uygular; buton script'inden (`OnClick`) çağrıldığında da
* onay sorulur. Kendi onay diyaloğunu açan `DbMigrateButton` `confirmed: true` geçer.
*/
static ApiDbMigrate = (onSuccess?: () => void) => {
static ApiDbMigrate = (onSuccess?: () => void, confirmed = false) => {
if (!confirmed && !window.confirm(UiEvalService.translate('::App.DbMigrate.ConfirmMessage'))) {
return
}
toast.push(
<Notification type="info" duration={3000}>
{UiEvalService.translate('::App.Platform.StartMessage')}

View file

@ -7,6 +7,7 @@ import {
hideImageHoverPreview,
openImageInNewTab,
showImageHoverPreview,
thumbnailSource,
} from './imageHoverPreview'
import { normalizeImageSize } from '../../list/shared/imageValue'
import Input from '@/components/ui/Input'
@ -113,7 +114,7 @@ const ImageUploadEditorComponent = ({
{urls.map((url, i) => (
<div key={i} style={{ position: 'relative', display: 'inline-block' }}>
<img
src={url}
src={thumbnailSource(url)}
alt=""
onMouseEnter={(event) => showImageHoverPreview(url, event)}
onMouseMove={(event) => showImageHoverPreview(url, event)}

View file

@ -1,5 +1,18 @@
const NO_IMAGE = '/img/others/no-image.png'
// Gorsel yukleme alani belge de tasiyabilir (CV, imzali form); data URI'si gorsel olmayan deger
// <img> ile cizilemez, yerine belge ikonu gosterilir.
const DOCUMENT_ICON =
'data:image/svg+xml;utf8,' +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path fill="#e5e7eb" d="M10 2h20l10 10v34H10z"/><path fill="#9ca3af" d="M30 2v10h10z"/><path fill="#6b7280" d="M16 22h16v2H16zm0 6h16v2H16zm0 6h11v2H16z"/></svg>',
)
const isDocumentDataUrl = (url: string) => url.startsWith('data:') && !url.startsWith('data:image/')
/** Kucuk resimde gosterilecek kaynak: gorsel kendisi, belge ise belge ikonu. */
export const thumbnailSource = (url: string) => (isDocumentDataUrl(url) ? DOCUMENT_ICON : url)
/** Hem React SyntheticEvent hem de native MouseEvent ile çalışabilmesi için minimum sözleşme. */
type HoverPreviewEvent = {
clientX: number
@ -77,6 +90,8 @@ const getPreviewElement = () => {
}
export const showImageHoverPreview = (src: string, event: HoverPreviewEvent) => {
if (isDocumentDataUrl(src)) return
const element = getPreviewElement()
previewTarget = event.currentTarget instanceof HTMLElement ? event.currentTarget : null
const image = element.querySelector('img') as HTMLImageElement
@ -111,14 +126,15 @@ export const hideImageHoverPreview = () => {
export const openImageInNewTab = (url: string) => {
hidePreviewElement()
if (!url.startsWith('data:image/')) {
if (!url.startsWith('data:')) {
window.open(url, '_blank', 'noopener,noreferrer')
return
}
// Tarayicilar data: adresine ust duzey gecisi engeller; gorsel ya da belge blob olarak acilir.
try {
const match = url.match(/^data:(image\/[^;]+);base64,(.*)$/)
if (!match) throw new Error('Unsupported image data URL')
const match = url.match(/^data:([^;,]+);base64,(.*)$/)
if (!match) throw new Error('Unsupported data URL')
const binary = atob(match[2])
const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0))

View file

@ -7,6 +7,7 @@ import {
hideImageHoverPreview,
openImageInNewTab,
showImageHoverPreview,
thumbnailSource,
} from '../../form/editors/imageHoverPreview'
import { normalizeImageSize, parseJsonObject } from '../shared/imageValue'
import Input from '@/components/ui/Input'
@ -158,7 +159,7 @@ const ImageUploadEditorComponent = (cellElement: any): ReactElement => {
{urls.map((url, i) => (
<div key={i} style={{ position: 'relative', display: 'inline-block' }}>
<img
src={url}
src={thumbnailSource(url)}
alt=""
style={{
width: thumbW,

View file

@ -59,13 +59,14 @@ export const toImageSource = (value: string) => {
const splitImageString = (value: string) => {
const trimmed = value.trim()
if (!trimmed) return []
if (trimmed.startsWith('data:image/')) return [trimmed]
// data URI virgul tasir (data:application/pdf;base64,...); ayraclarla bolunmez.
if (trimmed.startsWith('data:')) return [trimmed]
return trimmed
.split(/\r?\n|\|\s*/)
.flatMap((part) => {
const text = part.trim()
if (!text || text.startsWith('data:image/')) return text ? [text] : []
if (!text || text.startsWith('data:')) return text ? [text] : []
return text.split(',').map((item) => item.trim())
})
.map(toImageSource)

View file

@ -29,6 +29,7 @@ import {
hideImageHoverPreview,
openImageInNewTab,
showImageHoverPreview,
thumbnailSource,
} from '../form/editors/imageHoverPreview'
import { translateWorkflowLabel } from '@/utils/workflow/workflowHelpers'
@ -98,7 +99,7 @@ const cellTemplateImage = (
img.onerror = null
img.src = NO_IMAGE
}
img.src = url
img.src = thumbnailSource(url)
img.alt = ''
img.style.cssText = `width:${width}px;height:${height}px;object-fit:cover;border-radius:4px;margin:2px;vertical-align:middle;display:inline-block;cursor:zoom-in;`