diff --git a/.github/instructions/ai.instructions.md b/.github/instructions/ai.instructions.md index 680129a5..ab1a1e52 100644 --- a/.github/instructions/ai.instructions.md +++ b/.github/instructions/ai.instructions.md @@ -23,7 +23,7 @@ Companion documents (this file wins on conflict): | `dotnet.instructions.md` | Binding code standard for everything under `api/` | | `list.instructions.md` | Step-by-step procedure for adding a module / list through seeders | | `../../README.md` | Technical map: what exists, where it lives, how it is wired | -| `../../configs/seeds/docs/modules/{Module}.md` | **How a generated module works**: discovery answers, approved recipe, screens, formulas, status rules, permissions, FAQ. Read it first when asked how a module/component behaves; write or update it with every module/component change (`lowcode.instructions.md` §0.13). Index: `README.md` §10.5 | +| `../../configs/seeds/docs/modules/{Menu}.md` | **How a generated module works**: discovery answers, approved recipe, screens, formulas, status rules, permissions, FAQ. Read it first when asked how a module/component behaves; write or update it with every module/component change (`lowcode.instructions.md` §0.13). Index: `README.md` §10.5 | | `../../CLAUDE.md` | Operating rules and standing defaults for AI agents in this repo | --- @@ -629,7 +629,7 @@ A proposal is complete only if all are present: 4. Menu-route-component mapping included. 5. Validation checklist included. 6. Risk/rollback notes included. -7. Once produced, the module document `configs/seeds/{scope}/docs/modules/{Module}.md` is completed (analysis, +7. Once produced, the module document `configs/seeds/{scope}/docs/modules/{Menu}.md` is completed (analysis, decisions, behaviour) and indexed in `README.md` §10.5. --- diff --git a/.github/instructions/lowcode-reference.instructions.md b/.github/instructions/lowcode-reference.instructions.md index decfd582..83386731 100644 --- a/.github/instructions/lowcode-reference.instructions.md +++ b/.github/instructions/lowcode-reference.instructions.md @@ -1311,7 +1311,7 @@ ekranları ABP tablolarıdır, Licence/Dev Request host tablolarını okur. | Ekran | Kod / route | Tablo | Komponent üretirken ne işe yarar | | --- | --- | --- | --- | | **Definitions › Sector** | `App.Definitions.Sector` | `Adm_T_Sector` | Sektör lookup’ı. Veri `data/App.Definitions.Sector.json`'dan seed edilir. | -| **Definitions › Contacts** | `App.Definitions.Contact` (menüsüz sekmeler `.ContactSales`, `.ContactPurchasing`, `.ContactFinancial`, `.ContactAccounting`, `.ContactNotes`, `.ContactPerson`, `.ContactBankAccount`) | `Adm_T_Contact` · `Adm_T_ContactPerson` · `Adm_T_ContactBankAccount` | Satış ve satınalmanın ortak müşteri/tedarikçi kartı; belge ekranlarında cari lookup'ı buradan alınır (`IsActive = 1`, `TenantId = '@TENANTID'`). Wizard ekranıdır, ayrıntı `configs/seeds/docs/modules/AdministrationDefinitions.md`. Seed `data/App.Definitions.Contact.json`. | +| **Definitions › Contacts** | `App.Definitions.Contact` (menüsüz sekmeler `.ContactSales`, `.ContactPurchasing`, `.ContactFinancial`, `.ContactAccounting`, `.ContactNotes`, `.ContactPerson`, `.ContactBankAccount`) | `Adm_T_Contact` · `Adm_T_ContactPerson` · `Adm_T_ContactBankAccount` | Satış ve satınalmanın ortak müşteri/tedarikçi kartı; belge ekranlarında cari lookup'ı buradan alınır (`IsActive = 1`, `TenantId = '@TENANTID'`). Wizard ekranıdır, ayrıntı `configs/seeds/docs/modules/App.Administration.md` › Tanımlamalar. Seed `data/App.Definitions.Contact.json`. | | **Definitions › Contact Tags** | `App.Definitions.ContactTag` | `Adm_T_ContactTag` | Kontak sınıflandırma etiketleri; Kontaklar'ın `Tags` alanı (`dxTagBox`) buradan seçer. Seed `data/App.Definitions.ContactTag.json`. | | **Definitions › Sequence** | `App.Definitions.Sequence` | `Adm_T_Sequence` | Belge numarası üretimi (`lowcode` §9.9); alan varsayılanında `CustomValueType: 5` ile bağlanır. Entity `IMultiTenant`'tır; ekran `IsTenant = true`, yetkiler `MultiTenancySide = Both` — her kiracı kendi numaratörlerini tutar. Seed `data/App.Definitions.Sequence.json`. | | **Definitions › UoM Category** | `App.Definitions.UomCategory` (alt form `.Uom`) | `Adm_T_UomCategory` · `Adm_T_Uom` | Ölçü birimi, `Ratio`/`Rounding` — miktar alanı olan ekranlarda birim lookup'ı ve çevrim. Entity'ler `IMultiTenant`'tır; ekranlar `IsTenant = true`, yetkiler `MultiTenancySide = Both`. Seed `data/App.Definitions.{UomCategory,Uom}.json`. | @@ -1412,9 +1412,9 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — ` | **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. | -| **Performance Management** | `App.Hr.Performance` dalı (yalnız İK): `PerformancePeriod`, `PerformanceReview`, `PerformanceCalibration`, `DevelopmentPlan`; tanım `App.Hr.PerformanceRating` (İK › Tanımlar). Çalışana ait `MyPerformanceReview`, `TeamPerformanceReview`, `My360Feedback` menüsüzdür; Intranet › Dashboard'daki custom widget'lardan (`MyPerformanceWidget`, `TeamPerformanceWidget`, `My360FeedbackWidget`) açılır; çalışanınkiler profilin **Performansım** sekmesinde de görünür | `Hr_T_PerformanceRating` · `Hr_T_PerformancePeriod` · `Hr_T_PerformancePeriodSkill` · `Hr_T_PerformanceReview` · `Hr_T_PerformanceGoal` · `Hr_T_PerformanceCompetency` · `Hr_T_PerformanceFeedback` · `Hr_T_PerformanceFeedbackScore` · `Hr_T_DevelopmentPlan` | tenant | Dönem → değerlendirme (hedef KPI/OKR + yetkinlik `Hr_T_Skill`/`Hr_T_SkillLevel` + isteğe bağlı 360) → kalibrasyon → gelişim planı. **Aynı tabloya persona ekranları**: İK (tümü), çalışan (`EmployeeId = '@USERID'`), yönetici (`ManagerId = '@USERID'`), 360 değerlendiricisi (`ReviewerId = '@USERID'`); kilitli alanlar İK ekranının yetkisine bağlıdır (sunucu düşürür), satır sahipliği ve aşama kuralı `Hr_S_PerformanceGuard` (before-command). Hesap ve durum geçişi `Hr_S_PerformanceReviewRecalc` / `Hr_S_PerformanceReviewAfterSave`; tamamlanan değerlendirme `Adm_T_UserSkill`'e yazar. Widget'lar veriyi ekranın kendi sorgusundan (`list-form-select/select`) okur. Çalışma şekli ve kararlar: `configs/seeds/docs/modules/HrPerformance.md`. Wizard + Custom Component (pano kutusu). | -| **Leave Management** | `App.Hr.Leave` dalı (yalnız İK): `LeaveRequest` (Grid Workflow: Müdür Onayı `@ManagerUserNames` → İK Onayı; üst pozisyonu olmayan çalışanda müdür adımı `RequiresManagerApproval` karşılaştırmasıyla atlanır), `LeaveBalance` (alt formlar `LeaveBalanceAdjustment`, `LeaveBalanceYear`). Çalışana ait `MyLeaveRequest`, `MyLeaveBalance` ve müdüre ait `TeamLeaveRequest` menüsüzdür; Intranet › Dashboard'daki `MyLeaveWidget` / `TeamLeaveWidget`'tan açılır; çalışanınkiler profilin **İzinlerim** sekmesinde de görünür; kullanıcı detayında **İzinler** sekmesi | `Hr_T_LeaveRequest` · `Hr_T_LeaveBalanceAdjustment` · görünümler `Hr_V_LeaveBalanceYear` · `Hr_V_LeaveSummary` | tenant | Gün sayısı `Hr_F_LeaveWorkDays` (Ayarlar › İnsan Kaynakları › İzin çalışma günleri + `Hr_T_WorkCalendar`); bakiye İş Kanunu md.53 kademeleri (ayarlardan) + devir + düzeltme; müdür = departmanın en üst pozisyonunun sahibi. Doğrulama, müdür çözümü, rapor ↔ `Adm_T_UserSickLeave` eşlemesi ve bildirim `Hr_S_LeaveRequestAfterSave`; satır koruması `Hr_S_LeaveRequestGuard`; Sağlık Kartı tarafı `Hr_S_LeaveSickLeaveSync`. SQL'den ayar okuma `Hr_F_HrSetting` (kiracı → genel → varsayılan). Çalışma şekli: `configs/seeds/docs/modules/HrLeave.md`. Wizard + Custom Component + küçük UI/motor eki. | -| **Timesheet & Attendance** | `App.Hr.Attendance` dalı (yalnız İK): `AttendanceLog` (ham okutma; Excel import), `Timesheet` (çalışan × gün; düzenlenen gün `IsManual`), `TimesheetMonthly` (salt okunur aylık özet, alt form `Timesheet` `Id → PeriodKey`), `TimesheetPeriod` (ay yeniden hesap / kapanış). Çalışana ait `MyTimesheet` (+ alt form `MyTimesheetDay`) menüsüzdür; Intranet › Dashboard'daki `MyTimesheetWidget`'tan açılır; profilin **Puantajım** sekmesinde de görünür; kullanıcı detayında **Puantaj** sekmesi | `Hr_T_AttendanceLog` · `Hr_T_Timesheet` · `Hr_T_TimesheetPeriod` · görünümler `Hr_V_AttendanceShift` · `Hr_V_TimesheetMonthly` | tenant | Hesap `Hr_S_TimesheetCalculate` (gün tipi: rapor > ücretsiz izin > `Hr_T_WorkCalendar` tatili > hafta tatili (İzin çalışma günü ayarları) > ücretli izin > okutma > eğitim katılımı (`Training`) > varsayılan çalışma / devamsız; izinli günde `LeaveTypeId`, eğitim gününde `TrainingId`; mola `MAX(vardiya, okutulan)`; geç/erken vardiya toleransı aşılırsa tamamı; fazla mesai haftalık 45 saati aşan kısım + tatil çalışması). Kişi eşlemesi `AbpUsers.PdksCardNo` / `RegistrationNo`; kartı olan çalışan ilk PDKS okutmasından itibaren okutmayla, diğerleri elle (kayıtsız gün `IsAssumed`) takip edilir. Tetikler: hareket kaydı `Hr_S_AttendanceProcess`, PDKS Custom Endpoint `Hr_S_AttendanceImport` (`/hr/attendance/`), dönem `Hr_S_TimesheetPeriodAfterSave`, gece işi `Hr_S_TimesheetNightly`, izin/rapor prosedürleri, `Hr_S_TrainingSync`, `Hr_S_WorkCalendarAfterSave`. Modüller arası çakışma kuralları (raporlu gün devamsız değildir, rapora denk gelen izin günü bakiyeye döner, kapalı aya izin/rapor yazılmaz) `HrAttendance.md` §7.1'dedir. Ayarlar `App.HrSettings.Attendance.*`. Çalışma şekli: `configs/seeds/docs/modules/HrAttendance.md`. Wizard + Custom Component + Custom Endpoint + zamanlanmış iş + küçük UI eki. | +| **Performance Management** | `App.Hr.Performance` dalı (yalnız İK): `PerformancePeriod`, `PerformanceReview`, `PerformanceCalibration`, `DevelopmentPlan`; tanım `App.Hr.PerformanceRating` (İK › Tanımlar). Çalışana ait `MyPerformanceReview`, `TeamPerformanceReview`, `My360Feedback` menüsüzdür; Intranet › Dashboard'daki custom widget'lardan (`MyPerformanceWidget`, `TeamPerformanceWidget`, `My360FeedbackWidget`) açılır; çalışanınkiler profilin **Performansım** sekmesinde de görünür | `Hr_T_PerformanceRating` · `Hr_T_PerformancePeriod` · `Hr_T_PerformancePeriodSkill` · `Hr_T_PerformanceReview` · `Hr_T_PerformanceGoal` · `Hr_T_PerformanceCompetency` · `Hr_T_PerformanceFeedback` · `Hr_T_PerformanceFeedbackScore` · `Hr_T_DevelopmentPlan` | tenant | Dönem → değerlendirme (hedef KPI/OKR + yetkinlik `Hr_T_Skill`/`Hr_T_SkillLevel` + isteğe bağlı 360) → kalibrasyon → gelişim planı. **Aynı tabloya persona ekranları**: İK (tümü), çalışan (`EmployeeId = '@USERID'`), yönetici (`ManagerId = '@USERID'`), 360 değerlendiricisi (`ReviewerId = '@USERID'`); kilitli alanlar İK ekranının yetkisine bağlıdır (sunucu düşürür), satır sahipliği ve aşama kuralı `Hr_S_PerformanceGuard` (before-command). Hesap ve durum geçişi `Hr_S_PerformanceReviewRecalc` / `Hr_S_PerformanceReviewAfterSave`; tamamlanan değerlendirme `Adm_T_UserSkill`'e yazar. Widget'lar veriyi ekranın kendi sorgusundan (`list-form-select/select`) okur. Çalışma şekli ve kararlar: `configs/seeds/docs/modules/App.Hr.md` › Performans Yönetimi. Wizard + Custom Component (pano kutusu). | +| **Leave Management** | `App.Hr.Leave` dalı (yalnız İK): `LeaveRequest` (Grid Workflow: Müdür Onayı `@ManagerUserNames` → İK Onayı; üst pozisyonu olmayan çalışanda müdür adımı `RequiresManagerApproval` karşılaştırmasıyla atlanır), `LeaveBalance` (alt formlar `LeaveBalanceAdjustment`, `LeaveBalanceYear`). Çalışana ait `MyLeaveRequest`, `MyLeaveBalance` ve müdüre ait `TeamLeaveRequest` menüsüzdür; Intranet › Dashboard'daki `MyLeaveWidget` / `TeamLeaveWidget`'tan açılır; çalışanınkiler profilin **İzinlerim** sekmesinde de görünür; kullanıcı detayında **İzinler** sekmesi | `Hr_T_LeaveRequest` · `Hr_T_LeaveBalanceAdjustment` · görünümler `Hr_V_LeaveBalanceYear` · `Hr_V_LeaveSummary` | tenant | Gün sayısı `Hr_F_LeaveWorkDays` (Ayarlar › İnsan Kaynakları › İzin çalışma günleri + `Hr_T_WorkCalendar`); bakiye İş Kanunu md.53 kademeleri (ayarlardan) + devir + düzeltme; müdür = departmanın en üst pozisyonunun sahibi. Doğrulama, müdür çözümü, rapor ↔ `Adm_T_UserSickLeave` eşlemesi ve bildirim `Hr_S_LeaveRequestAfterSave`; satır koruması `Hr_S_LeaveRequestGuard`; Sağlık Kartı tarafı `Hr_S_LeaveSickLeaveSync`. SQL'den ayar okuma `Hr_F_HrSetting` (kiracı → genel → varsayılan). Çalışma şekli: `configs/seeds/docs/modules/App.Hr.md` › İzin Yönetimi. Wizard + Custom Component + küçük UI/motor eki. | +| **Timesheet & Attendance** | `App.Hr.Attendance` dalı (yalnız İK): `AttendanceLog` (ham okutma; Excel import), `Timesheet` (çalışan × gün; düzenlenen gün `IsManual`), `TimesheetMonthly` (salt okunur aylık özet, alt form `Timesheet` `Id → PeriodKey`), `TimesheetPeriod` (ay yeniden hesap / kapanış). Çalışana ait `MyTimesheet` (+ alt form `MyTimesheetDay`) menüsüzdür; Intranet › Dashboard'daki `MyTimesheetWidget`'tan açılır; profilin **Puantajım** sekmesinde de görünür; kullanıcı detayında **Puantaj** sekmesi | `Hr_T_AttendanceLog` · `Hr_T_Timesheet` · `Hr_T_TimesheetPeriod` · görünümler `Hr_V_AttendanceShift` · `Hr_V_TimesheetMonthly` | tenant | Hesap `Hr_S_TimesheetCalculate` (gün tipi: rapor > ücretsiz izin > `Hr_T_WorkCalendar` tatili > hafta tatili (İzin çalışma günü ayarları) > ücretli izin > okutma > eğitim katılımı (`Training`) > varsayılan çalışma / devamsız; izinli günde `LeaveTypeId`, eğitim gününde `TrainingId`; mola `MAX(vardiya, okutulan)`; geç/erken vardiya toleransı aşılırsa tamamı; fazla mesai haftalık 45 saati aşan kısım + tatil çalışması). Kişi eşlemesi `AbpUsers.PdksCardNo` / `RegistrationNo`; kartı olan çalışan ilk PDKS okutmasından itibaren okutmayla, diğerleri elle (kayıtsız gün `IsAssumed`) takip edilir. Tetikler: hareket kaydı `Hr_S_AttendanceProcess`, PDKS Custom Endpoint `Hr_S_AttendanceImport` (`/hr/attendance/`), dönem `Hr_S_TimesheetPeriodAfterSave`, gece işi `Hr_S_TimesheetNightly`, izin/rapor prosedürleri, `Hr_S_TrainingSync`, `Hr_S_WorkCalendarAfterSave`. Modüller arası çakışma kuralları (raporlu gün devamsız değildir, rapora denk gelen izin günü bakiyeye döner, kapalı aya izin/rapor yazılmaz) `App.Hr.md` › Puantaj ve Devam Takibi §7.1'dedir. Ayarlar `App.HrSettings.Attendance.*`. Çalışma şekli: `configs/seeds/docs/modules/App.Hr.md` › Puantaj ve Devam Takibi. Wizard + Custom Component + Custom Endpoint + zamanlanmış iş + küçük UI eki. | | **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. | @@ -1533,9 +1533,9 @@ alanları da doldurur (`lowcode` §0.9). | "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 | -| "performans değerlendirme, hedef / KPI / OKR, yetkinlik değerlendirmesi, 360, kalibrasyon, gelişim planı" | İK › Performance Management | Var olan `Hr_T_Performance*` / `Hr_T_DevelopmentPlan` ekranını genişlet; yeni persona ekranı aynı tabloya `DefaultFilter` + `Hr_S_PerformanceGuard` ile açılır (`configs/seeds/docs/modules/HrPerformance.md`) | -| "izin talebi, izin onayı, izin bakiyesi, yıllık izin hakkı, rapor/istirahat izni" | İK › Leave Management | Var olan `Hr_T_LeaveRequest` ekranını genişlet; persona ekranı aynı tabloya `DefaultFilter` + `Hr_S_LeaveRequestGuard` ile açılır, bakiye `Hr_V_LeaveSummary`'den okunur (`configs/seeds/docs/modules/HrLeave.md`) | -| "puantaj, devam takibi, PDKS, giriş-çıkış, geç kalma, fazla mesai, devamsızlık" | İK › Timesheet & Attendance | Var olan `Hr_T_AttendanceLog` / `Hr_T_Timesheet` ekranlarını genişlet; hesap `Hr_S_TimesheetCalculate`'te tek yerdedir, kural değişikliği oraya yazılır (`configs/seeds/docs/modules/HrAttendance.md`) | +| "performans değerlendirme, hedef / KPI / OKR, yetkinlik değerlendirmesi, 360, kalibrasyon, gelişim planı" | İK › Performance Management | Var olan `Hr_T_Performance*` / `Hr_T_DevelopmentPlan` ekranını genişlet; yeni persona ekranı aynı tabloya `DefaultFilter` + `Hr_S_PerformanceGuard` ile açılır (`configs/seeds/docs/modules/App.Hr.md` › Performans Yönetimi) | +| "izin talebi, izin onayı, izin bakiyesi, yıllık izin hakkı, rapor/istirahat izni" | İK › Leave Management | Var olan `Hr_T_LeaveRequest` ekranını genişlet; persona ekranı aynı tabloya `DefaultFilter` + `Hr_S_LeaveRequestGuard` ile açılır, bakiye `Hr_V_LeaveSummary`'den okunur (`configs/seeds/docs/modules/App.Hr.md` › İzin Yönetimi) | +| "puantaj, devam takibi, PDKS, giriş-çıkış, geç kalma, fazla mesai, devamsızlık" | İK › Timesheet & Attendance | Var olan `Hr_T_AttendanceLog` / `Hr_T_Timesheet` ekranlarını genişlet; hesap `Hr_S_TimesheetCalculate`'te tek yerdedir, kural değişikliği oraya yazılır (`configs/seeds/docs/modules/App.Hr.md` › Puantaj ve Devam Takibi) | | "yapay zekâ cevaplasın" | Saas › Definitions › AiBot | Bot tanımı; `/admin/ai` bu tanımı kullanır | ### 12.7 Canlı referans uygulamalar diff --git a/.github/instructions/lowcode.instructions.md b/.github/instructions/lowcode.instructions.md index 8d2b7e70..772e8c4a 100644 --- a/.github/instructions/lowcode.instructions.md +++ b/.github/instructions/lowcode.instructions.md @@ -54,7 +54,7 @@ configs/seeds/ ├── {sql|postgres}/host/object|execute/… ← yalnızca host veritabanında çalışan script (ör. HangFire'a dayanan view) ├── crud/{EntityName}.json ← tablonun REST uçları ├── wizard/{WizardName}.json ← ekran + menü + yetki + dil anahtarları (List yolunda sunucu yazar, §4.1) -├── docs/modules/{Modül}.md ← modül dokümanı; iskelet + envanteri deploy yazar (§0.13) +├── docs/modules/{Menü}.md ← modül dokümanı; iskelet + envanteri deploy yazar (§0.13) ├── data/{ListFormCode}.json ← ekrandan girilen liste verisinin aynası (opsiyonel, §9.15) │ data/{ListFormCode}/{anahtar}.json ← aynı aynanın klasör modu (satır başına dosya) │ Custom Component'ler klasör modunda yaşar: @@ -75,7 +75,7 @@ kurulur; host veritabanını paylaşan tenant'ta dosyalar yeniden uygulanmaz (`S | 5 | Alt ekranlar (varsa) | ek `wizard/…` dosyaları | Ana wizard'dan **önceki** `SeededAt` damgasını alır | | 6 | Liste verisi (isteniyorsa) | `data/{ListFormCode}.json` | Ekran ve tablo hazır olmalı; `ListForm.SeedFilePath` bu yolu gösterir (§9.15) | | 7 | SEO alanları (public yol ürettiysen) | Yolu tanımlayan satırın kendisi: `data/App.Menus.Routes.json` ya da `data/App.DeveloperKit.CustomComponents/{Id}.json` | Yolu üreten dosya yazıldıktan sonra; ziyaretçiye açık hiçbir yol metasız kalmaz (§0.9) | -| 8 | Modül dokümanı | `docs/modules/{Modül}.md` (iskelet + envanteri deploy açar) + `README.md` §10.5 dizin satırı | Son adımdır; anlatım bölümleri doldurulur, MCP'de `save_module_doc` (§0.13) | +| 8 | Modül dokümanı | `docs/modules/{Menü}.md` (iskelet + envanteri deploy açar) + `README.md` §10.5 dizin satırı | Son adımdır; anlatım bölümleri doldurulur, MCP'de `save_module_doc` (§0.13) | **`Wizard.SeededAt` bir bağımlılık aracıdır.** Dosya adı tarih taşımaz (`{WizardName}.json`); `WizardDataSeeder` `wizard/` klasörünü **`Wizard.SeededAt` damgasına göre sıralı** işler (eşitlikte @@ -515,7 +515,7 @@ ister ve kiracı kullanıcısına hiçbiri açılmaz. | `delete_wizard` | Wizard'ı ve yalnızca onun ürettiği kayıtları siler; `dropTables: true` ekranın tablosunu da düşürür | Bağımlı wizard varsa reddeder. Tablo kullanıcı açıkça onaylamadan düşürülmez; `App.SqlQueryManager` ister (§4.5) | | `start_dev_request` | `App.DevRequests` talebini üstlenir: `Ready to Start` durumundaysa `In Progress` durumuna alır, değilse reddeder | Ek olarak `App.DevRequests.Update` ister. Açıklamadaki görseller ayrı resim içeriği olarak gelir (§0.11) | | `get_dev_request` | Talebi durumuna dokunmadan okur (aynı metin + analiz + resim içerikleri) | Analizden önce ya da yarım kalan talebe dönmek için; `App.DevRequests` ister | -| `save_dev_request_analysis` | `Backlog`/`Analysis` durumundaki talebin analizini `Analysis` kolonuna yazar (var olanı değiştirir), talebi `Analysis` durumuna alır; diğer durumları reddeder | Ek olarak `App.DevRequests.Update` ister. Standart §0.12; `Description`'a dokunmaz | +| `save_dev_request_analysis` | `Backlog`/`Analysis` durumundaki talebin analizini `Analysis` kolonuna yazar (var olanı değiştirir), talebi `Analysis` durumuna alır; diğer durumları reddeder. `menuCode` dalının modül dokümanı bölümüne de yazar, dosya/bölüm yoksa açar (§0.13) | Ek olarak `App.DevRequests.Update` ve `App.Listforms.Wizard` ister. Standart §0.12; `Description`'a dokunmaz | | `append_dev_request_note` | Talebin `Analysis` kolonunun sonuna HTML ekler | Üretim sonuç notu için; `Description` ve `Analysis` `update_row` ile yazılmaz (§0.11) | | `add_dev_request_subtasks` | `SubTasks` listesine tamamlanmış satırlar ekler | Atanan = bağlanan kullanıcı, bitiş = bugün (sunucu yazar); `SubTasks`'ı `update_row` ile yazma (§0.11) | | `verify_wizard` | DB Migrate ile kurulmuş ekranı veri yazmadan doğrular (migrate bekleyen dosyada `install` kontrolü başarısız döner, diğerleri yapılmaz): menü, yetki tanımı, ekran sorgusu (List) ya da bileşen (Custom), seed kapanışı | İsteğe bağlı: kullanıcı migrate sonrası isterse. Talep döngüsünün (§0.11) adımı değildir. `passed` yalnızca engelleyici bir kontrol kalırsa `false` | @@ -673,7 +673,7 @@ bileşen, seed dosyası yazılmaz; yalnızca okuma araçları ve `save_dev_reque | 1. Kuyruğu oku (yalnızca toplu) | `query_list` — `ListFormCode: App.DevRequests`, filtre `["Status","=","Backlog"]`, sıralama `SortOrder` | — | | 2. Talebi oku | `get_dev_request` — metin + görseller | — | | 3. Keşif | `list_wizards` (menü kökleri, modüller, izin grupları), `list_lists` / `describe_list` / `search_schema` (var olan ekran, tablo, lookup kaynağı), `list_components`, `get_dev_guide` (§0.6, §0.7, §0.8, §1) | — | -| 4. Yaz | `save_dev_request_analysis` — analizin tamamı, HTML (Timesheets satırını sunucu yazar, §0.11) | Analysis | +| 4. Yaz | `save_dev_request_analysis` — analizin tamamı, HTML + `menuCode` (menü yerindeki dalın ya da ekranın kodu). Analiz o dalın modül dokümanı bölümüne ("2. Analiz ve kararlar", §0.13) de yazılır; kök menünün ilk talebiyse dosya ve bölüm burada açılır (Timesheets satırını sunucu yazar, §0.11) | Analysis | **Durum kuralı sunucudadır:** araç yalnızca `Backlog` ya da `Analysis` durumundaki talebi kabul eder; `Analysis`'teki talebe yeniden çağrılırsa analiz değiştirilir. `Ready to Start` ve sonrası @@ -820,7 +820,7 @@ varsayılan olarak önerilir: - **Ekran:** menüsüz wizard (`CreateMenu: false`), kodu `App.Hr.My{Ekran}` / `App.Hr.Team{Ekran}`, İK ekranıyla aynı tabloya açılır. Satırları `DefaultFilter` + alan varsayılanıyla oturumdaki kullanıcıya süzülür (`"EmployeeId" = '@USERID'`); yetki okuma yetkisidir, İK yetkisi verilmez. - Kalıp: `configs/seeds/docs/modules/HrPerformance.md` §3.2–§3.3. + Kalıp: `configs/seeds/docs/modules/App.Hr.md` › Performans Yönetimi §3.2–§3.3. - **Erişim:** Intranet panosunda `Sas_T_IntranetWidget` kaydı (`SourceType: 1`, custom component; `PermissionName` = persona ekranının okuma yetkisi) özet gösterir ve listeye bağlanır. - **Profil:** `/admin/profile` sekmeleri sabittir — Çalışan Bilgileri, İzinlerim @@ -841,42 +841,58 @@ varsayılan olarak önerilir: bir alanın profilde görünmesi isteniyorsa liste ve `MyEmployeeInfo.tsx` birlikte değişir; sağlık, ücret ve işten çıkış alanları listeye eklenmez. -### 0.13 Modül dokümanı — `configs/seeds/docs/modules/{Modül}.md` +### 0.13 Modül dokümanı — `configs/seeds/docs/modules/{Menü}.md` Üretilen her modül kendi çalışma şeklini bir md dosyasında taşır; "bu ekran nasıl çalışıyor / şu puan nereden geliyor" sorusu kod ve seed taranmadan bu dosyadan cevaplanır (MCP'de `get_module_doc`). Doküman **wizard'ın parçasıdır**: Wizard ekranından ya da MCP `deploy_wizard` ile üretilen her modülde sunucu onu kendisi açar ve güncel tutar; anlatım bölümlerini üreten kişi/AI doldurur. -Wizard dışı (entity, özel React) modüller dokümanı elle yazar. +Wizard dışı (entity, özel React) modüller bölümünü elle yazar. -- **Yer:** seed klasörü — `configs/seeds/docs/modules/{Modül}.md`. Sunucu yalnızca seed köküne - yazabildiği için depo kökünde değildir. Wizard export zip'i dokümanı taşır, import yazar (`docs/modules/*.md`). -- **Hangi wizard hangi dokümana** (`ModuleDocCatalog`; wizard sözleşmesine alan eklenmez): - 1. Dokümanın ilk satırındaki beyan ekranı sahipleniyorsa o doküman: - `` (başka dalda - duran tanım ekranları için). - 2. Menüsüz alt form, onu `SubForms` içinde taşıyan ekranın dokümanına gider. - 3. Üst menü zincirinde kökün altında bir dal varsa dal (`App.Hr › App.Hr.Performance › …` → - `App.Hr.Performance`), yoksa ekranın kendi kodu. Ad koddan türer: `App.` atılır, noktalar - silinir → `HrPerformance.md`. +- **Yer ve ad:** seed klasörü — `configs/seeds/docs/modules/{Menü}.md`, **kök menü başına tek + dosya**. Ad kök menünün kodudur (`App.Administration.md`, `App.Hr.md`, + `App.Prc.md`). Ad sabit bir listeden değil menü ve dil seed dosyalarından okunur + (`ModuleDocCatalog.DocNameOfRoot`); yeni bir kök menü ilk deploy'unda kendi dosyasını açar. + Sunucu yalnızca seed köküne yazabildiği için depo kökünde değildir. Wizard export zip'i dokümanı + taşır, import yazar (`docs/modules/*.md`). +- **Bölüm:** kök menünün altındaki her dal dosyada bir bölümdür; bölüm bir beyan satırıyla başlar, + başlığı `## `, alt bölümleri `### `'tür: + ```markdown + + ## İşe Alım (`App.Hr.Recruitment`) + ### 1. Amaç ve kapsam + ``` + Bölümler menü sırasıyla dizilir; menüde karşılığı olmayan elle yazılmış bölüm (ör. + `App.Hr.Personnel`) yerini korur. +- **Hangi wizard hangi bölüme** (`ModuleDocCatalog`; wizard sözleşmesine alan eklenmez): + 1. Bir bölümün beyanındaki `claims=` ekranı sahipleniyorsa o bölüm (başka dalda duran tanım + ekranları için). + 2. Menüsüz alt form, onu `SubForms` içinde taşıyan ekranın bölümüne gider. + 3. Menü ağacında kökün altındaki ilk seviye (`App.Hr › App.Hr.Performance › …` → + `App.Hr.Performance`); ekran doğrudan kökün altındaysa ekranın kendi kodu. Kök ve dal + `data/App.Menus.Menu.json`'dan bulunur. - **Otomatik kısım:** deploy (`ListFormWizardAppService.Create`), silme, tasarımcı kaydı (`WizardSeedSynchronizer`) ve import kapanışı `ModuleDocManager.RefreshAllAsync` çağırır: - doküman yoksa iskelet açılır (bölümler `_Henüz yazılmadı._ `), + dosya yoksa kök başlığı açılır, wizard'ı olan dalın bölümü yoksa iskeleti menü sırasındaki yerine + eklenir (alt bölümler `_Henüz yazılmadı._ `), `` … `` arasındaki **"Ek — Ekran - envanteri"** wizard dosyalarından yeniden yazılır (menü, kaynak, görünümler, alt formlar, - widget'lar, komutlar/prosedürler, varsayılanlar, alan tablosu). Envanter elle düzenlenmez. - Wizard'ı kalmayan ve hiç yazılmamış iskelet silinir. Wizard'a yeni bir kayıt yolu eklenirse - `RefreshAllAsync` çağrısı da eklenir. -- **Elle/AI ile yazılan kısım:** aşağıdaki bölümler; doldurulan bölümden `module-doc:todo` - işareti kaldırılır, boş kalacak bölüme "Yok." yazılır. MCP'de `save_module_doc` (dosyanın - tamamı; envanter gönderilmez, sunucu ekler; beyan satırı korunur). Claude Code depoda dosyayı - doğrudan yazar. + envanteri"** bölümlere göre gruplanarak wizard dosyalarından yeniden yazılır (menü, kaynak, + görünümler, alt formlar, widget'lar, komutlar/prosedürler, varsayılanlar, alan tablosu). Envanter + elle düzenlenmez. Wizard'ı kalmayan ve hiç yazılmamış bölüm, bölümü kalmayan dosya silinir. + Wizard'a yeni bir kayıt yolu eklenirse `RefreshAllAsync` çağrısı da eklenir. +- **Elle/AI ile yazılan kısım:** aşağıdaki alt bölümler; doldurulan alt bölümden `module-doc:todo` + işareti kaldırılır, boş kalacak alt bölüme "Yok." yazılır. MCP'de `get_module_doc` / + `save_module_doc` ekran ya da dal koduyla çağrılır: yalnızca o bölüm okunur ve yazılır (beyan + satırı gönderilmezse mevcut beyan korunur; envanter gönderilmez, sunucu ekler). Dosya adıyla + çağrılırsa dosyanın tamamıdır. Menüde henüz olmayan modülün kodu (analizdeki `App.Inventory.Stock`) + kök ve dalı koddan alır: okuma iskelet döner, yazma `App.Inventory.md` dosyasını açar. Claude Code + depoda dosyayı doğrudan yazar. - **Zorunluluk:** MCP döngüsünde talep `update_row` ile `Testing`'e alınırken talebin wizard'larının - dokümanında `module-doc:todo` kalmışsa ya da doküman yoksa istek reddedilir - (`IModuleDocAppService.GetIncompleteForDevRequestAsync`). -- **Dizin:** `README.md` §10.5'e bir satır eklenir; README'de modül en fazla ilgili bölümde tek - cümleyle anılıp dokümana bağlanır. -- **Bölümler** (`ModuleDocRenderer.Sections`): + **bölümünde** `module-doc:todo` kalmışsa ya da bölüm yoksa istek reddedilir; aynı dosyadaki + başka dalların eksikleri talebi engellemez (`IModuleDocAppService.GetIncompleteForDevRequestAsync`). +- **Dizin:** yeni kök menü `README.md` §10.5 tablosuna bir satır, yeni dal o satırın "Bölümler" + hücresine bir ad ekler; README'de modül en fazla ilgili bölümde tek cümleyle anılıp dokümana bağlanır. +- **Alt bölümler** (`ModuleDocRenderer.Sections`, her dal bölümünde `### `): 1. **Amaç ve kapsam** — kim kullanır, hangi işi çözer. 2. **Analiz ve kararlar** — keşif turunun cevapları (soru → seçilen seçenek → gerekçe) ya da MCP'de onaylanmış analiz, onaylanan tarif ve `(varsayılan)` kalan satırlar. @@ -2183,14 +2199,14 @@ Kurallar: Karşılaştırma **sayısaldır** (`EvaluateCondition`: `>`, `>=`, `<`, `<=`, `=`, `!=`); bit/metin kolon okunamaz ve hata verir. Kayda göre adım atlamak için prosedür sayısal bir bayrak kolonu yazar ve kolon ekranda gizli alan olur (örnek: İzin Yönetimi'nde üst pozisyonu olmayan çalışanın müdür - adımı, `RequiresManagerApproval`, `HrLeave.md` §5.6). + adımı, `RequiresManagerApproval`, `App.Hr.md` › İzin Yönetimi §5.6). - `Approval` düğümü `NextOnApprove` / `NextOnReject`, `Start` ve `Inform` düğümleri `NextOnStart` alanını kullanır. `End` düğümünün çıkışı yoktur. - **Kayda göre değişen onaycı:** `Approver` değeri `@Kolon` ise (ör. `@ManagerUserNames`) onaycı kaydın o kolonundan okunur (`ListFormWorkflowAppService.ResolveNodeApprover`); kolon `|` ile ayrılmış kullanıcı adı/e-posta taşır ve ekranın alanı olmalıdır (satır ListForm sorgusundan okunur; gizli alan yeter). Kolon boşsa akış hata verir — boş onaycı herkese onay yetkisi verirdi. Kolonu kayıt sonrası prosedür doldurur - (örnek: İzin Yönetimi'nde departman müdürü, `HrLeave.md`). Tasarımcıda onaycı listesi kullanıcılarla + (örnek: İzin Yönetimi'nde departman müdürü, `App.Hr.md` › İzin Yönetimi). Tasarımcıda onaycı listesi kullanıcılarla birlikte `Alan: {Kolon}` seçeneklerini sunar. - **`Inform` düğümü e-posta gönderir** (MailQueue üzerinden, `Approver` alanındaki kullanıcı/rol adreslerine, önceki adımların notlarıyla birlikte). Uygulama içi bildirim ya da SMS isteniyorsa @@ -2631,7 +2647,7 @@ Script `AsyncFunction` ile derlenir, aşağıdaki adlar parametre olarak enjekte | `clear('A','B')` | Verilen alanları `null` yapar | | `copy('kolon','Alan')` | Lookup/GridBox'ta **seçili kayıttan** taşır; hedef verilmezse yolun son parçası hedef olur. Seçili kayıt, olay formdan gelse de (popup form, form sayfası) değişen alanın editöründen okunur; lookup sorgusu taşınacak kolonları döndürmelidir (ör. `SELECT Id AS [Key], …, DepartmentId, JobPositionId`) | | `selected('Yol')` · `snum()` · `sstr()` | Seçili kaydın tamamı / sayı / metin hâli | -| `readOnly('Alan', kosul)` | Formdaki **herhangi bir** editörü kilitler/açar (yalnızca script'in bağlı olduğu alanı değil). Grid popup'ında açılış çalışması (`isReady`) editörler her yeniden çizildiğinde tekrarlanır ve form verisi o anda güncel değildir; koşul başka bir alana bakıyorsa değer `editor.component.cellValue(satır, 'Alan')` ile okunur (örnek: `HrLeave.md` §5.1) | +| `readOnly('Alan', kosul)` | Formdaki **herhangi bir** editörü kilitler/açar (yalnızca script'in bağlı olduğu alanı değil). Grid popup'ında açılış çalışması (`isReady`) editörler her yeniden çizildiğinde tekrarlanır ve form verisi o anda güncel değildir; koşul başka bir alana bakıyorsa değer `editor.component.cellValue(satır, 'Alan')` ile okunur (örnek: `App.Hr.md` › İzin Yönetimi §5.1) | | `round(x, 2)` · `sum('A','B')` | Matematik | | `days('Bas','Bit')` · `hours('Bas','Bit')` | Gün farkı (bitiş dahil) · saat farkı (negatifse +24) | | `tpl('{Alan} - {value}')` | Şablon: `{Alan}`, `{value}`, `{selected.Yol}` | @@ -4820,7 +4836,7 @@ tedarikçi lookup'ı + iki kademeli onay). veri aynası ve `InsertedRecords` içindeki kullanılmayan kayıtlar gider; tablo yalnızca onayda seçilirse (MCP: `dropTables: true`) scripti ve crud dosyasıyla düşer (§4.5). Dosyayı diskten silmek kayıtları temizlemez. -- [ ] Modül dokümanı (`configs/seeds/docs/modules/{Modül}.md`) yazıldı ya da güncellendi; analiz/kararlar, +- [ ] Modül dokümanı (`configs/seeds/docs/modules/{Menü}.md`) yazıldı ya da güncellendi; analiz/kararlar, ekranlar, hesaplar ve yetkiler üretilen artefaktların gerçek adlarıyla yazılı, README §10.5 dizininde satırı var (§0.13). diff --git a/README.md b/README.md index 24d9c719..5fb74d46 100644 --- a/README.md +++ b/README.md @@ -989,12 +989,12 @@ sebebi ve değerlendirme kriteri tanımları İK › Tanımlar (`App.Hr.Definiti 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. **Performans Yönetimi** (`App.Hr.Performance`) wizard + custom component ile üretilmiştir: İK menüsü şartları ve takibi taşır, çalışana ait listeler menüsüzdür ve -Intranet panosundaki widget'lardan açılır; çalışma şekli [HrPerformance.md](configs/seeds/docs/modules/HrPerformance.md). +Intranet panosundaki widget'lardan açılır; çalışma şekli [App.Hr › Performans Yönetimi](configs/seeds/docs/modules/App.Hr.md). **İzin Yönetimi** (`App.Hr.Leave`) aynı kalıptadır (talep, Müdür → İK Grid Workflow onayı, İş Kanunu md.53 bakiyesi, -rapor ↔ Sağlık Kartı eşlemesi, kullanıcı detayında İzinler sekmesi); çalışma şekli [HrLeave.md](configs/seeds/docs/modules/HrLeave.md). +rapor ↔ Sağlık Kartı eşlemesi, kullanıcı detayında İzinler sekmesi); çalışma şekli [App.Hr › İzin Yönetimi](configs/seeds/docs/modules/App.Hr.md). **Puantaj ve Devam Takibi** (`App.Hr.Attendance`) hareketlerden (PDKS ucu, Excel, elle) günlük ve aylık puantaj kurar; izin, rapor, çalışma takvimi ve vardiyadan beslenir, kullanıcı detayında Puantaj sekmesi ve Intranet'te Puantajım widget'ı vardır; -çalışma şekli [HrAttendance.md](configs/seeds/docs/modules/HrAttendance.md). +çalışma şekli [App.Hr › Puantaj ve Devam Takibi](configs/seeds/docs/modules/App.Hr.md). **Yetki kodları** `PlatformConsts.AppCodes` içinde merkezî olarak tanımlıdır ve `configs/seeds/data/Abp.Identity.Permissions.json` ile seed edilir (gruplar: @@ -1248,34 +1248,22 @@ rota ve menüleri. ### 10.5. Modül dokümanları (`configs/seeds/docs/modules/`) -Konfigürasyonla üretilen her modülün çalışma şekli, keşif analizi ve kararları kendi dosyasındadır; -"bu ekran nasıl çalışıyor?" sorusunun cevabı oradadır (MCP'de `get_module_doc`). Dokümanlar seed -klasöründedir: wizard deploy'u (ekran ya da MCP) dosyayı yoksa açar ve sonundaki "Ek — Ekran -envanteri"ni her deploy, silme, tasarımcı kaydı ve import'ta wizard dosyalarından yeniden yazar; -anlatım bölümlerini üreten doldurur (MCP'de `save_module_doc`). Wizard export'u dokümanı taşır. -Yeni modül bu tabloya bir satır ekler (`lowcode.instructions.md` §0.13). Liste ekranlarının -başlığındaki ⓘ simgesi ise ekranın kendi ayrıntılı açıklamasını gösterir (`DescTr`/`DescEn`, -`lowcode.instructions.md` §4.4.2). +Konfigürasyonla üretilen modüllerin çalışma şekli, keşif analizi ve kararları **kök menü başına tek +dosyadadır**; menünün altındaki her dal dosyada bir bölümdür (`module-doc:section`). "Bu ekran nasıl +çalışıyor?" sorusunun cevabı oradadır (MCP'de `get_module_doc`; ekran ya da dal kodu verilirse +yalnızca o bölüm döner). Dosya adı kök menünün kodudur (`App.Hr` → `App.Hr.md`, +`App.Prc` → `App.Prc.md`); sabit bir liste yoktur, menü ağacından okunur. Wizard deploy'u +(ekran ya da MCP) yeni kök menünün dosyasını, yeni dalın bölümünü menü sırasındaki yerine açar ve +sondaki "Ek — Ekran envanteri"ni her deploy, silme, tasarımcı kaydı ve import'ta wizard dosyalarından +yeniden yazar; anlatım bölümlerini üreten doldurur (MCP'de `save_module_doc`). Wizard export'u +dokümanı taşır (`lowcode.instructions.md` §0.13). Liste ekranlarının başlığındaki ⓘ simgesi ise +ekranın kendi ayrıntılı açıklamasını gösterir (`DescTr`/`DescEn`, `lowcode.instructions.md` §4.4.2). -| Modül | Menü | Doküman | +| Doküman | Kök menü | Bölümler | | --- | --- | --- | -| Performans Yönetimi | İK › Performans Yönetimi (`App.Hr.Performance`) | [HrPerformance.md](configs/seeds/docs/modules/HrPerformance.md) | -| İşe Alım | İK › İşe Alım (`App.Hr.Recruitment`) | [HrRecruitment.md](configs/seeds/docs/modules/HrRecruitment.md) | -| İzin Yönetimi | İK › İzin Yönetimi (`App.Hr.Leave`) | [HrLeave.md](configs/seeds/docs/modules/HrLeave.md) | -| Puantaj ve Devam Takibi | İK › Puantaj ve Devam Takibi (`App.Hr.Attendance`) | [HrAttendance.md](configs/seeds/docs/modules/HrAttendance.md) | -| Eğitimler | İK › Eğitimler (`App.Hr.Trainings`) | [HrTrainings.md](configs/seeds/docs/modules/HrTrainings.md) | -| Araçlar | İK › Araçlar (`App.Hr.Vehicles`) | [HrVehicles.md](configs/seeds/docs/modules/HrVehicles.md) | -| Disiplin Dosyaları | İK › Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) | [HrDisciplinaryCase.md](configs/seeds/docs/modules/HrDisciplinaryCase.md) | -| Tanımlamalar (dizin + genel tanımlar) | İK › Tanımlamalar (`App.Hr.Definitions`) | [HrDefinitions.md](configs/seeds/docs/modules/HrDefinitions.md) | -| Organizasyon ve Yetkinlik | İK › Departmanlar, Pozisyonlar, Yetenek Tipleri, Organizasyon Şeması | [HrOrganization.md](configs/seeds/docs/modules/HrOrganization.md) | -| Çalışma Takvimi ve Vardiyalar | İK › Çalışma Takvimi, Vardiyalar | [HrWorkCalendar.md](configs/seeds/docs/modules/HrWorkCalendar.md) | -| Sağlık Kartları | İK › Sağlık Kartları (`App.Hr.HealthCard`) | [HrHealthCard.md](configs/seeds/docs/modules/HrHealthCard.md) | -| Ziyaretçiler | İK › Ziyaretçiler (`App.Hr.Visitor`) | [HrVisitor.md](configs/seeds/docs/modules/HrVisitor.md) | -| Olay Günlüğü | İK › Olay Günlüğü (`App.Hr.EventLog`) | [HrEventLog.md](configs/seeds/docs/modules/HrEventLog.md) | -| Personel Kaydı (özlük, sözleşme, eğitim, aile, mali bilgiler) | Kimlik › Kullanıcılar › detay | [HrPersonnel.md](configs/seeds/docs/modules/HrPersonnel.md) | -| Intranet (pano, duyuru, anket, sosyal duvar, etkinlik, doküman, mesajlaşma) | İK › Intranet (`App.Hr.Intranet`) | [HrIntranet.md](configs/seeds/docs/modules/HrIntranet.md) | -| Satınalma Tanımlamaları (ödeme/teslimat koşulları, ödeme/teslim yöntemleri) | Satınalma › Tanımlamalar (`App.Prc.Definitions`) | [PrcDefinitions.md](configs/seeds/docs/modules/PrcDefinitions.md) | -| Kontaklar (satış ve satınalmanın ortak müşteri/tedarikçi kartı ve sekmeleri, kontak etiketleri) | Yönetim › Tanımlamalar (`App.Administration.Definitions`) | [AdministrationDefinitions.md](configs/seeds/docs/modules/AdministrationDefinitions.md) | +| [App.Administration.md](configs/seeds/docs/modules/App.Administration.md) | Yönetim (`App.Administration`) | Tanımlamalar (Kontaklar: satış ve satınalmanın ortak müşteri/tedarikçi kartı ve sekmeleri, kontak etiketleri) | +| [App.Hr.md](configs/seeds/docs/modules/App.Hr.md) | İnsan Kaynakları (`App.Hr`) | Tanımlamalar (dizin + genel tanımlar), Organizasyon ve Yetkinlik, Personel Kaydı (Kimlik › Kullanıcılar › detay), İşe Alım, Çalışma Takvimi ve Vardiyalar, İzin Yönetimi, Puantaj ve Devam Takibi, Sağlık Kartları, Eğitimler, Performans Yönetimi, Disiplin Dosyaları, Araçlar, Ziyaretçiler, Olay Günlüğü, Intranet | +| [App.Prc.md](configs/seeds/docs/modules/App.Prc.md) | Satınalma (`App.Prc`) | Tanımlamalar (ödeme/teslimat koşulları, ödeme/teslim yöntemleri) | --- @@ -1572,13 +1560,13 @@ liste süzgeci ve çağrı kapısı aynı kuralı kullanır. | `deploy_wizard` | Wizard'ı Wizard ekranıyla aynı yoldan (`IListFormWizardAppService.Create`) deploy eder. Girdi seed dosyası biçimi (`{"Wizard": …}`) ya da düz cevaplardır; ikisi de `WizardSeedFileDto.FromSeedJson`'dan geçer. Dosyaya kullanıcının etkin talebi `DevRequest` olarak yazılır (sunucu doldurur). Wizard ekranı gibi yalnızca seed dosyalarını yazar; ekran DB Migrate ile kurulur ve çıkıştaki `isPending` o zamana kadar `true` kalır (model migrate'i beklemez; `verify_wizard` bekleyen dosyada `install` kontrolünde durur). `replaceFileName` doluysa güncellemedir (dosyalar yeniden yazılır, önceki kayıtları migrate kaldırır). İstek demo veri taşıyorsa (prompt'taki satırlar, ekran görüntüsü) wizard `SeedData: true` ile deploy edilir — ekranın `SeedFilePath`'i `data/{ListFormCode}.json` olur ve `SeedSync*` bayrakları açılır — satırlar aynı çağrıda `seedRows` ile bu dosyaya yazılır (alan adları doğrulanır, `Guid` anahtarı sunucu üretir); migrate ekranı kurduktan sonra satırları ekler (`lowcode.instructions.md` §0.10.1). Widget sorgularındaki her dil anahtarı tanımlı olmalı ya da wizard'ın `Language.Texts` alanında EN + TR verilmeli, yoksa deploy adlarıyla reddeder (`ValidateWidgetLanguageKeysAsync`). `uploadUrl`'süz `dxImageUpload` alanı base64 sakladığı için kolonu sınırlı boyluysa (katalogdaki karakter sınırı) deploy reddedilir; tablo kolonuna bağlı `dxImageViewer` alanı da reddedilir — görsel kolonunun editörü her zaman `dxImageUpload`'dır (`ValidateImageColumnLengths`). `MenuOrder` yok sayılır: yeni ekran kardeşlerinin sonuna, güncelleme mevcut yerine yazılır — lookup kaynağı ekran önce deploy edildiği için onu kullanan ekranın üstünde kalır. | | `delete_wizard` | Wizard Manager'daki silmeyle aynı: `InsertedRecords` + ekranın veri aynası, bağımlı wizard varsa reddedilir. `dropTables: true` ekranın tablosunu (yalnızca tasarımcı/`create_table` ile kurulmuş ve başka yerde kullanılmayan) CRUD endpoint'leri, `sql/object` ve `crud` dosyalarıyla düşürür; model bunu kullanıcı onayı olmadan göndermez (`WizardTableCleaner`, `lowcode.instructions.md` §4.5). | | `verify_wizard` | Deploy edilmiş ekranı veri yazmadan doğrular: menü kaydı ve URL'si, menünün istediği yetki tanımı (`AbpPermissions`), List yolunda ekran sorgusu (`GetSelectAsync`, tek satır, çağıranın yetkisiyle), Custom yolunda bileşen (etkin, rota = menü URL'si) ve seed kapanışı (`ExportAnalysis` uyarıları; engellemez). İsteğe bağlıdır, migrate sonrasında kullanılır; `App.DevRequests` döngüsünün adımı değildir — döngü `Testing`'de biter, kullanıcı elle test edip `Staging`'e alır (`lowcode.instructions.md` §0.11). | -| `start_dev_request` | Geliştirme talebini Id ya da tam başlıkla üstlenir: yalnızca `Ready to Start` durumundakini `In Progress` durumuna alır, diğerlerini reddeder; talebin metnini döndürür. Açıklamaya yapıştırılmış base64 görseller (`data:image/png|jpeg|gif|webp`) metinden ayıklanır (`McpDevRequestImages`), yerlerinde `[image-N]` kalır ve her biri ayrı MCP resim içeriği (`ImageContentBlock`) olarak döner — model görseli resim olarak görür, görsel hiçbir yere yüklenmez. `.Write` + `App.DevRequests.Update` ister. | +| `start_dev_request` | Geliştirme talebini Id ya da tam başlıkla üstlenir: yalnızca `Ready to Start` durumundakini `In Progress` durumuna alır, diğerlerini reddeder; talebin metnini döndürür. Açıklamaya yapıştırılmış base64 görseller (`data:image/png|jpeg|gif|webp`) metinden ayıklanır (`McpDevRequestImages`), yerlerinde `[image-N]` kalır ve her biri ayrı MCP resim içeriği (`ImageContentBlock`) olarak döner — model görseli resim olarak görür, görsel hiçbir yere yüklenmez. Sonuç istemcinin 1 MB sınırına sığdırılır: büyük görseller küçültülüp JPEG'e çevrilir (`IMcpImageShrinker`), sığmayan gönderilmez ve metinde bildirilir. `.Write` + `App.DevRequests.Update` ister. | | `get_dev_request` | Talebi durumuna dokunmadan, `start_dev_request` ile aynı biçimde (metin + analiz + resim içerikleri) okur; analizden önce ya da yarım kalan talebe dönmek için. `App.DevRequests` ister. | -| `save_dev_request_analysis` | `Backlog` ya da `Analysis` durumundaki talebin analizini (HTML) `Analysis` kolonuna yazar — var olanı değiştirir — ve talebi `Analysis` durumuna alır; diğer durumları reddeder. `Description`'a dokunmaz. Analizin standardı `lowcode.instructions.md` §0.12. `.Write` + `App.DevRequests.Update` ister. | +| `save_dev_request_analysis` | `Backlog` ya da `Analysis` durumundaki talebin analizini (HTML) `Analysis` kolonuna yazar — var olanı değiştirir — ve talebi `Analysis` durumuna alır; diğer durumları reddeder. `Description`'a dokunmaz. Zorunlu `menuCode` (dalın ya da ekranın kodu) ile analizi modül dokümanındaki dal bölümüne ("2. Analiz ve kararlar") de yazar; kök menünün ilk talebiyse dosya (`App.Inventory.md`) ve bölüm burada açılır, elle yazılmış alt bölüme dokunulmaz. Analizin standardı `lowcode.instructions.md` §0.12. `.Write` + `App.DevRequests.Update` + `App.Listforms.Wizard` ister. | | `add_dev_request_subtasks` | Talebin `SubTasks` listesine tamamlanmış satırlar ekler: model yalnızca başlığı verir, atanan kişi bağlanan kullanıcının adı (`userName`), bitiş tarihi bugün (`yyyy-MM-dd`) olarak sunucuda yazılır; var olan satırlar korunur. `.Write` + `App.DevRequests.Update` ister. | | `append_dev_request_note` | Talebin `Analysis` kolonunun sonuna HTML ekler (üretim sonuç notu); `Description` talebin yazıldığı hâliyle kalır. İkisi de `update_row` ile yazılmaz — açıklama base64 görsel taşır. `.Write` + `App.DevRequests.Update` ister. | | `list_components` / `get_component` / `save_component` / `delete_component` | Custom component'ler `ICustomComponentAppService` üzerinden; seed senkronu ve `DataSources` çözümü aynen çalışır. `save_component` ada göre ekler/günceller, tasarımcı belgesi (`Props.visualDesigner`, `sourceMode ≠ code`) taşıyan bileşene kod yazmayı reddeder — kod belgeden üretildiği için tasarımcıdaki ilk kayıtta ezilirdi. | -| `get_module_doc` / `save_module_doc` | Modül dokümanı (`configs/seeds/docs/modules/{Modül}.md`, `IModuleDocAppService`). Ad yerine ekran kodu ya da wizard dosya adı verilebilir. `save_module_doc` elle yazılan bölümleri kaydeder, "Ek — Ekran envanteri"ni sunucu üretir. Talebi `update_row` ile `Testing`'e almak, talebin wizard'larının dokümanı tamamlanmadan (dosya var, `module-doc:todo` kalmamış) reddedilir. Okuma `App.Listforms.Wizard`, yazma ayrıca `Wizards.Update` ister. | +| `get_module_doc` / `save_module_doc` | Modül dokümanı (`configs/seeds/docs/modules/{Menü}.md`, `IModuleDocAppService`). Kök menü kodu (`App.Hr`) dosyanın tamamını, ekran/dal kodu ya da wizard dosya adı yalnızca o dalın bölümünü okur/yazar. `save_module_doc` elle yazılan bölümleri kaydeder, "Ek — Ekran envanteri"ni sunucu üretir. Talebi `update_row` ile `Testing`'e almak, talebin wizard'larının bölümü tamamlanmadan (bölüm var, `module-doc:todo` kalmamış) reddedilir. Okuma `App.Listforms.Wizard`, yazma ayrıca `Wizards.Update` ister. | | `list_report_templates` / `get_report_template` / `save_report_category` / `save_report_template` / `delete_report_template` | Rapor kategorileri ve `DynamicReport` şablonları (`McpReportAppService`). Okuma depodan, ekranın okuma yetkisiyle yapılır. Yazma `App.Reports.Categories` / `App.Reports.ReportTemplates` ekranlarının C/U/D sözleşmesinden (`IListFormDataAppService`) geçer; seed senkronu aynen çalışır. Kayıt ada göre ekler/günceller. `listFormCode` verilirse HTML'deki `{{AlanAdi}}` yer tutucuları o ekranın alanlarına göre doğrulanır ve cevapta satır butonu (`rowButton`) döner (§15). | **Timesheets.** Talebin `Timesheets` listesini sunucu doldurur (`IMcpDevRequestTimesheetRecorder`): @@ -1668,7 +1656,7 @@ yetkisi yalnızca kapıdır. Bir çağrı üç katmandan geçer ve her katman ay | `delete_report_template` | — | `.Write` | `App.Reports.ReportTemplates.Delete` | | `start_dev_request` | — | `.Write` | `App.DevRequests.Update` | | `get_dev_request` | — | — | `App.DevRequests` | -| `save_dev_request_analysis` | — | `.Write` | `App.DevRequests.Update` | +| `save_dev_request_analysis` | — | `.Write` | `App.DevRequests.Update`, `App.Listforms.Wizard` (modül dokümanı) | | `append_dev_request_note` | — | `.Write` | `App.DevRequests.Update` | | `add_dev_request_subtasks` | — | `.Write` | `App.DevRequests.Update` | @@ -1719,12 +1707,14 @@ kimlik doğrulamayı istemci MCP OAuth akışıyla kendisi yürütür: sunucusunu (`AuthServer:Authority`) öğrenir, `/.well-known/oauth-authorization-server` (OpenIddict keşif belgesi, `registration_endpoint` eklenmiş) belgesini okur. 3. `/connect/register` (RFC 7591, `McpOAuthClientManager`): - - İstenen geri dönüş adresleri **bilinen istemcide** (`Platform_Mcp`; Claude, ChatGPT — - `DbMigrator` ayarı `OpenIddict:Applications:Platform_Mcp:RedirectUris`) kayıtlıysa onun - kimliği döner; onay ekranı çıkmaz. + - İstenen geri dönüş adresleri bir **bilinen istemcide** kayıtlıysa onun kimliği döner: + `Platform_Mcp` (Claude, ChatGPT; onay ekranı çıkmaz) ya da `Platform_Mcp_Local` (yerel + `mcp-remote` proxy'si, `127.0.0.1` callback'i; açık onaylı). Adresler `DbMigrator` ayarı + `OpenIddict:Applications:{ClientId}:RedirectUris`'tedir; ayarı olmayan istemci seed edilmez. - Değilse (Cursor, VS Code, Claude Code, başka bir AI istemcisi) **dinamik istemci** üretilir: `mcp_` önekli, PKCE zorunlu, **açık onaylı** OpenIddict uygulaması. Aynı adres kümesi aynı - uygulamaya bağlanır; tavan `McpConsts.MaxDynamicClients`. Kabul edilen adresler: HTTPS, + uygulamaya bağlanır — kayıt kilit altında ve kendi UoW'sinde commit edilir, masaüstü + istemcisinin aynı anda başlattığı proxy süreçleri ikinci kayıt açamaz; tavan `McpConsts.MaxDynamicClients`. Kabul edilen adresler: HTTPS, localhost HTTP (RFC 8252), uygulama şemaları (`cursor://…`); `javascript:` vb. reddedilir. Onay ekranındaki ad istemcinin beyanı + geri dönüş adresinin sahibidir (ad doğrulanamaz). 4. Kullanıcı platformun giriş ekranına (`/Account/Login`, kiracı seçimi dahil) yönlenir; @@ -2148,7 +2138,7 @@ ve `SeedPathResolver` üzerinden çözülür: configs/seeds/ ├── wizard/ # {Ad}.json → WizardDataSeeder ├── crud/ # {EntityName}.json → CrudEndpointSeedApplier -├── docs/modules/ # {Modül}.md → ModuleDocManager (seed edilmez) +├── docs/modules/ # {Menü}.md → ModuleDocManager (seed edilmez) ├── data/ # {ListFormCode}.json ya da {ListFormCode}/{anahtar}.json → ListFormSeedDataApplier │ # App.Menus.{Routes,Module,Menu}.json — route/modül/menü ağacı │ # Abp.Identity.Permission{Groups,s}.json — yetki tanımları diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application.Contracts/IMcpDevelopAppService.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application.Contracts/IMcpDevelopAppService.cs index 40b379d8..b88d93e7 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application.Contracts/IMcpDevelopAppService.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application.Contracts/IMcpDevelopAppService.cs @@ -39,9 +39,10 @@ public interface IMcpDevelopAppService : IApplicationService /// /// Talebin analizini yazar (var olani degistirir) ve talebi Analysis durumuna alir; yalnizca - /// Backlog ya da Analysis durumundaki talep analiz edilir. + /// Backlog ya da Analysis durumundaki talep analiz edilir. Analiz + /// dalinin modul dokumani bolumune de yazilir; dosya ya da bolum yoksa acilir. /// - Task SaveDevRequestAnalysisAsync(string request, string html); + Task SaveDevRequestAnalysisAsync(string request, string? menuCode, string html); /// /// Analizin sonuna HTML ekler. Aciklama talebin yazildigi haliyle kalir; uretim notlari diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDataAppService.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDataAppService.cs index ce21c459..9a9c6e4b 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDataAppService.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDataAppService.cs @@ -60,8 +60,8 @@ public class McpDataAppService( } /// - /// Gelistirme talebi Testing'e alinirken talebin urettigi wizard'larin modul dokumanlari tamam - /// olmalidir (lowcode §0.13): dosya var ve doldurulmamis (module-doc:todo) bolum yok. + /// Gelistirme talebi Testing'e alinirken talebin urettigi wizard'larin modul dokumani bolumleri + /// tamam olmalidir (lowcode §0.13): bolum var ve doldurulmamis (module-doc:todo) alt bolum yok. /// Talebi Testing'e alan tek yol update_row oldugu icin kural burada uygulanir. Wizard /// okuma yetkisi olmayan kullanici wizard uretemeyecegi icin kontrol ona uygulanmaz. /// diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDevelopAppService.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDevelopAppService.cs index 89c11719..fdae9f59 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDevelopAppService.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Application/McpDevelopAppService.cs @@ -491,9 +491,10 @@ public class McpDevelopAppService( /// /// Durum kurali modelin dikkatine birakilmaz: yalnizca Backlog ya da Analysis durumundaki talep /// analiz edilir. Analysis'teki talebin analizi begenilmediyse yeniden yazilir; Ready to Start'a - /// kullanici alir. + /// kullanici alir. Analiz modulun dokumanina da tasinir: talep ilk kez bir menude yapiliyorsa + /// dokuman ve dalin bolumu burada acilir, uretim beklenmez. /// - public async Task SaveDevRequestAnalysisAsync(string request, string html) + public async Task SaveDevRequestAnalysisAsync(string request, string? menuCode, string html) { await EnsureToolAllowedAsync(McpToolNames.SaveDevRequestAnalysis); await AuthorizationService.CheckAsync(DevRequestUpdatePermission); @@ -503,6 +504,13 @@ public class McpDevelopAppService( throw new UserFriendlyException(L[McpErrorCodes.DevRequestAnalysisRequired]); } + // Arac listesini onbellekten okuyan istemci parametreyi hic gondermeyebilir; marshaller'in + // ArgumentException'i modele ulasmaz, bu mesaj ise ulasir ve model cagriyi kodla tekrarlar. + if (string.IsNullOrWhiteSpace(menuCode)) + { + throw new UserFriendlyException(L[McpErrorCodes.DevRequestMenuCodeRequired]); + } + var devRequest = await FindDevRequestAsync(request); if (devRequest.Status is not (McpConsts.DevRequestStatuses.Backlog or McpConsts.DevRequestStatuses.Analysis)) @@ -510,6 +518,15 @@ public class McpDevelopAppService( throw new UserFriendlyException(L[McpErrorCodes.DevRequestNotAnalyzable, devRequest.Title ?? devRequest.Id.ToString(), devRequest.Status ?? string.Empty]); } + // Dokuman once yazilir: menu kodu gecersizse analiz de kaydedilmez, model kodu duzeltip tekrar dener. + await moduleDocAppService.SaveAnalysisAsync(new ModuleDocAnalysisInput + { + MenuCode = menuCode, + DevRequestId = devRequest.Id, + DevRequestTitle = devRequest.Title, + Html = html, + }); + devRequest.Analysis = html.Trim(); devRequest.Status = McpConsts.DevRequestStatuses.Analysis; await devRequestRepository.UpdateAsync(devRequest, autoSave: true); diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpConsts.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpConsts.cs index d56ab434..05f2518c 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpConsts.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpConsts.cs @@ -44,6 +44,13 @@ public static class McpConsts /// public const string OAuthClientId = "Platform_Mcp"; + /// + /// Yerel makinedeki MCP proxy'sinin (mcp-remote) istemci kimligi. Geri donus adresleri + /// DbMigrator'da OpenIddict:Applications:Platform_Mcp_Local ayarindadir. Loopback adresine + /// makinedeki her surec dinleyebildigi icin acik onay ister. + /// + public const string LocalOAuthClientId = "Platform_Mcp_Local"; + /// /// Dinamik kayitla (RFC 7591) uretilen istemcilerin kimlik oneki. Bilinen saglayicilarin /// (Claude, ChatGPT) disindaki MCP istemcileri bu onekle kendi OpenIddict uygulamasini alir. @@ -67,6 +74,7 @@ public static class McpConsts public static bool IsMcpClient(string? clientId) => clientId is not null && (string.Equals(clientId, OAuthClientId, System.StringComparison.Ordinal) + || string.Equals(clientId, LocalOAuthClientId, System.StringComparison.Ordinal) || clientId.StartsWith(DynamicClientIdPrefix, System.StringComparison.Ordinal)); /// MCP ucunun sunucu adresine gore yolu. diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpErrorCodes.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpErrorCodes.cs index c7bc315e..2f5f2e8c 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpErrorCodes.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpErrorCodes.cs @@ -57,6 +57,7 @@ public static class McpErrorCodes public const string DevRequestNotReady = Prefix + "DevRequestNotReady"; public const string DevRequestNotAnalyzable = Prefix + "DevRequestNotAnalyzable"; public const string DevRequestAnalysisRequired = Prefix + "DevRequestAnalysisRequired"; + public const string DevRequestMenuCodeRequired = Prefix + "DevRequestMenuCodeRequired"; public const string DevRequestNoteRequired = Prefix + "DevRequestNoteRequired"; public const string DevRequestSubTasksRequired = Prefix + "DevRequestSubTasksRequired"; public const string DevRequestSubTasksInvalid = Prefix + "DevRequestSubTasksInvalid"; diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpToolNames.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpToolNames.cs index 287ba648..30bd8a66 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpToolNames.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain.Shared/McpToolNames.cs @@ -149,6 +149,7 @@ public static class McpToolNames [DeleteWizard] = [PlatformConsts.AppCodes.Listforms.Wizard, PlatformConsts.AppCodes.Listforms.Wizards.Delete, PlatformConsts.AppCodes.SqlQueryManagers.Default], [GetModuleDoc] = [PlatformConsts.AppCodes.Listforms.Wizard], [SaveModuleDoc] = [PlatformConsts.AppCodes.Listforms.Wizard, PlatformConsts.AppCodes.Listforms.Wizards.Update], + [SaveDevRequestAnalysis] = [PlatformConsts.AppCodes.Listforms.Wizard], }; /// diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Data/McpOAuthClientDataSeedContributor.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Data/McpOAuthClientDataSeedContributor.cs index 74114c52..02f9d800 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Data/McpOAuthClientDataSeedContributor.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Data/McpOAuthClientDataSeedContributor.cs @@ -7,16 +7,15 @@ using Volo.Abp.DependencyInjection; namespace Sozsoft.Mcp.Data; /// -/// Bilinen MCP istemcisini () seed eder. Geri donus -/// adresleri OpenIddict:Applications:Platform_Mcp:RedirectUris ayarindadir; yeni bir -/// saglayici eklemek bu listeye callback eklemektir. +/// Bilinen MCP istemcilerini (, +/// ) seed eder. Geri donus adresleri +/// OpenIddict:Applications:{ClientId}:RedirectUris ayarindadir; yeni bir saglayici eklemek +/// bu listeye callback eklemektir. Ayari olmayan istemci olusturulmaz. /// public class McpOAuthClientDataSeedContributor( IConfiguration configuration, IMcpOAuthClientManager clientManager) : IDataSeedContributor, ITransientDependency { - private const string RedirectUrisKey = "OpenIddict:Applications:Platform_Mcp:RedirectUris"; - public async Task SeedAsync(DataSeedContext context) { // OpenIddict uygulamalari host kapsamindadir; kiraci seed turlarinda tekrarlanmaz. @@ -25,12 +24,15 @@ public class McpOAuthClientDataSeedContributor( return; } - var redirectUris = configuration.GetSection(RedirectUrisKey).Get(); - if (redirectUris is null || redirectUris.Length == 0) + foreach (var clientId in new[] { McpConsts.OAuthClientId, McpConsts.LocalOAuthClientId }) { - return; - } + var redirectUris = configuration.GetSection($"OpenIddict:Applications:{clientId}:RedirectUris").Get(); + if (redirectUris is null || redirectUris.Length == 0) + { + continue; + } - await clientManager.EnsureKnownClientAsync(redirectUris); + await clientManager.EnsureKnownClientAsync(clientId, redirectUris); + } } } diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Services/McpOAuthClientManager.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Services/McpOAuthClientManager.cs index a5c6cee7..e1e8f65a 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Services/McpOAuthClientManager.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.Domain/Services/McpOAuthClientManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -6,18 +6,22 @@ using System.Text.Json; using System.Threading.Tasks; using OpenIddict.Abstractions; using Sozsoft.Platform; +using Volo.Abp; +using Volo.Abp.DistributedLocking; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.MultiTenancy; using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.Uow; namespace Sozsoft.Mcp.Services; /// /// Uzak MCP istemcilerinin OpenIddict uygulamalari. Iki tur istemci vardir: /// -/// Bilinen istemci (): geri donus adresleri -/// DbMigrator ayarinda sabit olan saglayicilar (Claude, ChatGPT). Onay ekrani gostermez. +/// Bilinen istemci: geri donus adresleri DbMigrator ayarinda sabit olan istemciler — +/// (Claude, ChatGPT; onay ekrani gostermez) ve +/// (yerel mcp-remote proxy'si; acik onayli). /// Dinamik istemci (): baska bir MCP /// istemcisi (Cursor, VS Code, Claude Code, ...) kayit ucundan kendi uygulamasini alir. Kayit /// herkese acik oldugu icin bu istemciler acik onay ister: kullanici giris yaptiktan sonra @@ -28,10 +32,10 @@ namespace Sozsoft.Mcp.Services; public interface IMcpOAuthClientManager { /// Bilinen istemciyi olusturur ya da geri donus adreslerini gunceller. - Task EnsureKnownClientAsync(IReadOnlyCollection redirectUris); + Task EnsureKnownClientAsync(string clientId, IReadOnlyCollection redirectUris); /// - /// Istemci kaydi. Adresler bilinen istemcide kayitliysa onu, degilse ayni adres kumesine + /// Istemci kaydi. Adresler bir bilinen istemcide kayitliysa onu, degilse ayni adres kumesine /// sahip dinamik istemciyi dondurur; yoksa yenisini uretir. /// Task RegisterAsync(string? clientName, IReadOnlyCollection redirectUris); @@ -40,25 +44,33 @@ public interface IMcpOAuthClientManager public class McpOAuthClientManager( IAbpApplicationManager applicationManager, IRepository applicationRepository, - ICurrentTenant currentTenant) + ICurrentTenant currentTenant, + IAbpDistributedLock distributedLock, + IUnitOfWorkManager unitOfWorkManager) : DomainService, IMcpOAuthClientManager { private const int MaxClientNameLength = 100; + private const string RegistrationLockName = "Mcp:OAuthClientRegistration"; + private static readonly TimeSpan RegistrationLockTimeout = TimeSpan.FromSeconds(15); + + private static readonly Dictionary KnownClients = new(StringComparer.Ordinal) + { + [McpConsts.OAuthClientId] = ("MCP Connectors", OpenIddictConstants.ConsentTypes.Implicit), + [McpConsts.LocalOAuthClientId] = ("MCP Local Proxy", OpenIddictConstants.ConsentTypes.Explicit) + }; /// Tarayici disi calistirilabilir icerik tasiyan, geri donus adresi olamayacak semalar. private static readonly string[] ForbiddenSchemes = ["javascript", "data", "file", "vbscript", "about", "blob"]; - public async Task EnsureKnownClientAsync(IReadOnlyCollection redirectUris) + public async Task EnsureKnownClientAsync(string clientId, IReadOnlyCollection redirectUris) { + var (displayName, consentType) = KnownClients[clientId]; + // OpenIddict uygulamalari host kapsamindadir. using (currentTenant.Change(null)) { - var existing = await applicationManager.FindByClientIdAsync(McpConsts.OAuthClientId); - var descriptor = BuildDescriptor( - McpConsts.OAuthClientId, - "MCP Connectors", - redirectUris, - OpenIddictConstants.ConsentTypes.Implicit); + var existing = await applicationManager.FindByClientIdAsync(clientId); + var descriptor = BuildDescriptor(clientId, displayName, redirectUris, consentType); if (existing is null) { @@ -88,42 +100,63 @@ public class McpOAuthClientManager( using (currentTenant.Change(null)) { - var known = await applicationManager.FindByClientIdAsync(McpConsts.OAuthClientId); - if (known is not null) + foreach (var knownClientId in KnownClients.Keys) { + var known = await applicationManager.FindByClientIdAsync(knownClientId); + if (known is null) + { + continue; + } + var knownUris = await applicationManager.GetRedirectUrisAsync(known); if (redirectUris.All(uri => knownUris.Any(registered => SameUri(registered, uri)))) { - return McpClientRegistration.Accepted(McpConsts.OAuthClientId); + return McpClientRegistration.Accepted(knownClientId); } } - var dynamicClients = await GetDynamicClientsAsync(); + // Masaustu istemcisi ayni anda birden cok proxy sureci baslatir ve hepsi ayni adreslerle + // kayit olur. Kontrol ile ekleme kilitsiz ve istegin UoW'sinde kalirsa hicbiri digerinin + // kaydini goremez, ayni adres kumesi icin birden cok uygulama acilir. Kilit altinda + // calisip kendi UoW'sinde commit eden kayit, sonraki istegin onu bulmasini saglar. + await using var handle = await distributedLock.TryAcquireAsync(RegistrationLockName, RegistrationLockTimeout) + ?? throw new AbpException($"Could not acquire '{RegistrationLockName}' lock."); - // Ayni istemci her baglantida yeniden kayit olabilir; ayni adres kumesi tek uygulamaya - // baglanir, tablo buyumez. - var match = dynamicClients.FirstOrDefault(client => SameUriSet(client.RedirectUris, redirectUris)); - if (match.ClientId is not null) - { - return McpClientRegistration.Accepted(match.ClientId); - } + using var uow = unitOfWorkManager.Begin(requiresNew: true, isTransactional: true); + var registration = await RegisterDynamicClientAsync(clientName, redirectUris); + await uow.CompleteAsync(); - if (dynamicClients.Count >= McpConsts.MaxDynamicClients) - { - return McpClientRegistration.Rejected(McpClientRegistrationError.LimitReached, McpConsts.MaxDynamicClients.ToString(CultureInfo.InvariantCulture)); - } - - var clientId = McpConsts.DynamicClientIdPrefix + GuidGenerator.Create().ToString("N"); - await applicationManager.CreateAsync(BuildDescriptor( - clientId, - DisplayNameOf(clientName, redirectUris.First()), - redirectUris, - OpenIddictConstants.ConsentTypes.Explicit)); - - return McpClientRegistration.Accepted(clientId); + return registration; } } + private async Task RegisterDynamicClientAsync(string? clientName, IReadOnlyCollection redirectUris) + { + var dynamicClients = await GetDynamicClientsAsync(); + + // Ayni istemci her baglantida yeniden kayit olabilir; ayni adres kumesi tek uygulamaya + // baglanir, tablo buyumez. + var match = dynamicClients.FirstOrDefault(client => SameUriSet(client.RedirectUris, redirectUris)); + if (match.ClientId is not null) + { + return McpClientRegistration.Accepted(match.ClientId); + } + + if (dynamicClients.Count >= McpConsts.MaxDynamicClients) + { + return McpClientRegistration.Rejected(McpClientRegistrationError.LimitReached, McpConsts.MaxDynamicClients.ToString(CultureInfo.InvariantCulture)); + } + + var clientId = McpConsts.DynamicClientIdPrefix + GuidGenerator.Create().ToString("N"); + await applicationManager.CreateAsync(BuildDescriptor( + clientId, + DisplayNameOf(clientName, redirectUris.First()), + redirectUris, + OpenIddictConstants.ConsentTypes.Explicit)); + + return McpClientRegistration.Accepted(clientId); + } + private async Task RedirectUris)>> GetDynamicClientsAsync() { var query = await applicationRepository.GetQueryableAsync(); diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/IMcpImageShrinker.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/IMcpImageShrinker.cs new file mode 100644 index 00000000..824bfb35 --- /dev/null +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/IMcpImageShrinker.cs @@ -0,0 +1,18 @@ +namespace Sozsoft.Mcp.Tools; + +/// +/// Arac sonucundaki gorselleri istemcinin boyut sinirina sigdirir. MCP istemcileri tek bir arac +/// sonucunu sinirlar (Claude Desktop 1 MB); talep aciklamasina yapistirilan ekran goruntuleri +/// tek basina bu siniri asabilir. Gorsel isleme kutuphanesi barindiran uygulamadadir; modul +/// grafik paketine baglanmaz. +/// +public interface IMcpImageShrinker +{ + /// + /// Base64 uzunlugu 'i asmayan gorsel dondurur: sigiyorsa oldugu gibi, + /// sigmiyorsa kucultulmus JPEG. Okunabilir boyutta sigdirilamazsa ya da cozulemezse null. + /// + McpShrunkImage? Shrink(string mimeType, string base64, int maxLength); +} + +public sealed record McpShrunkImage(string MimeType, string Data); diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopPrompts.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopPrompts.cs index e4afa6d1..27ecf6f7 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopPrompts.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopPrompts.cs @@ -43,7 +43,7 @@ public static class McpDevelopPrompts "Talebi start_dev_request ile ustlen. Arac reddederse (talep Ready to Start degil, bulunamadi ya da " + "birden fazla eslesme var) hicbir sey uretme, baska bir talebe gecme: nedenini bildir ve dur. " + "Talep (Description) ve onaylanmis analizi (Analysis) birlikte tarifin kendisidir: soru sorma, DB Migrate'i bekleme. " + - "Testing'e almadan once uretilen modulun dokumanini get_module_doc ile oku, todo bolumlerini save_module_doc ile doldur (lowcode 0.13); sonra talebi Testing'e alip bitir. " + + "Testing'e almadan once uretilen ekranin modul dokumani bolumunu get_module_doc ile ekran koduyla oku, todo alt bolumlerini save_module_doc ile ayni kodla doldur (lowcode 0.13); sonra talebi Testing'e alip bitir. " + "Sonunda rapor ver: uretilen artefaktlar, talebin son durumu ve DB Migrate gerektigi."; [McpServerPrompt(Name = McpPromptNames.ProcessReadyRequests)] @@ -53,6 +53,6 @@ public static class McpDevelopPrompts "Once get_dev_guide ile lowcode 0.11 bolumunu oku ve oradaki adimlari uygula. " + "Her talebi start_dev_request ile ustlen; reddedilen talebi atla ve rapora yaz. " + "Talep (Description) ve onaylanmis analizi (Analysis) birlikte tarifin kendisidir: soru sorma, DB Migrate'i bekleme. " + - "Her talepte Testing'e almadan once modul dokumanini save_module_doc ile doldur (lowcode 0.13), sonra talebi Testing'e alip digerine gec. " + + "Her talepte Testing'e almadan once ekranin modul dokumani bolumunu save_module_doc ile doldur (lowcode 0.13), sonra talebi Testing'e alip digerine gec. " + "Sonunda parti raporu ver: talep basina uretilen artefaktlar ve son durum; DB Migrate gerektigini tek satirda belirt."; } diff --git a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopTools.cs b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopTools.cs index 8a48d265..5ee1d34f 100644 --- a/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopTools.cs +++ b/api/modules/Sozsoft.Mcp/Sozsoft.Mcp.HttpApi/Tools/McpDevelopTools.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Text.Json; @@ -17,10 +18,16 @@ namespace Sozsoft.Mcp.Tools; /// yolla ayni sekilde olusur. /// [McpServerToolType] -public sealed class McpDevelopTools(IMcpDevelopAppService developAppService) +public sealed class McpDevelopTools(IMcpDevelopAppService developAppService, IMcpImageShrinker imageShrinker) { private static readonly JsonSerializerOptions TextOptions = new(JsonSerializerDefaults.Web); + /// + /// Talep sonucunun (metin + base64 gorseller) ust siniri, karakter. Claude Desktop arac sonucunu + /// 1 MB ile sinirlar; JSON-RPC zarfi ve kacislar icin pay birakilir. + /// + private const int MaxResultLength = 900_000; + [McpServerTool(Name = McpToolNames.GetDevGuide, ReadOnly = true)] [Description("Ekran ve bilesen uretim sozlesmesini okur: wizard alanlari, enum degerleri, editor/lookup/script sozlesmesi, custom component kurallari. section bos ise baslik listesi doner; once listeyi al, sonra ihtiyac duydugun bolumu numarasiyla iste (ornegin 4.2). Rehberde dosya yazmak anlatilan yerlerde dosya yerine bu sunucunun araclarini kullan.")] public async Task GetDevGuideAsync( @@ -110,8 +117,10 @@ public sealed class McpDevelopTools(IMcpDevelopAppService developAppService) [Description("Talebin Id'si (GUID) ya da tam basligi.")] string request, [Description("Analizin tamami, HTML.")] - string html) - => ToContent(await developAppService.SaveDevRequestAnalysisAsync(request, html)); + string html, + [Description("Zorunlu. Talebin menu yeri: kok menunun altindaki dalin ya da ekranin kodu (App.Inventory.Definitions, App.Hr.LeaveRequest); analizdeki Menu yeri ile ayni. Menude henuz olmayan yeni kod da verilir. Analiz bu dalin modul dokumani bolumune ('2. Analiz ve kararlar') yazilir; kok menunun dosyasi (App.Inventory.md) ya da dalin bolumu yoksa acilir.")] + string? menuCode = null) + => ToContent(await developAppService.SaveDevRequestAnalysisAsync(request, menuCode, html)); [McpServerTool(Name = McpToolNames.AppendDevRequestNote, Destructive = false, Idempotent = false)] [Description("Talebin Analysis alaninin sonuna HTML ekler; var olan analize ve Description'a dokunmaz. Description talebin yazildigi haliyle kalir; uretim sonuc notunu (

MCP

+ uretilenler, varsayimlar ve DB Migrate bekleyen wizard'lar) bu aracla ekle. Description'i ya da Analysis'i update_row ile yazma.")] @@ -139,33 +148,58 @@ public sealed class McpDevelopTools(IMcpDevelopAppService developAppService) [McpServerTool(Name = McpToolNames.GetModuleDoc, ReadOnly = true)] - [Description("Modul dokumanini (docs/modules/{Modul}.md, seed klasoru) okur: nasil calistigi, analiz/kararlar, ekranlar, hesaplar, yetkiler ve otomatik 'Ek — Ekran envanteri'. isComplete false ise missingSections doldurulmamis bolumlerdir. 'Bu modul/ekran nasil calisiyor?' sorusunda once bunu oku. Ad yerine ekranin kodu (App.Hr.PerformanceReview) ya da wizard dosya adi da verilebilir; deploy_wizard dokumani yoksa iskeletini kendisi acar.")] + [Description("Modul dokumanini (docs/modules/{Menu}.md, seed klasoru; kok menu basina tek dosya, adi kok menu kodu: App.Hr, App.Prc, App.Administration) okur: nasil calistigi, analiz/kararlar, ekranlar, hesaplar, yetkiler ve otomatik 'Ek — Ekran envanteri'. Menunun altindaki her dal dosyada bir bolumdur; ekranin ya da dalin kodu (App.Hr.PerformanceReview, App.Hr.Performance) ya da wizard dosya adi verilirse yalnizca o bolum ve envanteri doner, dosya adi verilirse dosyanin tamami. isComplete false ise missingSections doldurulmamis alt bolumlerdir. 'Bu modul/ekran nasil calisiyor?' sorusunda once bunu ekran koduyla oku; deploy_wizard dosyayi ve dalin bolumunu yoksa kendisi acar. Menude henuz olmayan yeni modulun kodu (App.Inventory, App.Inventory.Stock) hata vermez: exists false ve doldurulacak iskelet doner; save_module_doc ayni kodla yazinca dosya acilir.")] public async Task GetModuleDocAsync( - [Description("Dokuman adi (HrPerformance), ekran kodu ya da wizard dosya adi.")] + [Description("Ekran ya da dal kodu, wizard dosya adi (o bolum) veya kok menu kodu (App.Hr; dosyanin tamami).")] string name) => await developAppService.GetModuleDocAsync(name); [McpServerTool(Name = McpToolNames.SaveModuleDoc, Destructive = true, Idempotent = true)] - [Description("Modul dokumaninin elle yazilan bolumlerini kaydeder (Markdown, dosyanin tamami). Uretimin parcasidir: deploy_wizard'dan sonra once get_module_doc ile iskeleti oku, module-doc:todo isaretli her bolumu (Amac ve kapsam, Analiz ve kararlar — onaylanmis analiz ve kararlar, Menu ve ekranlar, Veri modeli, Is kurallari ve hesaplar, Yetki ve gorunurluk, Entegrasyonlar, Akis ornegi, Sik sorulanlar, Dosyalar ve geri alma) doldurup isaretleri kaldirarak gonder; bos kalacak bolume 'Yok.' yaz. 'Ek — Ekran envanteri' bolumunu gonderme, sunucu uretir. Ilk satirdaki '' beyanini koru. Talep, dokumanlari tamamlanmadan update_row ile Testing'e alinamaz. Bolum standardi get_dev_guide lowcode 0.13.")] + [Description("Modul dokumaninin elle yazilan bolumunu kaydeder (Markdown). Uretimin parcasidir: deploy_wizard'dan sonra get_module_doc ile ekranin bolumunu oku, module-doc:todo isaretli her alt bolumu (Amac ve kapsam, Analiz ve kararlar — onaylanmis analiz ve kararlar, Menu ve ekranlar, Veri modeli, Is kurallari ve hesaplar, Yetki ve gorunurluk, Entegrasyonlar, Akis ornegi, Sik sorulanlar, Dosyalar ve geri alma) doldurup isaretleri kaldirarak ayni ekran ya da dal koduyla gonder: yalnizca o bolum yazilir, diger dallara dokunulmaz. Bos kalacak alt bolume 'Yok.' yaz. 'Ek — Ekran envanteri' bolumunu gonderme, sunucu uretir. Bolumun '' beyan satirini gondermezsen mevcut beyan korunur. Kok menu koduyla (App.Hr) cagrilirsa dosyanin tamami yazilir. Talep, bolumu tamamlanmadan update_row ile Testing'e alinamaz. Bolum standardi get_dev_guide lowcode 0.13.")] public async Task SaveModuleDocAsync( - [Description("Dokuman adi (HrPerformance), ekran kodu ya da wizard dosya adi.")] + [Description("Ekran ya da dal kodu, wizard dosya adi (o bolum) veya kok menu kodu (App.Hr; dosyanin tamami).")] string name, - [Description("Dokumanin tamami, Markdown.")] + [Description("Bolumun (ya da dosya adi verildiyse dosyanin) tamami, Markdown.")] string content) => await developAppService.SaveModuleDocAsync(name, content); /// /// Talep metni JSON olarak, gorseller ayri resim icerigi olarak doner; model resmi ancak bu - /// bicimde gorur, base64 metni olarak goremez. + /// bicimde gorur, base64 metni olarak goremez. Sonucun tamami istemcinin sinirina sigar: kalan + /// pay gorsellere esit bolunur, payini asan gorsel kucultulur, kucultulse de sigmayan gonderilmez + /// ve hangisinin eksik oldugu metinde bildirilir. /// - private static List ToContent(McpDevRequestDto devRequest) + private List ToContent(McpDevRequestDto devRequest) { - List content = [new TextContentBlock { Text = JsonSerializer.Serialize(devRequest, TextOptions) }]; + var text = JsonSerializer.Serialize(devRequest, TextOptions); + List content = [new TextContentBlock { Text = text }]; - foreach (var image in devRequest.Images) + var remaining = MaxResultLength - text.Length; + var omitted = new List(); + + for (var i = 0; i < devRequest.Images.Count; i++) { + var image = devRequest.Images[i]; + var share = Math.Max(0, remaining) / (devRequest.Images.Count - i); + var shrunk = imageShrinker.Shrink(image.MimeType, image.Data, share); + if (shrunk is null) + { + omitted.Add(image.Placeholder); + continue; + } + + remaining -= shrunk.Data.Length; + // Veri zaten base64; cozup yeniden kodlamak buyuk gorsellerde bosuna bellek harcar. - content.Add(new ImageContentBlock { Data = Encoding.UTF8.GetBytes(image.Data), MimeType = image.MimeType }); + content.Add(new ImageContentBlock { Data = Encoding.UTF8.GetBytes(shrunk.Data), MimeType = shrunk.MimeType }); + } + + if (omitted.Count > 0) + { + content.Add(new TextContentBlock + { + Text = $"Boyut siniri nedeniyle gonderilmeyen gorseller: {string.Join(", ", omitted)}. Gerekirse kullanicidan gorselin ne gosterdigini sor." + }); } return content; diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/ModuleDocs/IModuleDocAppService.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/ModuleDocs/IModuleDocAppService.cs index 23b278b7..46780a0a 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/ModuleDocs/IModuleDocAppService.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/ModuleDocs/IModuleDocAppService.cs @@ -6,9 +6,9 @@ using Volo.Abp.Application.Services; namespace Sozsoft.Platform.ListForms; /// -/// Modul dokumanlari (docs/modules/{Modul}.md, kapsam seed klasoru). Dokumanin elle ya da -/// AI ile yazilan bolumleri kaydedilir; "Ek — Ekran envanteri" bolumu wizard dosyalarindan uretilir -/// ve her deploy, silme, tasarimci kaydi ve import'ta yenilenir. +/// Modul dokumanlari (docs/modules/{Menu}.md, kok menu basina bir dosya; kokun altindaki her +/// dal dosyada bir bolum). Dokumanin elle ya da AI ile yazilan bolumleri kaydedilir; "Ek — Ekran +/// envanteri" bolumu wizard dosyalarindan uretilir ve her deploy, silme, tasarimci kaydi ve import'ta yenilenir. /// public interface IModuleDocAppService : IApplicationService { @@ -16,13 +16,15 @@ public interface IModuleDocAppService : IApplicationService Task> GetListAsync(); /// - /// Dokumani adiyla (HrPerformance) ya da ait oldugu ekranin kodu/wizard dosya adiyla - /// (App.Hr.PerformanceReview, PerformanceReview.json) dondurur. + /// Dokumanin tamamini kok menu koduyla (App.Hr), bir dalin bolumunu dal kodu ya da ekranin + /// kodu/wizard dosya adiyla (App.Hr.Performance, App.Hr.PerformanceReview, + /// PerformanceReview.json) dondurur. /// Task GetByNameAsync(string name); /// - /// Dokumanin elle yazilan bolumlerini kaydeder; otomatik envanter bolumu girdiden atilir ve + /// Dokumanin elle yazilan bolumlerini kaydeder: ad dokumana isaret ediyorsa dosyanin tamami, dala + /// ya da ekrana isaret ediyorsa yalnizca o bolum yazilir. Otomatik envanter girdiden atilir ve /// yeniden uretilir. /// Task SaveAsync(ModuleDocSaveInput input); @@ -32,39 +34,62 @@ public interface IModuleDocAppService : IApplicationService /// bolum var). Bos liste talebin dokumantasyonunun tamam oldugunu gosterir. ///
Task> GetIncompleteForDevRequestAsync(Guid devRequestId); + + /// + /// Talep analizini dalin bolumune ("2. Analiz ve kararlar") yazar; bolum ya da dosya yoksa acar. + /// Elle yazilmis alt bolume dokunulmaz. + /// + Task SaveAnalysisAsync(ModuleDocAnalysisInput input); } public class ModuleDocDto { - /// Dosya adi, uzantisiz (HrPerformance). + /// Dosya adi, uzantisiz; kok menunun kodu (App.Hr). public string Name { get; set; } = string.Empty; - /// Seed klasorune gore goreli yol (docs/modules/HrPerformance.md). + /// Dalin bolum anahtari (App.Hr.Performance); dokumanin tamami istendiyse null. + public string? Section { get; set; } + + /// Seed klasorune gore goreli yol (docs/modules/App.Hr.md). public string Path { get; set; } = string.Empty; + /// Dosya (bolum istendiyse dosyada bolum) var. public bool Exists { get; set; } /// - /// Dosyada doldurulmamis bolum yoksa true. Otomatik acilan iskeletin bolumleri - /// module-doc:todo isaretini tasir; isaret kalmayinca dokuman tamam sayilir. + /// Dosyada (bolum istendiyse bolumde) doldurulmamis alt bolum yoksa true. Otomatik acilan + /// iskeletin alt bolumleri module-doc:todo isaretini tasir; isaret kalmayinca tamam sayilir. /// public bool IsComplete { get; set; } - /// Doldurulmamis bolum basliklari. + /// Doldurulmamis alt bolumler (Bolum › Alt bolum). public List MissingSections { get; set; } = []; - /// Dokumana bagli ekran kodlari (wizard'larin ListFormCode / menu kodu). + /// Dokumana (ya da bolume) bagli ekran kodlari (wizard'larin ListFormCode / menu kodu). public List Wizards { get; set; } = []; - /// Dosyanin tamami; listede doldurulmaz. + /// Dosyanin tamami ya da bolum ve envanteri; listede doldurulmaz. public string? Content { get; set; } } public class ModuleDocSaveInput { - /// Dokuman adi ya da ait oldugu ekranin kodu/wizard dosya adi. + /// Dokuman adi (dosyanin tamami) ya da dal/ekran kodu, wizard dosya adi (o dalin bolumu). public string Name { get; set; } = string.Empty; /// Markdown. Otomatik envanter bolumu varsa yok sayilir. public string Content { get; set; } = string.Empty; } + +public class ModuleDocAnalysisInput +{ + /// Talebin menu yeri: dalin ya da ekranin kodu (App.Inventory.Definitions). + public string MenuCode { get; set; } = string.Empty; + + public Guid DevRequestId { get; set; } + + public string? DevRequestTitle { get; set; } + + /// Analiz, HTML. + public string Html { get; set; } = string.Empty; +} diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs index be180ec2..58b7a96f 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ListFormWizardAppService.cs @@ -2752,7 +2752,7 @@ public class ListFormWizardAppService( // host/object|execute); digerlerinde alt klasor yoktur. if (isDocsFolder) { - // Yalnizca modul dokumanlari: docs/modules/{Modul}.md. + // Yalnizca modul dokumanlari: docs/modules/{Menu}.md. if (segments.Length != 3 || !segments[1].Equals(SeedPathResolver.ModuleDocsFolder, StringComparison.OrdinalIgnoreCase)) return null; } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocAppService.cs b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocAppService.cs index 1f0a0bda..2023ddbe 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocAppService.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocAppService.cs @@ -27,4 +27,14 @@ public class ModuleDocAppService(ModuleDocManager manager) : PlatformAppService, public Task> GetIncompleteForDevRequestAsync(Guid devRequestId) => manager.GetIncompleteForDevRequestAsync(devRequestId); + + /// + /// Talep analizinin parcasidir; talebi analiz edebilen (Wizard ekranini okuyabilen) kullanici + /// dokumanin iskeletini ve analiz alt bolumunu yazabilir, diger bolumler icin gerekir. + /// + public Task SaveAnalysisAsync(ModuleDocAnalysisInput input) + { + Check.NotNull(input, nameof(input)); + return manager.SaveAnalysisAsync(input.MenuCode, input.DevRequestId, input.DevRequestTitle, input.Html); + } } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocCatalog.cs b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocCatalog.cs index d03304a4..cb59bb81 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocCatalog.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocCatalog.cs @@ -11,14 +11,19 @@ namespace Sozsoft.Platform.ListForms; /// /// Bir seed klasorundeki wizard dosyalarini ve modul dokumanlarini okur; her wizard'in hangi -/// dokumana ait oldugunu cozer. Kural, wizard sozlesmesine alan eklemeden menu agacindan cikar: +/// dokumana ve dokumanin hangi bolumune ait oldugunu cozer. +/// +/// Dokuman kok menu basina tektir ve adi menu kodudur (App.Hr → App.Hr.md); kokun altindaki her dal +/// dokumanda bir bolumdur (<!-- module-doc:section App.Hr.Leave --> + ## basligi). +/// Kural, wizard sozlesmesine alan eklemeden menu agacindan cikar: +/// /// -/// Bir dokuman ekranin kodunu basligindaki beyanla sahiplenmisse (module-doc: claims=…) o dokuman. -/// Menusuz alt form, onu SubForms icinde tasiyan ekranin dokumanina gider. -/// Ust menu zincirinde kokun altinda bir dal varsa (App.Hr › App.Hr.Performance › …) -/// dalin kodu, yoksa (ekran dogrudan kokun altinda) ekranin kendi kodu. +/// Bir bolum ekranin kodunu beyanla sahiplenmisse (module-doc:section … claims=…) o bolum. +/// Menusuz alt form, onu SubForms icinde tasiyan ekranin bolumune gider. +/// Menu agacinda kokun altindaki ilk seviye (App.Hr › App.Hr.Performance › …) bolumdur; +/// ekran dogrudan kokun altindaysa ekranin kendi kodu. /// -/// Dokuman adi koddan turer: bastaki App. atilir, noktalar silinir (App.Hr.Performance → HrPerformance). +/// Ad sabit bir listeden degil menu agacindan gelir; yeni bir kok menu ilk deploy'unda kendi dosyasini acar. /// public sealed class ModuleDocCatalog { @@ -28,10 +33,20 @@ public sealed class ModuleDocCatalog /// Doldurulmamis bolumun isareti; isaret kalmayan dokuman tamam sayilir. public const string TodoMarker = ""; - private static readonly Regex ClaimsPattern = new(@"", RegexOptions.Compiled); - private static readonly Regex NamePattern = new("^[A-Za-z0-9_-]+$", RegexOptions.Compiled); + private static readonly Regex SectionPattern = new( + @"^[ \t]*$", + RegexOptions.Compiled | RegexOptions.Multiline); - private readonly Dictionary claims = new(StringComparer.OrdinalIgnoreCase); + private static readonly Regex NamePattern = new(@"^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+)*$", RegexOptions.Compiled); + + /// Ekran kodu → (dokuman, bolum) beyanlari. + private readonly Dictionary claims = new(StringComparer.OrdinalIgnoreCase); + + /// Menu kodu → ust menu kodu ve sirasi (data/App.Menus.Menu.json). + private readonly Dictionary menus = new(StringComparer.OrdinalIgnoreCase); + + /// Menu kodu → Turkce adi (data/App.Languages.LanguageText.json); bolum basliklari icin. + private readonly Dictionary menuTitles = new(StringComparer.OrdinalIgnoreCase); private ModuleDocCatalog(string scopeRoot) { @@ -67,19 +82,71 @@ public sealed class ModuleDocCatalog } } + await catalog.LoadMenusAsync(); + foreach (var name in catalog.ExistingDocNames()) { - var match = ClaimsPattern.Match(await File.ReadAllTextAsync(catalog.DocPath(name))); - if (!match.Success) - continue; - - foreach (var code in match.Groups["codes"].Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) - catalog.claims.TryAdd(code, name); + foreach (var section in ParseSections(await File.ReadAllTextAsync(catalog.DocPath(name)))) + { + catalog.claims.TryAdd(section.Key, (name, section.Key)); + foreach (var code in section.Claims) + catalog.claims.TryAdd(code, (name, section.Key)); + } } return catalog; } + /// + /// Menu agaci ve menu adlari seed dosyalarindan okunur; wizard deploy'u menu ve dil satirlarini + /// ayni dosyalara yazdigi icin yeni bir dal da migrate beklemeden gorunur. + /// + private async Task LoadMenusAsync() + { + foreach (var row in await ReadRowsAsync("App.Menus.Menu.json")) + { + var code = Text(row, "Code"); + if (code == null) + continue; + + menus[code] = (Text(row, "ParentCode"), row.TryGetProperty("Order", out var order) && order.TryGetInt32(out var value) ? value : int.MaxValue); + } + + foreach (var row in await ReadRowsAsync("App.Languages.LanguageText.json")) + { + var key = Text(row, "Key"); + if (key == null || !menus.ContainsKey(key)) + continue; + + if (string.Equals(Text(row, "CultureName"), "tr", StringComparison.OrdinalIgnoreCase) && Text(row, "Value") is { } title) + menuTitles[key] = title; + } + } + + private async Task> ReadRowsAsync(string fileName) + { + var path = Path.Combine(ScopeRoot, SeedPathResolver.DataFolder, fileName); + if (!File.Exists(path)) + return []; + + try + { + using var document = JsonDocument.Parse(await File.ReadAllTextAsync(path)); + return document.RootElement.TryGetProperty("Rows", out var rows) && rows.ValueKind == JsonValueKind.Array + ? [.. rows.EnumerateArray().Select(r => r.Clone())] + : []; + } + catch (JsonException) + { + return []; + } + } + + private static string? Text(JsonElement row, string property) => + row.TryGetProperty(property, out var value) && value.ValueKind == JsonValueKind.String && !string.IsNullOrWhiteSpace(value.GetString()) + ? value.GetString()!.Trim() + : null; + public IEnumerable ExistingDocNames() => Directory.Exists(DocsPath) ? Directory.GetFiles(DocsPath, "*.md").Select(Path.GetFileNameWithoutExtension).OfType() @@ -91,26 +158,33 @@ public sealed class ModuleDocCatalog public static bool IsValidName(string? name) => !string.IsNullOrWhiteSpace(name) && NamePattern.IsMatch(name); - /// App.Hr.Performance → HrPerformance. - public static string NameFromCode(string code) - { - var trimmed = code.Trim(); - if (trimmed.StartsWith("App.", StringComparison.OrdinalIgnoreCase)) - trimmed = trimmed[4..]; + /// + /// Kok menunun dokuman adi: menu kodunun kendisi (App.Hr → App.Hr.md). Dosya adina + /// girmeyecek karakterler atilir. + /// + public static string DocNameOfRoot(string rootCode) => + string.Concat(rootCode.Trim().Where(c => char.IsLetterOrDigit(c) || c is '.' or '_' or '-')); - return string.Concat(trimmed.Where(char.IsLetterOrDigit)); - } + /// Menu kodunun Turkce adi; dil satiri yoksa null. + public string? MenuTitle(string code) => menuTitles.GetValueOrDefault(code); + + /// Bolumun kok menu altindaki sirasi; menude olmayan bolum (ornegin elle yazilmis) sona gider. + public int SectionOrder(string sectionKey) => menus.TryGetValue(sectionKey, out var menu) ? menu.Order : int.MaxValue; /// Wizard'in ait oldugu dokumanin adi. - public string Resolve(ListFormWizardDto wizard) => Resolve(wizard, new HashSet(StringComparer.OrdinalIgnoreCase)); + public string Resolve(ListFormWizardDto wizard) => ResolveTarget(wizard).Doc; - private string Resolve(ListFormWizardDto wizard, HashSet visited) + /// Wizard'in ait oldugu dokuman, bolum ve kok menu. + public (string Doc, string Section, string Root) ResolveTarget(ListFormWizardDto wizard) => + ResolveTarget(wizard, new HashSet(StringComparer.OrdinalIgnoreCase)); + + private (string Doc, string Section, string Root) ResolveTarget(ListFormWizardDto wizard, HashSet visited) { var listFormCode = wizard.ResolveListFormCode(); var menuCode = wizard.ResolveMenuCode(); if (claims.TryGetValue(listFormCode, out var claimed) || claims.TryGetValue(menuCode, out claimed)) - return claimed; + return (claimed.Doc, claimed.Section, RootOfDoc(claimed.Doc, wizard)); visited.Add(listFormCode); @@ -121,30 +195,80 @@ public sealed class ModuleDocCatalog .FirstOrDefault(w => !visited.Contains(w.ResolveListFormCode()) && (w.SubForms ?? []).Any(s => string.Equals(s.Code, listFormCode, StringComparison.OrdinalIgnoreCase))); if (parent != null) - return Resolve(parent, visited); + return ResolveTarget(parent, visited); } - return NameFromCode(BranchCode(wizard)); - } + var path = MenuPath(wizard); + var root = path[0]; + var section = path.Count >= 2 ? path[1] : menuCode; - /// Wizard'in dokumanini tasiyan menu dali: kokun altindaki ilk seviye ya da ekranin kendisi. - public static string BranchCode(ListFormWizardDto wizard) - { - var chain = wizard.ResolveMenuParentChain(); - return chain.Count >= 2 ? chain[1].Code : wizard.ResolveMenuCode(); + return (DocNameOfRoot(root), section, root); } - /// Dokuman adlarina gore gruplanmis wizard'lar. - public Dictionary> GroupByDoc() => - Wizards - .GroupBy(w => Resolve(w.Seed.Wizard), StringComparer.OrdinalIgnoreCase) - .ToDictionary(g => g.Key, g => g.ToList(), StringComparer.OrdinalIgnoreCase); - /// - /// Ad, var olan dokuman adi ya da bir wizard'a (dosya adi, ekran ya da menu kodu) isaret - /// edebilir; ikincisinde wizard'in dokumani doner. + /// Ekranin kokten kendisine menu yolu. Menu tablosu zinciri tamamlar: wizard'da yalnizca dogrudan + /// ust menu yazili olsa da kok bulunur. Tabloda olmayan seviyeler wizard'daki zincirden gelir. /// - public string? FindName(string? input) + private List MenuPath(ListFormWizardDto wizard) + { + var chain = wizard.ResolveMenuParentChain().Select(l => l.Code).ToList(); + var path = new List(); + + var current = chain.Count > 0 ? chain[^1] : null; + var guard = new HashSet(StringComparer.OrdinalIgnoreCase); + while (current != null && menus.TryGetValue(current, out var menu) && guard.Add(current)) + { + path.Insert(0, current); + current = string.IsNullOrWhiteSpace(menu.Parent) ? null : menu.Parent; + } + + if (path.Count == 0 || chain.Count > path.Count) + path = chain; + + path.Add(wizard.ResolveMenuCode()); + return path; + } + + private string RootOfDoc(string doc, ListFormWizardDto wizard) + { + var root = menus.Where(m => string.IsNullOrWhiteSpace(m.Value.Parent)).Select(m => m.Key) + .FirstOrDefault(code => string.Equals(DocNameOfRoot(code), doc, StringComparison.OrdinalIgnoreCase)); + return root ?? MenuPath(wizard)[0]; + } + + /// Dokuman adina, sonra bolum anahtarina gore gruplanmis wizard'lar. + public Dictionary GroupByDoc() + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var wizard in Wizards) + { + var (doc, section, root) = ResolveTarget(wizard.Seed.Wizard); + if (!result.TryGetValue(doc, out var group)) + result[doc] = group = new DocGroup(root); + + if (!group.Sections.TryGetValue(section, out var list)) + group.Sections[section] = list = []; + + list.Add(wizard); + } + + return result; + } + + public sealed class DocGroup(string rootCode) + { + public string RootCode { get; } = rootCode; + + public Dictionary> Sections { get; } = new(StringComparer.OrdinalIgnoreCase); + + public IEnumerable<(string FileName, WizardSeedFileDto Seed)> All => Sections.Values.SelectMany(v => v); + } + + /// + /// Girdinin isaret ettigi dokuman ve (varsa) bolum. Girdi dokuman adi, bolum anahtari ya da bir + /// wizard (dosya adi, ekran ya da menu kodu) olabilir; son ikisinde bolum de doner. + /// + public (string Doc, string? Section)? Find(string? input) { if (string.IsNullOrWhiteSpace(input)) return null; @@ -155,7 +279,7 @@ public sealed class ModuleDocCatalog var existing = ExistingDocNames().FirstOrDefault(n => string.Equals(n, value, StringComparison.OrdinalIgnoreCase)); if (existing != null) - return existing; + return (existing, null); var wizard = Wizards.FirstOrDefault(w => string.Equals(w.FileName, value, StringComparison.OrdinalIgnoreCase) || @@ -164,9 +288,44 @@ public sealed class ModuleDocCatalog string.Equals(w.Seed.Wizard.ResolveListFormCode(), value, StringComparison.OrdinalIgnoreCase) || string.Equals(w.Seed.Wizard.ResolveMenuCode(), value, StringComparison.OrdinalIgnoreCase)); if (wizard.Seed != null) - return Resolve(wizard.Seed.Wizard); + { + var target = ResolveTarget(wizard.Seed.Wizard); + return (target.Doc, target.Section); + } - return IsValidName(value) ? value : null; + // Bolum anahtari (wizard'i olmayan elle yazilmis bolum de dahil) ya da bir dal kodu. + if (claims.TryGetValue(value, out var claimed)) + return (claimed.Doc, claimed.Section); + + var branch = Wizards + .Select(w => ResolveTarget(w.Seed.Wizard)) + .FirstOrDefault(t => string.Equals(t.Section, value, StringComparison.OrdinalIgnoreCase)); + if (branch.Doc != null) + return (branch.Doc, branch.Section); + + // Wizard'i olmayan menu kodu: kok ise dosyanin tamami, degilse kokun altindaki dalin bolumu + // (entity tabanli dalin bolumu elle boyle acilir). + var path = new List(); + for (var code = value; code != null && menus.TryGetValue(code, out var menu) && !path.Contains(code); code = menu.Parent) + path.Insert(0, code); + + // Menude henuz olmayan kod (analizi yapilan yeni modul): kok ve dal menu kodu biciminden + // cikarilir (App.Inventory.Stock → App.Inventory › App.Inventory.Stock); deploy menuyu yazinca + // ayni dosya ve bolum bulunur. + if (path.Count == 0) + { + var segments = value.Split('.'); + if (!IsValidName(value) || segments.Length < 2) + return null; + + path = [string.Join('.', segments[..2])]; + if (segments.Length > 2) + path.Add(string.Join('.', segments[..3])); + } + + return path.Count == 1 + ? (DocNameOfRoot(path[0]), null) + : (DocNameOfRoot(path[0]), path[1]); } /// Otomatik envanter bolumu cikarilmis icerik. @@ -182,27 +341,65 @@ public sealed class ModuleDocCatalog return content[..begin].TrimEnd() + tail; } - /// Doldurulmamis bolumlerin basliklari ( tasiyan bolumler). - public static List MissingSections(string content) + /// Dokumanin bolumleri (envanter haric), dosyadaki sirayla. + public static List ParseSections(string content) { - var missing = new List(); - string? heading = null; + var manual = StripAuto(content.Replace("\r\n", "\n")); + var matches = SectionPattern.Matches(manual); + var sections = new List(); - foreach (var line in StripAuto(content).Split('\n')) + for (var i = 0; i < matches.Count; i++) { - if (line.StartsWith("## ", StringComparison.Ordinal)) - heading = line[3..].Trim(); - else if (line.Contains(TodoMarker, StringComparison.Ordinal) && heading != null && !missing.Contains(heading)) - missing.Add(heading); + var start = matches[i].Index; + var end = i + 1 < matches.Count ? matches[i + 1].Index : manual.Length; + var text = manual[start..end].TrimEnd() + "\n"; + var codes = matches[i].Groups["codes"].Success + ? matches[i].Groups["codes"].Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + : []; + var heading = text.Split('\n').FirstOrDefault(l => l.StartsWith("## ", StringComparison.Ordinal)); + + sections.Add(new DocSection(matches[i].Groups["key"].Value, [.. codes], heading?[3..].Trim() ?? matches[i].Groups["key"].Value, start, end, text)); } - return missing; + return sections; } - /// Hicbir bolumu doldurulmamis (otomatik acildigi gibi duran) dokuman. - public static bool IsUntouchedSkeleton(string content) + /// Dokumandaki bir bolum: anahtar, sahiplendigi ekran kodlari, basligi ve metni. + public sealed record DocSection(string Key, IReadOnlyList Claims, string Title, int Start, int End, string Text) { - var sections = StripAuto(content).Split('\n').Count(l => l.StartsWith("## ", StringComparison.Ordinal)); - return sections > 0 && MissingSections(content).Count == sections; + /// Doldurulmamis alt bolumler ( tasiyan ### basliklari). + public List Missing() + { + var missing = new List(); + string? heading = null; + + foreach (var line in Text.Split('\n')) + { + if (line.StartsWith("### ", StringComparison.Ordinal)) + heading = line[4..].Trim(); + else if (line.Contains(TodoMarker, StringComparison.Ordinal)) + { + var item = $"{Title} › {heading ?? Title}"; + if (!missing.Contains(item)) + missing.Add(item); + } + } + + return missing; + } + + /// Hicbir alt bolumu doldurulmamis (otomatik acildigi gibi duran) bolum. + public bool IsUntouchedSkeleton + { + get + { + var subSections = Text.Split('\n').Count(l => l.StartsWith("### ", StringComparison.Ordinal)); + return subSections > 0 && Missing().Count == subSections; + } + } } + + /// Doldurulmamis bolumlerin basliklari (Bolum › Alt bolum). + public static List MissingSections(string content) => + [.. ParseSections(content).SelectMany(s => s.Missing())]; } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocManager.cs b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocManager.cs index 9a9b5207..cfff928e 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocManager.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocManager.cs @@ -13,9 +13,10 @@ using Volo.Abp.DependencyInjection; namespace Sozsoft.Platform.ListForms; /// -/// Modul dokumanlarinin dosya islemleri. Wizard deploy'u, silme, tasarimci senkronizasyonu ve -/// import kapanisi cagirir: wizard'i olan her dokumanin envanteri -/// yeniden yazilir, dokumani olmayan modul icin iskelet acilir. Elle yazilan bolumlere dokunulmaz. +/// Modul dokumanlarinin dosya islemleri. Dokuman kok menu basina tektir ({Menu}.md), kokun +/// altindaki her dal dokumanda bir bolumdur. Wizard deploy'u, silme, tasarimci senkronizasyonu ve +/// import kapanisi cagirir: yeni kok menu icin dokuman, yeni dal icin +/// bolum iskeleti acilir, envanter yeniden yazilir. Elle yazilan bolumlere dokunulmaz. /// public class ModuleDocManager( IConfiguration configuration, @@ -23,6 +24,9 @@ public class ModuleDocManager( { private static readonly UTF8Encoding Utf8NoBom = new(encoderShouldEmitUTF8Identifier: false); + /// Analizin yazdigi alt bolumun isareti; isaret tasiyan govde sonraki analizde yenilenir. + private const string AnalysisMarker = "\n_Talep: {title}_\n\n{html.Trim()}\n"; + var updated = ReplaceSubSection(section.Text, ModuleDocRenderer.Sections[1], body); + if (updated != null) + manual = manual[..section.Start] + updated + (section.End < manual.Length ? "\n" + manual[section.End..].TrimStart('\n') : string.Empty); + + Directory.CreateDirectory(catalog.DocsPath); + await File.WriteAllTextAsync(path, manual.TrimEnd() + "\n", Utf8NoBom); + + catalog = await LoadCatalogAsync(); + var groups = catalog.GroupByDoc(); + await RefreshAsync(catalog, name, groups.GetValueOrDefault(name)); + + return await ToDtoAsync(catalog, name, sectionKey, groups, includeContent: false); + } + + /// + /// Bolumdeki ### {heading} alt bolumunun govdesini degistirir. Govde doldurulmamissa ya da + /// bir analizle yazilmissa yenilenir, elle yazilmissa null doner (dokunulmaz). + /// + private static string? ReplaceSubSection(string sectionText, string heading, string body) + { + var lines = sectionText.TrimEnd('\n').Split('\n').ToList(); + var start = lines.FindIndex(l => l.StartsWith("### ", StringComparison.Ordinal) && l[4..].Trim() == heading); + if (start < 0) + return sectionText.TrimEnd() + $"\n\n### {heading}\n\n{body}"; + + var end = lines.FindIndex(start + 1, l => l.StartsWith("### ", StringComparison.Ordinal)); + if (end < 0) + end = lines.Count; + + var current = string.Join('\n', lines.Skip(start + 1).Take(end - start - 1)); + if (!current.Contains(ModuleDocCatalog.TodoMarker, StringComparison.Ordinal) && !current.Contains(AnalysisMarker, StringComparison.Ordinal)) + return null; + + lines.RemoveRange(start + 1, end - start - 1); + lines.Insert(start + 1, string.Empty); + lines.Insert(start + 2, body.TrimEnd('\n')); + if (start + 3 < lines.Count) + lines.Insert(start + 3, string.Empty); + + return string.Join('\n', lines) + "\n"; + } + + private static string RootTitle(ModuleDocCatalog catalog, ModuleDocCatalog.DocGroup group) => + ModuleDocRenderer.Title(catalog, group.All.Select(w => w.Seed), group.RootCode); + public async Task> GetListAsync() { var catalog = await LoadCatalogAsync(); @@ -99,28 +215,50 @@ public class ModuleDocManager( var result = new List(); foreach (var name in groups.Keys.Union(catalog.ExistingDocNames(), StringComparer.OrdinalIgnoreCase).OrderBy(n => n, StringComparer.OrdinalIgnoreCase)) - result.Add(await ToDtoAsync(catalog, name, groups, includeContent: false)); + result.Add(await ToDtoAsync(catalog, name, null, groups, includeContent: false)); return result; } + /// + /// Dokuman adi verilirse dosyanin tamami, ekran/dal kodu verilirse yalnizca o dalin bolumu + /// (ve bolumun envanteri) doner. + /// public async Task GetAsync(string input) { var catalog = await LoadCatalogAsync(); - var name = catalog.FindName(input) ?? throw new UserFriendlyException($"Modül dokümanı bulunamadı: {input}"); + var (name, section) = catalog.Find(input) ?? throw new UserFriendlyException($"Modül dokümanı bulunamadı: {input}"); - return await ToDtoAsync(catalog, name, catalog.GroupByDoc(), includeContent: true); + return await ToDtoAsync(catalog, name, section, catalog.GroupByDoc(), includeContent: true); } + /// + /// Dokuman adi verilirse dosyanin tamami, ekran/dal kodu verilirse yalnizca o dalin bolumu + /// yazilir; envanter girdiden atilir ve yeniden uretilir. + /// public async Task SaveAsync(string input, string content) { var catalog = await LoadCatalogAsync(); - var name = catalog.FindName(input) ?? throw new UserFriendlyException($"Geçersiz modül dokümanı adı: {input}"); + var (name, section) = catalog.Find(input) ?? throw new UserFriendlyException($"Geçersiz modül dokümanı adı: {input}"); if (string.IsNullOrWhiteSpace(content)) throw new UserFriendlyException("Doküman içeriği boş olamaz."); var path = catalog.DocPath(name); - var manual = ModuleDocCatalog.StripAuto(Normalize(content)).TrimEnd() + "\n"; + + // Bolum yazilacaksa dosya ve bolum iskeleti once acilir; bolum ona gore yerine konur. + if (section != null && !File.Exists(path)) + await RefreshAsync(catalog, name, catalog.GroupByDoc().GetValueOrDefault(name)); + + // Henuz deploy edilmemis modulun (analiz) dosyasi da burada acilir: kok basligi + bolum. + var text = ModuleDocCatalog.StripAuto(Normalize(content)).TrimEnd() + "\n"; + var manual = section == null + ? text + : ReplaceSection( + File.Exists(path) + ? ModuleDocCatalog.StripAuto(Normalize(await File.ReadAllTextAsync(path))) + : ModuleDocRenderer.DocSkeleton(catalog.MenuTitle(name) ?? name, name), + section, + text); Directory.CreateDirectory(catalog.DocsPath); await File.WriteAllTextAsync(path, manual, Utf8NoBom); @@ -128,9 +266,31 @@ public class ModuleDocManager( // Envanter dosyaya yeniden eklenir; sahiplik beyani degismis olabilecegi icin katalog tazelenir. catalog = await LoadCatalogAsync(); var groups = catalog.GroupByDoc(); - await RefreshAsync(catalog, name, groups.GetValueOrDefault(name) ?? []); + await RefreshAsync(catalog, name, groups.GetValueOrDefault(name)); - return await ToDtoAsync(catalog, name, groups, includeContent: true); + return await ToDtoAsync(catalog, name, section, groups, includeContent: true); + } + + /// + /// Bolumu yeni metniyle degistirir. Metin beyan satiriyla baslamiyorsa bolumun mevcut beyani + /// (sahiplendigi kodlar dahil) korunur. + /// + private static string ReplaceSection(string manual, string sectionKey, string text) + { + var current = ModuleDocCatalog.ParseSections(manual) + .FirstOrDefault(s => string.Equals(s.Key, sectionKey, StringComparison.OrdinalIgnoreCase)); + + if (!text.TrimStart().StartsWith(""; + text = marker + "\n" + text.TrimStart(); + } + + if (current == null) + return manual.TrimEnd() + "\n\n" + text; + + var tail = manual[current.End..]; + return manual[..current.Start] + text + (tail.Length > 0 ? "\n" + tail.TrimStart('\n') : string.Empty); } public async Task> GetIncompleteForDevRequestAsync(Guid devRequestId) @@ -138,18 +298,19 @@ public class ModuleDocManager( var catalog = await LoadCatalogAsync(); var groups = catalog.GroupByDoc(); - var names = catalog.Wizards + var targets = catalog.Wizards .Where(w => w.Seed.DevRequest?.Id == devRequestId) - .Select(w => catalog.Resolve(w.Seed.Wizard)) - .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(w => catalog.ResolveTarget(w.Seed.Wizard)) + .Select(t => (t.Doc, t.Section)) + .Distinct() .ToList(); var result = new List(); - foreach (var name in names) + foreach (var (doc, section) in targets) { - var doc = await ToDtoAsync(catalog, name, groups, includeContent: false); - if (!doc.Exists || !doc.IsComplete) - result.Add(doc); + var dto = await ToDtoAsync(catalog, doc, section, groups, includeContent: false); + if (!dto.Exists || !dto.IsComplete) + result.Add(dto); } return result; @@ -158,23 +319,49 @@ public class ModuleDocManager( private static async Task ToDtoAsync( ModuleDocCatalog catalog, string name, - Dictionary> groups, + string? sectionKey, + Dictionary groups, bool includeContent) { var path = catalog.DocPath(name); - var exists = File.Exists(path); - var content = exists ? Normalize(await File.ReadAllTextAsync(path)) : null; - var missing = content == null ? [.. ModuleDocRenderer.Sections] : ModuleDocCatalog.MissingSections(content); + var content = File.Exists(path) ? Normalize(await File.ReadAllTextAsync(path)) : null; + var group = groups.GetValueOrDefault(name); + + var sections = content == null ? [] : ModuleDocCatalog.ParseSections(content); + var section = sectionKey == null ? null : sections.FirstOrDefault(s => string.Equals(s.Key, sectionKey, StringComparison.OrdinalIgnoreCase)); + var exists = content != null && (sectionKey == null || section != null); + + List missing = !exists + ? [.. ModuleDocRenderer.Sections] + : section != null ? section.Missing() : ModuleDocCatalog.MissingSections(content!); + + var wizards = sectionKey == null + ? group?.All ?? [] + : group?.Sections.GetValueOrDefault(sectionKey) ?? []; + + // Henuz yazilmamis dosya ya da bolum hata degildir (analizi yapilan yeni modul); doldurulacak + // iskelet doner, save_module_doc ayni adla yazinca dosya acilir. + string? text = null; + if (includeContent) + { + if (section != null) + text = section.Text.TrimEnd() + "\n\n" + ModuleDocRenderer.Inventory([(section.Title, (IReadOnlyList<(string FileName, WizardSeedFileDto Seed)>)[.. wizards])]); + else if (sectionKey != null) + text = ModuleDocRenderer.SectionSkeleton(ModuleDocRenderer.Title(catalog, wizards.Select(w => w.Seed), sectionKey), sectionKey); + else + text = content ?? ModuleDocRenderer.DocSkeleton(catalog.MenuTitle(name) ?? name, name); + } return new ModuleDocDto { Name = name, + Section = section?.Key ?? sectionKey, Path = ModuleDocCatalog.RelativePath(name), Exists = exists, IsComplete = exists && missing.Count == 0, MissingSections = missing, - Wizards = [.. (groups.GetValueOrDefault(name) ?? []).Select(w => w.Seed.Wizard.ResolveListFormCode())], - Content = includeContent ? content : null, + Wizards = [.. wizards.Select(w => w.Seed.Wizard.ResolveListFormCode())], + Content = text, }; } diff --git a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocRenderer.cs b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocRenderer.cs index 6cbfc0b8..cc8b4dac 100644 --- a/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocRenderer.cs +++ b/api/src/Sozsoft.Platform.Application/ListForms/ModuleDocs/ModuleDocRenderer.cs @@ -34,50 +34,75 @@ public static class ModuleDocRenderer private static readonly Regex ProcedurePattern = new(@"\bEXEC(?:UTE)?\s+(?:\[?dbo\]?\.)?\[?(?\w+)\]?", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex FromPattern = new(@"\bFROM\s+""?\[?(?\w+)\]?""?", RegexOptions.IgnoreCase | RegexOptions.Compiled); - public static string Skeleton(string title, string branchCode) + /// Kok menu dokumaninin iskeleti; dallar ile eklenir. + public static string DocSkeleton(string title, string rootCode) { var sb = new StringBuilder(); - sb.Append("# ").Append(title).Append(" (`").Append(branchCode).Append("`)\n\n"); - sb.Append("> Bu dosya ilk deploy'da otomatik açıldı. `module-doc:todo` işaretli bölümleri modülü üreten kişi ya da AI doldurur ") + sb.Append("# ").Append(title).Append(" (`").Append(rootCode).Append("`)\n\n"); + sb.Append("> Menünün altındaki her dal bu dosyada bir bölümdür (`module-doc:section`); dosya ve bölümler ilk deploy'da ") + .Append("otomatik açılır. `module-doc:todo` işaretli alt bölümleri modülü üreten kişi ya da AI doldurur ") .Append("(`lowcode.instructions.md` §0.13); MCP ile üretimde talep bu bölümler doldurulmadan Testing'e alınamaz. ") .Append("\"Ek — Ekran envanteri\" bölümü wizard dosyalarından üretilir, elle düzenlenmez.\n"); - foreach (var section in Sections) - sb.Append("\n## ").Append(section).Append("\n\n_Henüz yazılmadı._ ").Append(ModuleDocCatalog.TodoMarker).Append('\n'); - return sb.ToString(); } - /// Iskeletin basligi: dalin iki dilli adi wizard cevaplarinda varsa Turkcesi, yoksa kod. - public static string Title(IEnumerable seeds, string branchCode) + /// Bir dalin bolum iskeleti: beyan satiri, ## basligi ve doldurulacak alt bolumler. + public static string SectionSkeleton(string title, string sectionKey) { + var sb = new StringBuilder(); + sb.Append("\n"); + sb.Append("## ").Append(title).Append(" (`").Append(sectionKey).Append("`)\n"); + + foreach (var section in Sections) + sb.Append("\n### ").Append(section).Append("\n\n_Henüz yazılmadı._ ").Append(ModuleDocCatalog.TodoMarker).Append('\n'); + + return sb.ToString(); + } + + /// Menu kodunun basligi: menu dil satirindaki Turkce ad, yoksa wizard cevaplarindaki, yoksa kod. + public static string Title(ModuleDocCatalog catalog, IEnumerable seeds, string code) + { + var fromMenu = catalog.MenuTitle(code); + if (!string.IsNullOrWhiteSpace(fromMenu)) + return fromMenu; + foreach (var wizard in seeds.Select(s => s.Wizard)) { - if (string.Equals(wizard.ResolveMenuCode(), branchCode, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(wizard.MenuTr)) + if (string.Equals(wizard.ResolveMenuCode(), code, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(wizard.MenuTr)) return wizard.MenuTr; - var level = wizard.ResolveMenuParentChain().FirstOrDefault(l => string.Equals(l.Code, branchCode, StringComparison.OrdinalIgnoreCase)); + var level = wizard.ResolveMenuParentChain().FirstOrDefault(l => string.Equals(l.Code, code, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(level?.Tr)) return level.Tr; } - return branchCode; + return code; } - public static string Inventory(IReadOnlyList<(string FileName, WizardSeedFileDto Seed)> wizards) + /// Dokumanin envanteri: bolumler dokumandaki sirayla, her bolumun ekranlari menu sirasiyla. + public static string Inventory(IEnumerable<(string Title, IReadOnlyList<(string FileName, WizardSeedFileDto Seed)> Wizards)> sections) { var sb = new StringBuilder(); sb.Append(ModuleDocCatalog.AutoBegin).Append('\n'); sb.Append("## Ek — Ekran envanteri (otomatik)\n\n"); sb.Append("> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur.\n"); - var ordered = wizards - .OrderBy(w => w.Seed.Wizard.CreateMenu ? 0 : 1) - .ThenBy(w => w.Seed.Wizard.MenuOrder) - .ThenBy(w => w.Seed.Wizard.SeededAt); + foreach (var (title, wizards) in sections) + { + if (wizards.Count == 0) + continue; - foreach (var (fileName, seed) in ordered) - AppendWizard(sb, fileName, seed); + sb.Append("\n### ").Append(Cell(title)).Append('\n'); + + var ordered = wizards + .OrderBy(w => w.Seed.Wizard.CreateMenu ? 0 : 1) + .ThenBy(w => w.Seed.Wizard.MenuOrder) + .ThenBy(w => w.Seed.Wizard.SeededAt); + + foreach (var (fileName, seed) in ordered) + AppendWizard(sb, fileName, seed); + } sb.Append('\n').Append(ModuleDocCatalog.AutoEnd).Append('\n'); return sb.ToString(); @@ -90,7 +115,7 @@ public static class ModuleDocRenderer var code = wizard.ResolveListFormCode(); var title = FirstText(wizard.MenuTr, wizard.TitleTr, wizard.MenuEn, code); - sb.Append("\n### ").Append(Cell(title)).Append(" — `").Append(code).Append("`\n\n"); + sb.Append("\n#### ").Append(Cell(title)).Append(" — `").Append(code).Append("`\n\n"); sb.Append("| Özellik | Değer |\n| --- | --- |\n"); Row(sb, "Wizard", $"`{SeedPathResolver.WizardFolder}/{fileName}`"); diff --git a/api/src/Sozsoft.Platform.DbMigrator/appsettings.json b/api/src/Sozsoft.Platform.DbMigrator/appsettings.json index ff3ac536..d5de9333 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/appsettings.json +++ b/api/src/Sozsoft.Platform.DbMigrator/appsettings.json @@ -36,6 +36,11 @@ "https://claude.com/api/mcp/auth_callback", "https://chatgpt.com/connector_platform_oauth_redirect" ] + }, + "Platform_Mcp_Local": { + "RedirectUris": [ + "http://127.0.0.1:19876/oauth/callback" + ] } } } diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/Identity/SkiaMcpImageShrinker.cs b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/SkiaMcpImageShrinker.cs new file mode 100644 index 00000000..fc4a4833 --- /dev/null +++ b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/SkiaMcpImageShrinker.cs @@ -0,0 +1,63 @@ +using System; +using SkiaSharp; +using Sozsoft.Mcp.Tools; +using Volo.Abp.DependencyInjection; + +namespace Sozsoft.Platform.Identity; + +/// +/// MCP arac sonucundaki gorselleri SkiaSharp ile kucultur (rapor motorunun grafik katmani zaten +/// SkiaSharp'tir). Gorsel once modelin isleyebildigi en uzun kenara indirilir, sigmazsa adim adim +/// kucultulur; okunamayacak kadar kuculecekse gonderilmez. +/// +public class SkiaMcpImageShrinker : IMcpImageShrinker, ISingletonDependency +{ + /// Modelin gorseli isledigi en uzun kenar; daha buyugu yalnizca boyut tasir. + private const int MaxEdge = 1568; + + /// Bunun altinda ekran goruntusundeki metin okunmaz. + private const int MinEdge = 480; + + private const int JpegQuality = 80; + private const float ScaleStep = 0.75f; + + public McpShrunkImage? Shrink(string mimeType, string base64, int maxLength) + { + if (base64.Length <= maxLength) + return new McpShrunkImage(mimeType, base64); + + using var bitmap = SKBitmap.Decode(Convert.FromBase64String(base64)); + if (bitmap is null) + return null; + + using var source = SKImage.FromBitmap(bitmap); + var longest = Math.Max(bitmap.Width, bitmap.Height); + var scale = Math.Min(1f, MaxEdge / (float)longest); + + while (true) + { + var encoded = EncodeJpeg(source, scale); + if (encoded.Length <= maxLength) + return new McpShrunkImage("image/jpeg", encoded); + + scale *= ScaleStep; + if (longest * scale < MinEdge) + return null; + } + } + + private static string EncodeJpeg(SKImage source, float scale) + { + var width = Math.Max(1, (int)Math.Round(source.Width * scale)); + var height = Math.Max(1, (int)Math.Round(source.Height * scale)); + + // JPEG saydamlik tasimaz; saydam alanlar siyaha donmesin diye beyaz zemine cizilir. + using var surface = SKSurface.Create(new SKImageInfo(width, height, SKColorType.Rgba8888, SKAlphaType.Premul)); + surface.Canvas.Clear(SKColors.White); + surface.Canvas.DrawImage(source, new SKRect(0, 0, width, height), new SKSamplingOptions(SKCubicResampler.Mitchell)); + + using var snapshot = surface.Snapshot(); + using var data = snapshot.Encode(SKEncodedImageFormat.Jpeg, JpegQuality); + return Convert.ToBase64String(data.AsSpan()); + } +} diff --git a/claude.md b/claude.md index 11c0bbdc..f885cce4 100644 --- a/claude.md +++ b/claude.md @@ -111,7 +111,7 @@ These sections encode expectations the user will **not** repeat in every prompt. | `api/` kod standardı (sürüm, nullable, ölü kod, modern C#, ABP katmanları) | `.github/instructions/dotnet.instructions.md` | | Modül/liste ekleme prosedürü, seeder dosya sorumlulukları | `.github/instructions/list.instructions.md` | | Ne nerede yaşıyor, hangi ekran ne yapıyor | `README.md` | -| Bir modülün nasıl çalıştığı, analizi ve kararları | `configs/seeds/docs/modules/{Modül}.md` (dizin: `README.md` §10.5) | +| Bir modülün nasıl çalıştığı, analizi ve kararları | `configs/seeds/docs/modules/{Menü}.md` (dizin: `README.md` §10.5) | | Yetki kodları | `PlatformConsts.AppCodes` (backend) + `constants/permission.constant.ts` (UI) | | Seed yolları | `SeedPathResolver` | | SQL Server → PostgreSQL çeviri kuralları | `.github/instructions/lowcode.instructions.md` §8.3.1 | @@ -185,12 +185,15 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → Alt form ekranının menü/yetki/düzenleme kuralları (menüsüz alt formun yetkisi ana ekranın altında, `Form` sekmesi tek kayıt + `AllowAdding`/`AllowUpdating` açık): `lowcode.instructions.md` §4.6. 14. **Modül dokümanı** → MCP ya da wizard ile oluşturulan her modül çalışma şeklini - `configs/seeds/docs/modules/{Modül}.md` dosyasında taşır: keşif cevapları ve onaylanan - tarif (analiz), ekranlar, veri modeli, hesaplar/durum geçişleri, yetki dağılımı, entegrasyonlar, - sık sorulanlar. Dosyayı ve "Ek — Ekran envanteri"ni deploy kendisi açar/yeniler; anlatım - bölümlerini (`module-doc:todo`) üreten doldurur — MCP'de `save_module_doc`, Claude Code'da dosyaya - doğrudan. MCP talebi doküman tamamlanmadan `Testing`'e alınamaz. Wizard dışı modül dokümanı elle - yazılır. README'ye yalnızca §10.5 dizin satırı ve ilgili bölümde tek cümlelik bağlantı yazılır. + `configs/seeds/docs/modules/{Menü}.md` dosyasında taşır: dosya kök menü başına tektir ve adı kök + menünün kodudur (`App.Hr.md`, `App.Prc.md`, `App.Administration.md`), + menünün altındaki her dal dosyada bir `module-doc:section` bölümüdür. Bölüm keşif cevapları ve + onaylanan tarifi (analiz), ekranları, veri modelini, hesapları/durum geçişlerini, yetki dağılımını, + entegrasyonları, sık sorulanları taşır. Dosyayı, dalın bölümünü ve "Ek — Ekran envanteri"ni deploy + kendisi açar/yeniler; anlatım alt bölümlerini (`module-doc:todo`) üreten doldurur — MCP'de + `save_module_doc` (ekran/dal koduyla yalnızca o bölüm), Claude Code'da dosyaya doğrudan. MCP talebi + bölümü tamamlanmadan `Testing`'e alınamaz. Wizard dışı modülün bölümü elle yazılır. README'ye + yalnızca §10.5 dizin satırı/bölüm adı ve ilgili bölümde tek cümlelik bağlantı yazılır. "X nasıl çalışıyor?" sorusunda önce bu dosya okunur. Ayrıntı: `lowcode.instructions.md` §0.13. 15. **Ekran açıklaması** → wizard/MCP ile üretilen her liste ekranının (alt formlar dahil) `DescTr`/`DescEn` metni ayrıntılıdır; başlıktaki ⓘ simgesinde gösterilir: ne işe yaradığı, @@ -216,8 +219,9 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → - **Modül dokümanı** → `ModuleDocManager.RefreshAllAsync` wizard'ı yazan her yoldan çağrılır (deploy, silme, `WizardSeedSynchronizer`, import kapanışı); wizard dosyasını yazan yeni bir yol eklenirse - çağrı da eklenir, yoksa envanter bayatlar. Wizard → doküman eşlemesi tek yerdedir - (`ModuleDocCatalog`: beyan → alt formun ana ekranı → menü dalı); envanter biçimi + çağrı da eklenir, yoksa envanter bayatlar. Wizard → doküman/bölüm eşlemesi tek yerdedir + (`ModuleDocCatalog`: dosya = kök menü, bölüm = beyan → alt formun ana ekranı → menü dalı; kök ve + dal `data/App.Menus.Menu.json`'dan okunur, sabit liste yoktur); envanter biçimi `ModuleDocRenderer`'dadır. Export kapanışı dokümanı taşır (`WizardExportCollector`), import `docs/modules/*.md` yolunu kabul eder. @@ -317,7 +321,10 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → - **Talepteki görsel** → `App.DevRequests` açıklamasına yapıştırılan görsel base64 `data:` URI olarak kalır, hiçbir yere yüklenmez. `start_dev_request` / `get_dev_request` onu metinden ayıklar (`McpDevRequestImages`) ve MCP resim içeriği (`ImageContentBlock`) olarak döndürür; metinde - `[image-N]` kalır. Açıklama bu yüzden `update_row` ile yeniden yazılmaz. `SubTasks` de + `[image-N]` kalır. Sonucun tamamı istemcinin araç sonucu sınırına (Claude Desktop 1 MB) sığar: + kalan pay görsellere bölünür, payını aşan görsel `IMcpImageShrinker` (Host'ta SkiaSharp) ile küçültülüp + JPEG'e çevrilir, yine sığmayan gönderilmez ve metinde bildirilir; kaynak açıklama değişmez. + Açıklama bu yüzden `update_row` ile yeniden yazılmaz. `SubTasks` de `add_dev_request_subtasks` ile yazılır: atanan kişi bağlanan kullanıcı, bitiş tarihi bugün — sunucu doldurur, modele bırakılmaz. `Timesheets`'i tamamen sunucu yazar (`IMcpDevRequestTimesheetRecorder`): `get_dev_request`/`start_dev_request` talebi etkin talep yapar, @@ -331,7 +338,9 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → - **Talep analizi** → `Description` talebin yazıldığı hâliyle kalır; MCP ona yazmaz. Analiz ve üretim notları `Analysis` kolonundadır (Todo panosunda `AnalysisExpr`, Açıklama yanında sekme). Durum sırası `Backlog → Analysis → Ready to Start → …`: "Analiz et" `save_dev_request_analysis` - ile yalnızca `Backlog`/`Analysis` talebini analiz edip `Analysis`'e alır (hiçbir şey üretmez), + ile yalnızca `Backlog`/`Analysis` talebini analiz edip `Analysis`'e alır (ekran/tablo üretmez), + analizi `menuCode` dalının modül dokümanı bölümüne ("2. Analiz ve kararlar") de yazar — menüde ilk + talepse kök menünün dosyası (`App.Inventory.md`) ve dal bölümü burada açılır, elle yazılmış alt bölüme dokunulmaz; `Ready to Start`'a kullanıcı taşır, üretim notu `append_dev_request_note` ile `Analysis`'e eklenir. Analiz standardı tek yerdedir: `lowcode.instructions.md` §0.12; prompt'lar oraya yönlendirir. - **MCP şema araçları** → tablo/sütun bilgisi canlı katalogdan değil `Sas_H_DbTableColumn` @@ -341,6 +350,7 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → değil ekranların alanlarını döker: bir tablonun ekranda alan olarak tanımlanmamış kolonunu MCP göremez. Modelin okuması gereken kolon (ör. `AbpUsers`'ın kişisel bilgileri) ilgili ekranda gizli alan olarak durur. - **MCP OAuth** → bilinen sağlayıcılar (Claude, ChatGPT) seed edilmiş `Platform_Mcp` istemcisini, + yerel `mcp-remote` proxy'si açık onaylı `Platform_Mcp_Local` istemcisini, diğer MCP istemcileri `/connect/register` ile üretilen `mcp_` önekli açık onaylı istemcileri kullanır (`McpOAuthClientManager`; seed `McpOAuthClientDataSeedContributor`). Bilinen sağlayıcı eklemek = DbMigrator'daki `Platform_Mcp:RedirectUris` listesine callback eklemek. MCP @@ -542,7 +552,7 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` → tipler düz metin aramasında referanssız görünür. - Yorum satırına alınmış kod bloğu bırakılmaz. - Modül/ekran/bileşen ekleyen ya da davranışını değiştiren iş modül dokümanını - (`configs/seeds/docs/modules/{Modül}.md`) yazar veya günceller; liste ekranının açıklaması + (`configs/seeds/docs/modules/{Menü}.md`) yazar veya günceller; liste ekranının açıklaması ayrıntılıdır (standing default 14–15). - `api/` değişikliğinden sonra: `dotnet build -p:EnforceCodeStyleInBuild=true` — 0 hata, yeni `IDE00xx` yok. diff --git a/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json new file mode 100644 index 00000000..7e9770ce --- /dev/null +++ b/configs/seeds/data/App.DevRequests/53294e77-a4fb-45e4-a80e-acf07b5d75be.json @@ -0,0 +1,26 @@ +{ + "ListFormCode": "App.DevRequests", + "KeyFieldName": "Id", + "GeneratedAt": "2026-10-06T21:01:13.15342Z", + "Order": 0, + "Rows": [ + { + "Id": "53294e77-a4fb-45e4-a80e-acf07b5d75be", + "TenantId": null, + "UserName": "system@sozsoft.com", + "RequestDate": null, + "Status": "Backlog", + "Title": "Satınalma -> Malzeme Talepleri", + "Description": "

Depolar: Fiziki olarak konumlandırılan yerlerin listesidir. Bizim programımızda Firma sütunu yok yerine Şube adı olmalı. Depo Listesi, Depo Adı, Depo Kodu ve Şube Adı sütunlarından oluşması yeterlidir. Satınalma -> Tanımlamalar menüsüne eklenmelidir.



Operasyon Türleri : Şube ve Depo bazında tanımlanan Operasyon Türleri listesidir. Operasyon Türü : Alım, Teslimat, İç Transfer, Üretim ve Onarım dan oluşmaktadır. Satınalma -> Tanımlamalar menüsüne eklenmelidir.



Konumlar: Şube ve Depo bazında iç içe tanımlanan Konum listesidir. Burada Parent ve Child ilşkisi olması gerekiyor. Üst konum seçimi yapılabilir. Konum Türü olarak İç ve Dış olabilir.


Malzeme Talepleri : Satınalma yapılması için departmantların iç ve dış olmak üzere talep ettikleri ürünlerin kaydıdır. Talep eden, Talep Eden Departman, Mal Alımı olduğu zaman konulacak Depo ve Konum bilgisi ve Talep Tarihi bilgilerinden sonra Ürün ve talep edilen miktar bilgisi girilmeli. Ürün tanımında yer alan Birim bilgisi yine sistemle entegre şekilde gelmektedir. Termin Tarihi ürünün ne zaman ihtiyaç olduğu ve Talep Nedeni olarak ne amaçla istediği belirtilmelidir. Yine bu kaydın üst kısmında Taslak, Departman Onayı, Satınalma Onayı, Onaylandı, İşlemde, Tamamlandı gibi durumları da onay mekanizması Workflow gibi bir yöntemle yönetmeliyiz. Talepten sonra hemen talep edenin Departman Onaycısı onaylayacak bir liste üzerinden görmeli ve onaylamalı. Sonrasında kayıt SAtınalma departmanına düşmeli ondan sonra bu kayıt Satınalma Sorumlusu kabul etmeli ve Satınalma ile ilgili teklif toplama süreci başlamalı.


Departman Listesine App.Hr.Department Satınalma Onaycısı sütunu eklenmeli ve o departmanının onayı verecek olan kullanıcı o olmalı.



Taleplerim, Departman Onayı Bekleyenler, Satınalma Onayı Bekleyenler, Planlama Bekleyenler, Tüm Talepler listesinden oluşmalı.


Red Nedenleri : Bazı Satınalma talepleri hem departman onaycısı hemde satınalma tarafından reddedilebilir. Reddetme sebepleri aşağıadki gibidir. Bu liste Satınalma -> Tanımlamalar menüsüne yerleştirilmelidir.


", + "DueDate": "2026-10-06T21:01:00", + "Tags": "PO", + "Assignees": "system@sozsoft.com", + "Priority": null, + "Completed": false, + "SortOrder": 1, + "Timesheets": null, + "SubTasks": null, + "Analysis": null + } + ] +} diff --git a/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json b/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json new file mode 100644 index 00000000..09a8b5cb --- /dev/null +++ b/configs/seeds/data/App.DevRequests/5d11851e-5f00-4a0b-b5a3-b8211e56c8b5.json @@ -0,0 +1,26 @@ +{ + "ListFormCode": "App.DevRequests", + "KeyFieldName": "Id", + "GeneratedAt": "2026-10-06T21:01:53.4632621Z", + "Order": 0, + "Rows": [ + { + "Id": "5d11851e-5f00-4a0b-b5a3-b8211e56c8b5", + "TenantId": null, + "UserName": "system@sozsoft.com", + "RequestDate": null, + "Status": "Backlog", + "Title": "Inventory -> Tanımlamalar", + "Description": "

Ürünler : Ürün listesi ve detayı aşağıdaki örneklendirilmiştir. Ürünler Satış, Masraflar, Satınalma olarak 3 seçeneği var. Satış seçerse sadece Satış siparişlerinde görünür. Satınalma seçerse Satınalınabilir anlamına gelir. Ürün Türü Mal veya Hizmet olabilir. Envanter Takibi yapılıp yapılmayacağı seçilebilir. Eğer takip edilecekse Seri No, Lot Numarası veya Miktara göre seklinden seçilecek.


Nitelikler ve Varyantlar seçeneğinde yazılabilecek değerler Nitelik olarak tanımlanmalı. İçerisindeki değerleri de tanımlanabilir. Nitelik seçilip değerleri birden fazla şekilde yapılabilir. Eğer nitelikli bir ürün tanımlanırsa o varyantlı ürün listeler de seçilecektir.


Satınalma kısmında o ürünü hangi tedarikçiden hangi bedele aldığımızı belirtiyoruz.







Reçeteler : Ürünlerin hammadde ve yarı mamülerin ve tüketim miktarlarının belirlendiği kısımdır. Ayrıca tanımlanan operasyonların tanımlandığı listedir. Hangi bileşenlerin hangi operasyon ile tüketildiği belirlenecektir.

Operasyonlar : Inventory -> Tanımlamalar menüsünde yer alacaktır.

İş Merkezi tanımlamaları : Inventory -> Tanımlamalar menüsünde yer alacaktır.


Eğer nitelikli bir ürün tanımlanırsa o zaman Varyantlı liste oluşur ve tüm sistem varyantlı seçeneker çalışır. Eğer nitelik tanımlamazsa ana ürün seçilecektir.

Ürün reçetesine genel bakış raporu bu ERP ssitemlerdeki BOM ile aynı




", + "DueDate": "2026-10-06T21:02:00", + "Tags": "IN", + "Assignees": "system@sozsoft.com", + "Priority": null, + "Completed": false, + "SortOrder": 0, + "Timesheets": null, + "SubTasks": null, + "Analysis": null + } + ] +} diff --git a/configs/seeds/data/App.DevRequests/94639b65-1bb7-454a-ae73-3e1c5c9fe23a.json b/configs/seeds/data/App.DevRequests/94639b65-1bb7-454a-ae73-3e1c5c9fe23a.json index 60301af9..32219684 100644 --- a/configs/seeds/data/App.DevRequests/94639b65-1bb7-454a-ae73-3e1c5c9fe23a.json +++ b/configs/seeds/data/App.DevRequests/94639b65-1bb7-454a-ae73-3e1c5c9fe23a.json @@ -17,7 +17,7 @@ "Assignees": null, "Priority": null, "Completed": false, - "SortOrder": 0, + "SortOrder": 2, "Timesheets": null, "SubTasks": null, "Analysis": null diff --git a/configs/seeds/data/App.Languages.LanguageText.json b/configs/seeds/data/App.Languages.LanguageText.json index 6b4bd7f1..363e5aad 100644 --- a/configs/seeds/data/App.Languages.LanguageText.json +++ b/configs/seeds/data/App.Languages.LanguageText.json @@ -69430,6 +69430,20 @@ "Key": "App.Mcp.Error.DevRequestAnalysisRequired", "Value": "Analiz boş olamaz." }, + { + "Id": "c8039b7b-e33c-5a20-950b-772e6620e568", + "CultureName": "en", + "ResourceName": "Platform", + "Key": "App.Mcp.Error.DevRequestMenuCodeRequired", + "Value": "menuCode is required: pass the menu location of the request, i.e. the code of the branch or screen under the root menu (App.Inventory.Definitions). The analysis is written to that branch's section of the module document." + }, + { + "Id": "1c11fb6e-9011-5de0-b7c7-b3d9227c00c7", + "CultureName": "tr", + "ResourceName": "Platform", + "Key": "App.Mcp.Error.DevRequestMenuCodeRequired", + "Value": "menuCode zorunludur: talebin menü yerini, yani kök menünün altındaki dalın ya da ekranın kodunu (App.Inventory.Definitions) gönderin. Analiz bu dalın modül dokümanı bölümüne yazılır." + }, { "Id": "aa72e998-f4a1-5873-95ef-1fcfe0b601f9", "CultureName": "en", @@ -81727,14 +81741,14 @@ "CultureName": "en", "ResourceName": "Platform", "Key": "App.Hr.PerformanceReview.Desc", - "Value": "All Reviews — every employee review of every period; HR follows and manages the process end to end here.\nWhere: Human Resources › Performance Management › All Reviews (HR only). The detail has Goals, Competencies, 360 Feedback and Development Plan tabs; the Todo view groups reviews by stage.\nStages: Goal Setting → Self Review → Manager Review → Calibration → Completed.\nFields:\n• Period, employee (department/position copied), manager → HR selects the reviewing manager\n• Scores → goal, competency, 360 average (info), overall, calibrated score and rating; calculated automatically\n• Self, manager and calibration comments; submission and completion dates\nAutomatic: scores are recalculated on every save. HR may make any stage change; leaving Goal Setting requires at least one goal with weights totalling 100. Transitions notify the employee/manager; on Completed manager levels are written to the employee's skill profile.\nRelated: My Reviews (employee), Team Reviews (manager), Calibration, Development Plans. Details: docs/modules/HrPerformance.md." + "Value": "All Reviews — every employee review of every period; HR follows and manages the process end to end here.\nWhere: Human Resources › Performance Management › All Reviews (HR only). The detail has Goals, Competencies, 360 Feedback and Development Plan tabs; the Todo view groups reviews by stage.\nStages: Goal Setting → Self Review → Manager Review → Calibration → Completed.\nFields:\n• Period, employee (department/position copied), manager → HR selects the reviewing manager\n• Scores → goal, competency, 360 average (info), overall, calibrated score and rating; calculated automatically\n• Self, manager and calibration comments; submission and completion dates\nAutomatic: scores are recalculated on every save. HR may make any stage change; leaving Goal Setting requires at least one goal with weights totalling 100. Transitions notify the employee/manager; on Completed manager levels are written to the employee's skill profile.\nRelated: My Reviews (employee), Team Reviews (manager), Calibration, Development Plans. Details: docs/modules/App.Hr.md › Performans Yönetimi." }, { "Id": "af68340a-00bc-55f0-a436-e23b78326c9d", "CultureName": "tr", "ResourceName": "Platform", "Key": "App.Hr.PerformanceReview.Desc", - "Value": "Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir.\nNerede: İnsan Kaynakları › Performans Yönetimi › Tüm Değerlendirmeler (yalnız İK). Detayda Hedefler, Yetkinlikler, 360 Derece ve Gelişim Planı sekmeleri; Todo görünümünde değerlendirmeler aşama sütunlarındadır.\nAşamalar: Hedef Belirleme → Öz Değerlendirme → Yönetici Değerlendirmesi → Kalibrasyon → Tamamlandı.\nAlanlar:\n• Dönem, çalışan (departman/pozisyon çalışandan dolar), yönetici → değerlendiren yöneticiyi İK seçer\n• Puanlar → hedef puanı, yetkinlik puanı, 360 ortalaması (bilgi), genel puan, kalibre puan ve derece; hesaplar otomatiktir\n• Öz değerlendirme, yönetici ve kalibrasyon yorumları; gönderim ve tamamlanma tarihleri\nOtomatik: her kayıtta puanlar yeniden hesaplanır. İK her aşama geçişini yapabilir; Hedef Belirleme'den çıkmak için ağırlık toplamı 100 olan en az bir hedef gerekir. Geçişlerde çalışana/yöneticiye bildirim gider; Tamamlandı'da yönetici seviyeleri çalışanın yetkinlik profiline yazılır.\nİlişkili: Değerlendirmelerim (çalışan), Ekibimin Değerlendirmeleri (yönetici), Kalibrasyon, Gelişim Planları. Ayrıntı: docs/modules/HrPerformance.md." + "Value": "Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir.\nNerede: İnsan Kaynakları › Performans Yönetimi › Tüm Değerlendirmeler (yalnız İK). Detayda Hedefler, Yetkinlikler, 360 Derece ve Gelişim Planı sekmeleri; Todo görünümünde değerlendirmeler aşama sütunlarındadır.\nAşamalar: Hedef Belirleme → Öz Değerlendirme → Yönetici Değerlendirmesi → Kalibrasyon → Tamamlandı.\nAlanlar:\n• Dönem, çalışan (departman/pozisyon çalışandan dolar), yönetici → değerlendiren yöneticiyi İK seçer\n• Puanlar → hedef puanı, yetkinlik puanı, 360 ortalaması (bilgi), genel puan, kalibre puan ve derece; hesaplar otomatiktir\n• Öz değerlendirme, yönetici ve kalibrasyon yorumları; gönderim ve tamamlanma tarihleri\nOtomatik: her kayıtta puanlar yeniden hesaplanır. İK her aşama geçişini yapabilir; Hedef Belirleme'den çıkmak için ağırlık toplamı 100 olan en az bir hedef gerekir. Geçişlerde çalışana/yöneticiye bildirim gider; Tamamlandı'da yönetici seviyeleri çalışanın yetkinlik profiline yazılır.\nİlişkili: Değerlendirmelerim (çalışan), Ekibimin Değerlendirmeleri (yönetici), Kalibrasyon, Gelişim Planları. Ayrıntı: docs/modules/App.Hr.md › Performans Yönetimi." }, { "Id": "710a78b8-9f30-5049-81ff-44892e5eeb03", diff --git a/configs/seeds/docs/modules/AdministrationDefinitions.md b/configs/seeds/docs/modules/App.Administration.md similarity index 92% rename from configs/seeds/docs/modules/AdministrationDefinitions.md rename to configs/seeds/docs/modules/App.Administration.md index ac21fc09..3499fa45 100644 --- a/configs/seeds/docs/modules/AdministrationDefinitions.md +++ b/configs/seeds/docs/modules/App.Administration.md @@ -1,12 +1,17 @@ -# Yönetim › Tanımlamalar (`App.Administration.Definitions`) +# Yönetim (`App.Administration`) -> "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. Sektörler, Diziler ve Ölçü Kategorileri wizard ekranı değildir (`ListFormSeeder_Administration`); burada yalnızca menü sırası için anılır. +> Menünün altındaki her dal bu dosyada bir bölümdür (`module-doc:section`); dosya ve bölümler ilk deploy'da otomatik açılır. `module-doc:todo` işaretli alt bölümleri modülü üreten kişi ya da AI doldurur (`lowcode.instructions.md` §0.13); MCP ile üretimde talep bu bölümler doldurulmadan Testing'e alınamaz. "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. -## 1. Amaç ve kapsam + +## Tanımlamalar (`App.Administration.Definitions`) + +> Sektörler, Diziler ve Ölçü Kategorileri wizard ekranı değildir (`ListFormSeeder_Administration`); burada yalnızca menü sırası için anılır. + +### 1. Amaç ve kapsam Satış ve satınalmanın ortak kullandığı **Kontaklar** kartı (müşteri ve tedarikçi; şirket ya da bireysel) ve onu sınıflandıran **Kontak Etiketleri**. İleride yapılacak Satış ve Satınalma belgeleri (teklif, sipariş, fatura) kontağı bu ekrandan seçer. Kart başlangıçta Satınalma › Tanımlamalar altında `App.Prc.Supplier` olarak üretildi; satış tarafı da kullanacağı için Yönetim modülüne taşındı. -## 2. Analiz ve kararlar +### 2. Analiz ve kararlar - Modül `Adm`, tablo öneki `Adm_T_`, kod öneki `App.Definitions.` (Sektörler ile aynı aile). Eski adlardan karşılık: `Prc_T_Supplier` → `Adm_T_Contact`, `Prc_T_SupplierContact` → `Adm_T_ContactPerson`, `Prc_T_SupplierBankAccount` → `Adm_T_ContactBankAccount`, `Prc_T_SupplierTag` → `Adm_T_ContactTag`; alt tablolardaki bağ kolonu `SupplierId` → `ContactId`. - Ana liste "Kontaklar" olduğu için kartın kişi sekmesi **İlgili Kişiler** (`App.Definitions.ContactPerson`) adını aldı; iki ekranın adı çakışmaz. @@ -22,7 +27,7 @@ Satış ve satınalmanın ortak kullandığı **Kontaklar** kartı (müşteri ve - Sektör (`SectorId`) Sektörler ekranının (`App.Definitions.Sector`, `Adm_T_Sector`) kiracıya ait aktif kayıtlarından seçilir. `JobPosition` kolonu tabloda kalır, ekranda yoktur. - Kontak telefonu (`Phone`) `phoneCountry` biçimindedir: maske seçilen ülkenin kodu ve numara kalıbıyla değişir, `pattern` `^[0-9]{4,15}$`. Ülke alanı olmayan İlgili Kişiler telefonu `phoneGlobal` maskesi ve `^[0-9]{10}$` kuralı taşır; web sitesi `pattern`, e-posta `email` doğrulaması taşır. -## 3. Menü ve ekranlar +### 3. Menü ve ekranlar Yönetim (`App.Administration`) › Tanımlamalar (`App.Administration.Definitions`): @@ -34,7 +39,7 @@ Yönetim (`App.Administration`) › Tanımlamalar (`App.Administration.Definitio | 4 | Diziler | `App.Definitions.Sequence` | kod seed'i | | 5 | Ölçü Kategorileri | `App.Definitions.UomCategory` | kod seed'i | -## 4. Veri modeli +### 4. Veri modeli Tüm tablolar kiracı (`TenantId`) + tam audit + soft delete taşır. @@ -43,7 +48,7 @@ Tüm tablolar kiracı (`TenantId`) + tam audit + soft delete taşır. - `Adm_T_ContactPerson` (ContactId → `Adm_T_Contact.Id`, Photo, Name, JobTitle, Email, Phone, Mobile, Notes) - `Adm_T_ContactBankAccount` (ContactId → `Adm_T_Contact.Id`, BankName, Iban, AccountHolder, Currency, IsDefault) -## 5. İş kuralları ve hesaplar +### 5. İş kuralları ve hesaplar - Tanım lookup'ları yalnızca `IsActive = 1` ve silinmemiş kayıtları listeler. - Ülke › İl › İlçe › Mahalle cascade: üst alan değişince alttakiler temizlenir; mahalle seçilince posta kodu `copy` tarifiyle dolar. @@ -51,15 +56,15 @@ Tüm tablolar kiracı (`TenantId`) + tam audit + soft delete taşır. - IBAN doğrulaması: `^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$` (boşluksuz, büyük harf). - Yeni kayıtta Tür = Şirket, Grup Teklif Talebi = Sipariş Üzerine, Fatura onayı = 3 doğrulamadan sonra sor varsayılanları tablodan gelir. -## 6. Yetki ve görünürlük +### 6. Yetki ve görünürlük Yetki ağacı: `App.Administration` grubu › `App.Administration.Definitions` › `App.Definitions.Contact` (sıra 2) ve `App.Definitions.ContactTag` (sıra 3), her biri + Create/Update/Delete/Export/Import/Note. Alt formların yetkisi `App.Definitions.Contact` altındadır: Satış, Satınalma, Mali Bilgi ve Diğer, Muhasebe, Notlar (7–11), İlgili Kişiler (12), Banka Hesapları (13). `Modules = Sas|Adm`, `MultiTenancySide = Both`. Yetkiler hiçbir role otomatik atanmaz. Widget'lar: Kontaklar ve Kontak Etiketleri'nde Toplam · Aktif · Pasif; alt formlarda widget yok. -## 7. Entegrasyonlar +### 7. Entegrasyonlar Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalma tanımları yalnızca okunur. -## 8. Akış örneği +### 8. Akış örneği 1. Yönetim › Tanımlamalar › Kontak Etiketleri'nde "Vendor" aktif durur. 2. Kontaklar'da "Acme Corporation" eklenir, Etiketler kutusundan Vendor seçilir. @@ -67,14 +72,14 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm 4. İlgili Kişiler sekmesinde Addison Olson eklenir; `ContactId` kartın Id'sinden yazılır. 5. Banka Hesapları sekmesinde IBAN girilir ve Varsayılan işaretlenir. -## 9. Sık sorulanlar +### 9. Sık sorulanlar - **Tedarikçiler ekranı nereye gitti?** Bu ekrandır; müşteri ve tedarikçi aynı Kontaklar kartında tutulur. - **Kişiler neden listede ayrı satır değil?** Kişi kontak değildir; kartın İlgili Kişiler sekmesindedir. - **Yeni kontakta Satış/Satınalma sekmeleri neden yok?** Sekmeler kaydın kendisini düzenler; kayıt ana formdan eklendikten sonra görünür. - **Sekme "Kayıt Bulunamadı" gösteriyor.** Kullanıcının o sekmenin okuma yetkisi yoktur (`App.Definitions.ContactSales` vb.); yetkiler rol ekranından verilir. -## 10. Dosyalar ve geri alma +### 10. Dosyalar ve geri alma - Tablolar: `sql/object/Adm_T_Contact.sql`, `Adm_T_ContactPerson.sql`, `Adm_T_ContactBankAccount.sql`, `Adm_T_ContactTag.sql`. - Wizard'lar: `ContactTag.json`, `ContactPerson.json`, `ContactBankAccount.json`, `ContactSales.json`, `ContactPurchasing.json`, `ContactFinancial.json`, `ContactAccounting.json`, `ContactNotes.json`, `Contact.json`. @@ -86,7 +91,9 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm > Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. -### Kontaklar — `App.Definitions.Contact` +### Tanımlamalar (`App.Administration.Definitions`) + +#### Kontaklar — `App.Definitions.Contact` | Özellik | Değer | | --- | --- | @@ -102,6 +109,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | Kapsam | Kiracı | | Alt formlar | `App.Definitions.ContactSales` (Id → Id), `App.Definitions.ContactPurchasing` (Id → Id), `App.Definitions.ContactFinancial` (Id → Id), `App.Definitions.ContactAccounting` (Id → Id), `App.Definitions.ContactNotes` (Id → Id), `App.Definitions.ContactPerson` (Id → ContactId), `App.Definitions.ContactBankAccount` (Id → ContactId) | | Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | Country=Türkiye, IsActive=true | | Veri aynası | `data/App.Definitions.Contact.json` | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | @@ -125,7 +133,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `Tags` | Etiketler | dxTagBox | | ✓ | sorgu: Adm_T_ContactTag | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -### Kontak Etiketleri — `App.Definitions.ContactTag` +#### Kontak Etiketleri — `App.Definitions.ContactTag` | Özellik | Değer | | --- | --- | @@ -148,7 +156,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `Color` | Renk | dxColorBox | | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -### İlgili Kişiler — `App.Definitions.ContactPerson` +#### İlgili Kişiler — `App.Definitions.ContactPerson` | Özellik | Değer | | --- | --- | @@ -174,7 +182,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `Mobile` | Cep Telefonu | dxTextBox | | ✓ | | | `Notes` | Notlar | dxTextArea | | ✓ | | -### Banka Hesapları — `App.Definitions.ContactBankAccount` +#### Banka Hesapları — `App.Definitions.ContactBankAccount` | Özellik | Değer | | --- | --- | @@ -198,7 +206,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `Currency` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | | `IsDefault` | Varsayılan | dxCheckBox | | ✓ | | -### Kontak Muhasebe — `App.Definitions.ContactAccounting` +#### Kontak Muhasebe — `App.Definitions.ContactAccounting` | Özellik | Değer | | --- | --- | @@ -220,7 +228,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `InvoiceAutoApprove` | Faturaları Otomatik Onayla | dxSelectBox | | ✓ | liste: Never, AfterThree, Always | | `PaymentQrType` | Ödeme QR Kodu | dxSelectBox | | ✓ | liste: None, Sepa, Emv | -### Kontak Mali Bilgi ve Diğer — `App.Definitions.ContactFinancial` +#### Kontak Mali Bilgi ve Diğer — `App.Definitions.ContactFinancial` | Özellik | Değer | | --- | --- | @@ -241,7 +249,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `Reference` | Referans | dxTextBox | | ✓ | | | `Barcode` | Barkod | dxTextBox | | ✓ | | -### Kontak Notları — `App.Definitions.ContactNotes` +#### Kontak Notları — `App.Definitions.ContactNotes` | Özellik | Değer | | --- | --- | @@ -260,7 +268,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | --- | --- | --- | --- | --- | --- | | `Notes` | Notlar | dxHtmlEditor | | ✓ | | -### Kontak Satınalma — `App.Definitions.ContactPurchasing` +#### Kontak Satınalma — `App.Definitions.ContactPurchasing` | Özellik | Değer | | --- | --- | @@ -287,7 +295,7 @@ Yok. Ülke/Şehir/İlçe, Para Birimi, Dil, Sektör, Kullanıcılar ve Satınalm | `PurchaseIncotermId` | Teslimat Koşulu (Satınalma) | dxSelectBox | | ✓ | sorgu: Prc_T_Incoterm | | `PurchaseIncotermLocation` | Incoterm Konumu (Satınalma) | dxTextBox | | ✓ | | -### Kontak Satış — `App.Definitions.ContactSales` +#### Kontak Satış — `App.Definitions.ContactSales` | Özellik | Değer | | --- | --- | diff --git a/configs/seeds/docs/modules/App.Hr.md b/configs/seeds/docs/modules/App.Hr.md new file mode 100644 index 00000000..8e0dd2b1 --- /dev/null +++ b/configs/seeds/docs/modules/App.Hr.md @@ -0,0 +1,5787 @@ +# İnsan Kaynakları (`App.Hr`) + +> Menünün altındaki her dal bu dosyada bir bölümdür (`module-doc:section`); dosya ve bölümler ilk deploy'da otomatik açılır. `module-doc:todo` işaretli alt bölümleri modülü üreten kişi ya da AI doldurur (`lowcode.instructions.md` §0.13); MCP ile üretimde talep bu bölümler doldurulmadan Testing'e alınamaz. "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. + + +## Tanımlamalar (`App.Hr.Definitions`) + +İK modüllerinin ortak sözlükleri. Bu doküman iki işi görür: (1) Tanımlamalar menüsünün **dizinidir** +— her tanımın hangi modüle ait olduğunu ve nerede kullanıldığını gösterir; (2) belirli bir modüle ait +olmayan genel tanımları (kurum doktoru, yeterlilik belgesi, hastane, hastane bölümü, evrak türü, izin +türü, masraf türü, yan hak türü) anlatır. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Dizin + +`İnsan Kaynakları › Tanımlamalar` (`App.Hr.Definitions`, ikon `FcFilingCabinet`) + +| Sıra | Menü | `ListFormCode` | Kaynak | Ayrıntı | +| --- | --- | --- | --- | --- | +| 1 | Departmanlar | `App.Hr.Department` | Entity + seeder | **Organizasyon ve Yetkinlik** bölümü | +| 2 | Pozisyonlar | `App.Hr.JobPosition` | Entity + seeder | **Organizasyon ve Yetkinlik** bölümü | +| 3 | Yetenek Tipleri | `App.Hr.SkillType` | Entity + seeder | **Organizasyon ve Yetkinlik** bölümü | +| 4 | Yeterlilik Belgeleri | `App.Hr.Certificate` | Wizard | bu doküman | +| 5 | Evrak Türleri | `App.Hr.DocumentType` | Wizard | bu doküman | +| 6 | Aday Kaynakları | `App.Hr.CandidateSource` | Wizard | **İşe Alım** bölümü | +| 7 | Ret Sebepleri | `App.Hr.RejectionReason` | Wizard | **İşe Alım** bölümü | +| 8 | Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | Wizard | **İşe Alım** bölümü | +| 9 | Masraf Türleri | `App.Hr.ExpenseType` | Wizard | bu doküman | +| 10 | Yan Hak Türleri | `App.Hr.BenefitType` | Wizard | bu doküman | +| 11 | Vardiyalar | `App.Hr.Shift` | Wizard | **Çalışma Takvimi ve Vardiyalar** bölümü · **Puantaj ve Devam Takibi** bölümü | +| 12 | İzin Türleri | `App.Hr.LeaveType` | Wizard | bu doküman | +| 13 | Kurum Doktorları | `App.Hr.Doctor` | Wizard | bu bölüm · **Sağlık Kartları** bölümü | +| 14 | Hastaneler | `App.Hr.Hospital` | Wizard | bu bölüm · **Sağlık Kartları** bölümü | +| 15 | Hastane Bölümleri | `App.Hr.HospitalDepartment` | Wizard | bu bölüm · **Sağlık Kartları** bölümü | +| 16 | Performans Dereceleri | `App.Hr.PerformanceRating` | Wizard | **Performans Yönetimi** bölümü | +| 17 | Ceza Türleri | `App.Hr.DisciplinaryPenaltyType` | Wizard | **Disiplin Dosyaları** bölümü | + +Tanımlamalar dışında duran tanımlar: Eğitim tipi/konusu → **Eğitimler** bölümü; araç +belgesi/masrafı/gidilecek yer → **Araçlar** bölümü (her alt menüde tanım ekranları en üstte); +çalışma takvimi → **Çalışma Takvimi ve Vardiyalar** bölümü. + +Sıra modül akışını izler: organizasyon → işe alım → zaman (vardiya, izin) → sağlık → performans → disiplin. +İK menüsünün kök sırası: Tanımlamalar · Organizasyon Şeması · İşe Alım · Çalışma Takvimi · İzin Yönetimi · +Puantaj ve Devam Takibi · Sağlık Kartları · Eğitim · Performans · Disiplin Dosyaları · Araçlar · Ziyaretçiler · +Olay Günlüğü · Intranet. Yetki ağacı (`AbpPermissions.Order`) aynı sırayı izler; menüsüz çalışan/yönetici +yetkileri (`MyLeaveRequest`, `MyTimesheet`, `MyPerformanceReview` …) modüllerinin hemen ardındadır. + +--- + +### 2. Analiz ve kararlar (genel tanımlar) + +> §0.13 kuralından önce üretildiler; keşif turu kaydı yoktur. Kararlar wizard ve seed dosyalarından okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Her tanım tek Wizard liste ekranı; veri seed dosyasına **aynalanır** (`SeedFilePath = data/App.Hr.{Kod}.json`, ekle/güncelle/sil senkron). Ekrandan yapılan değişiklik dosyaya yazılır, DB sıfırlanınca geri gelir | +| Aktif/Pasif | Hepsinde `IsActive` (varsayılan aktif); lookup'lar çoğunlukla yalnız aktifleri listeler | +| Kod alanı | İzin, masraf ve yan hak türlerinde iş kodu (`Code`, ör. `Annual`, `Meal`) ayrıca tutulur; yan hak kodu teklifte saklanan değerdir | +| Hazırlık tanımları | İzin türü ve masraf türü **henüz bir talep ekranına bağlı değildir** — ileride izin/masraf talep ekranlarının (onaylı talep kalıbı, `lowcode.instructions.md` §10.7) kaynağı olmak üzere tanımlanmıştır. Hastane ve hastane bölümü de şu an kullanılmıyor | + +--- + +### 3. Ekranlar + +Hepsi Grid, Card, Pivot, Chart görünümlüdür. + +| Ekran | Alanlar | Widget'lar | Seed | +| --- | --- | --- | --- | +| Kurum Doktorları | Ad soyad*, diploma no/tarihi, işyeri hekimi belge no/tarihi, T.C. kimlik no, aktif | Toplam · Aktif · Pasif | 1 | +| Yeterlilik Belgeleri | Belge adı*, aktif | Toplam · Aktif · Pasif | 16 (operatör belgeleri, kaynakçı, SRC 4, forklift, mezuniyet belgeleri, çıraklık-ustalık…) | +| Hastaneler | Kurum adı*, aktif | Toplam · Aktif · Pasif | 45 | +| Hastane Bölümleri | Bölüm adı*, aktif | Toplam · Aktif · Pasif | 31 | +| Evrak Türleri | Dosya grubu* (Genel / Özlük Evrakları / Sağlık), dosya türü*, zorunlu, aktif | Toplam · Aktif · Pasif · Zorunlu | 48 | +| İzin Türleri | Kod*, ad*, cinsiyet* (All/Male/Female), yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün kullanılabilir, bakiye aşılırsa (Engelle/Uyar), aktif | Toplam · Ücretli · Ücretsiz | 9 (Yıllık, Mazeret, Ücretsiz, Hastalık, Doğum 112 gün, Babalık 5, Evlilik 3, Ölüm 3, Süt) | +| Masraf Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, fiş/belge gerekir, aktif | Toplam · Aktif · Pasif | 7 (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) | +| Yan Hak Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, aktif | Toplam · Aktif · Pasif | 10 (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk, yakacak, diğer) | + +`*` zorunlu. Varsayılanlar: izin türünde ücretli = evet, yıllık izinden düşer/belge/yarım gün = hayır, +cinsiyet = Tümü; masraf ve yan hakta para birimi TRY, vergi/SGK = hayır, masrafta fiş gerekir = evet. + +--- + +### 4. Veri modeli + +Tablolar `sql/object/Hr_T_{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.sql` +(entity yok); kiracı + audit + `IsActive`. Kolonlar §3'teki alanlarla aynıdır. Tablo düzeyinde tekil +kısıt yoktur. + +--- + +### 5. İş kuralları + +Hesap yoktur; yalnız form varsayılanları (§3). Seed dosyası aynalandığı için tanımlar ekrandan +değiştirildiğinde `configs/seeds/data/App.Hr.*.json` dosyası da değişir — bu dosyalar commit'lenmelidir. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Her tanımın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`, +hepsi `App.Hr.Definitions` ara yetkisinin altında. Tanım ekranlarının yazma yetkisi İK'da kalmalıdır; +lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik atanmaz. + +--- + +### 7. Entegrasyonlar (kim kullanıyor) + +| Tanım | Kullanan | +| --- | --- | +| Kurum Doktorları | Sağlık Kartı (periyodik muayene, protokol, sonuç hekimleri) | +| Yeterlilik Belgeleri | Kullanıcı detayı › Eğitim ve Yetkinlik (`UserCertificate`), Performans gelişim planı (sertifika aksiyonu) | +| Evrak Türleri | Eğitim dosyaları, Disiplin belgeleri | +| Yan Hak Türleri | İşe Alım › Teklif (`BenefitCodes`, kod ile) | +| İzin Türleri | İzin Yönetimi'nin tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı); `Sick` kodlu tür Sağlık Kartı istirahatiyle eşlenir — İzin Yönetimi bölümü | +| Hastaneler, Hastane Bölümleri, Masraf Türleri | Henüz kullanan ekran yok | + +--- + +### 8. Akış örneği + +1. İK yeni bir yan hak tanımlar: kod `Gym`, ad "Spor Salonu Üyeliği", varsayılan tutar 1.500 TRY, gelir vergisine tabi. +2. Kayıt `data/App.Hr.BenefitType.json` dosyasına da yazılır. +3. İşe Alım › Teklif formundaki **Yan Haklar** listesinde yeni hak seçilebilir. + +--- + +### 9. Sık sorulanlar + +**Pasif yaptığım tanım listelerden kayboldu.** Lookup'lar yalnız aktif kayıtları listeler; eski kayıtlarda değer korunur. + +**İzin talebi nereden girilir?** Henüz izin/masraf talep ekranı yoktur; türler tanım olarak hazırdır. + +**Evrak Türleri "özlük dosyası" diyor ama özlük dosyası ekranı yok.** Doğru; türler şu an eğitim ve disiplin belgelerinde kullanılır. + +--- + +### 10. Dosyalar + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.sql` | Tablolar | +| `configs/seeds/wizard/{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.json` | 8 wizard | +| `configs/seeds/data/App.Hr.{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.json` | Aynalanan tanım verisi | + + +## Organizasyon ve Yetkinlik (Departman, Pozisyon, Organizasyon Şeması, Yetenek Tipleri) + +Şirketin organizasyon iskeleti ve yetkinlik sözlüğü: şubeye bağlı departman ağacı, departmana bağlı +pozisyon ağacı, bunların görsel organizasyon şeması ve yetenek tipi → yetenek → seviye sözlüğü. +Çalışanın departman/pozisyon/işe giriş/vardiya bilgileri ve yetkinlikleri kullanıcı kaydında tutulur. +Diğer bütün İK modülleri (İşe Alım, Eğitim, Performans, Disiplin, Sağlık Kartı…) bu tanımları lookup +olarak kullanır. Bu bölüm **entity + C# seeder** ile kuruludur (wizard değil); Organizasyon Şeması +özel bir React sayfasıdır. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK | Departman ve pozisyon ağacını, yetenek sözlüğünü yönetir | İK › Tanımlamalar › Departmanlar · Pozisyonlar · Yetenek Tipleri | +| İK / sistem yöneticisi | Çalışanın departman, pozisyon, işe giriş, vardiya, yetkinlik ve dil bilgilerini girer | Kimlik › Kullanıcılar › detay (İş Bilgileri, Eğitim ve Yetkinlik sekmeleri) | +| Tüm kullanıcılar (yetkili) | Organizasyonu departman ya da pozisyon bazında görür, JPG olarak dışa aktarır | İK › Organizasyon Şeması | + +Kapsam: kiracı. Departman ve pozisyon **şube bazlıdır** (`BranchId` zorunlu); ekranlarda satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Bu bölüm §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan +> (`ListFormSeeder_Hr.cs`, entity'ler, `OrgChartAppService`, `OrgChart.tsx`) okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Entity + `ListFormSeeder_Hr.cs` (migration'lı tablolar); şema için özel React sayfası + AppService | +| Departman | Ağaç (`ParentId`), şubeye bağlı; varsayılan görünüm **Tree**; aynı şubede ad tekil | +| Pozisyon | Ağaç (`ParentId` = üst pozisyon), departmana ve şubeye bağlı; varsayılan görünüm **Tree**; aynı departmanda ad tekil | +| Yönetici ilişkisi | Departmanda yönetici alanı **yoktur**; hiyerarşi pozisyon ağacından okunur | +| Host şubesi | Host varsayılan şubesi sabit kimlikle kurulur (`PlatformConsts.Branches.BranchIdDefaultValue = 1c125bf3-…`); seed departman/pozisyon satırları buna bağlıdır, kiracı şubeleri yeni GUID alır | +| Admin varsayılanı | Admin kullanıcı departman **Yönetim**, pozisyon **Genel Müdür** ile kurulur | +| Yetkinlik sözlüğü | Yetenek Tipi ekranının iki alt formu: Seviyeler (ad + `Progress` 0–100 kaydırıcı + varsayılan) ve Yetenekler | +| Çalışan yetkinliği | İki ayrı ölçek: **diller** `Hr_T_SkillLevel` seviyesiyle (`UserLanguage`), **diğer yetkinlikler** sabit 1–5 ile (`Adm_T_UserSkill`) | +| Tip adı bağımlılığı | Bazı lookup'lar tip adını sabit yazar (`'Languages'`, `'Technical Skills'`) — bu tipler yeniden adlandırılmamalıdır | + +--- + +### 3. Menü ve ekranlar + +| Menü (TR) | `ListFormCode` / rota | Yer | Görünüm | Alt formlar | +| --- | --- | --- | --- | --- | +| Yetenek Tipleri | `App.Hr.SkillType` | Tanımlamalar (1) | Grid | `App.Hr.SkillLevel`, `App.Hr.Skill` (`Id → SkillTypeId`) | +| Departmanlar | `App.Hr.Department` | Tanımlamalar (2) | **Tree** (`Id`/`ParentId`, tümü açık) | — | +| Pozisyonlar | `App.Hr.JobPosition` | Tanımlamalar (3) | **Tree** | — | +| Organizasyon Şeması | `/admin/organization` (`@/views/admin/hr/OrgChart`) | `İnsan Kaynakları` (4) | Özel sayfa | — | + +Bu ekranlarda widget yoktur ve veri seed dosyasına aynalanmaz (`SeedSync*` kapalı). + +**Organizasyon Şeması** (`ui/src/views/admin/hr/OrgChart.tsx`): +- **Mod:** Departman ya da Pozisyon. +- **Kullanıcıları göster:** Açık/kapalı seçilebilir. +- **Yakınlaştırma:** %30–300 arası, Ctrl + tekerlek ile de. +- **Dışa aktarma:** JPG olarak. +- **Kartlar:** Derinliğe göre renklenir, alt sayısı ve aç/kapa düğmesi taşır, sürüklenerek yeri değiştirilir (yer kaydedilmez). +- **Kullanıcı satırı:** Avatar gösterir; üzerine gelince profil kartı açılır (unvan, departman, e-posta, telefon). + +--- + +### 4. Veri modeli + +``` +Sas_T_Branch ──< Hr_T_Department (ParentId ağacı) ──< Hr_T_JobPosition (ParentId ağacı) + ▲ +AbpUsers.DepartmentId / JobPositionId / HireDate / ShiftId ┘ + +Hr_T_SkillType ──< Hr_T_SkillLevel (Progress, IsDefault) + └────────< Hr_T_Skill ──< Adm_T_UserSkill (Level 1–5) + └────< UserLanguage (SkillLevelId) +``` + +| Tablo | Kolonlar | Kural | +| --- | --- | --- | +| `Hr_T_Department` | `BranchId` (zorunlu), `Name` (64), `ParentId` | `UX (TenantId, BranchId, Name)` | +| `Hr_T_JobPosition` | `BranchId` (zorunlu), `DepartmentId` (zorunlu, FK Restrict), `Name` (64), `ParentId` | `UX (TenantId, Name, DepartmentId)` | +| `Hr_T_SkillType` | `Name` (128) | `UX (TenantId, Name)`; silinince yetenek/seviye kademeli silinir | +| `Hr_T_SkillLevel` | `SkillTypeId`, `Name`, `Progress` (int, 0), `IsDefault` | `UX (TenantId, SkillTypeId, Name)` | +| `Hr_T_Skill` | `SkillTypeId`, `Name` | `UX (TenantId, SkillTypeId, Name)` | +| `Adm_T_UserSkill` | `UserId`, `SkillId`, `Level`, `Note` (512) | `CHECK Level BETWEEN 1 AND 5`; `UX (TenantId, UserId, SkillId)` | +| `AbpUsers` (genişletme) | `DepartmentId`, `JobPositionId`, `HireDate`, `ShiftId`, sözleşme/fesih/ehliyet alanları | `PlatformModuleExtensionConfigurator`, `AbpIdentityUserExtensions` | + +Entity'ler: `Entities/Tenant/Hr/Definitions/{SkillType,Skill,SkillLevel,Department,JobPosition}.cs` +(`FullAuditedEntity, IMultiTenant`); EF yapılandırması `PlatformDbContext.cs`. + +Seed (`configs/seeds/data/`): + +| Dosya | İçerik | +| --- | --- | +| `App.Hr.Department.json` | Yönetim (kök) → Üretim, Satış, Finans (→ Muhasebe), Bilgi İşlem | +| `App.Hr.JobPosition.json` | Genel Müdür (kök) → BT, İhracat, İç Piyasa, Üretim, Finans müdürleri; Finans Müdürü → Muhasebe Müdürü → Muhasebe Şefi | +| `App.Hr.SkillType.json` | Languages, Soft Skills, Technical Skills | +| `App.Hr.Skill.json` | 31 yetenek: 21 dil, 3 soft skill, 7 teknik | +| `App.Hr.SkillLevel.json` | Diller C2 100 · C1 85 · B2 75 · B1 60 · A2 40 · A1 10 (varsayılan); Soft Skills Expert 100 · Advanced 80 · Intermediate 50 · Elementary 25 · Beginner 15 (varsayılan); **Technical Skills için seviye yok** | + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Departman formu | Ad → üst departman → şube; şube değişince üst departman temizlenir; üst departman listesi şubeye göre süzülür | +| Pozisyon formu | Ad → üst pozisyon → şube → departman; şube değişince departman ve üst pozisyon, departman değişince üst pozisyon temizlenir. Üst pozisyon listesi seçilen departmanın **ve üst departmanlarının** pozisyonları + tüm kök pozisyonlardır (`JobPositionFullValues`) | +| Seviye — yeni kayıt | `IsDefault = true` (tek varsayılan zorlanmaz) | +| Kullanıcı — İş Bilgileri | Departman değişince pozisyon temizlenir, pozisyon listesi departmana göre süzülür; deneme süresi sonu işe girişten önce ya da 4 aydan sonra olamaz (`PlatformIdentityAppService`) | +| Şema — Departman modu | Her departman kartında o departmanın **en üst pozisyonu** ve yalnızca o pozisyondaki kullanıcılar gösterilir (üst pozisyonu olmayan ya da üstü başka departmanda olan; ada göre ilk) | +| Şema — Pozisyon modu | Her pozisyon bir kart; o pozisyondaki tüm kullanıcılar | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`: + +| Yetki | Üst | Alt yetkiler | +| --- | --- | --- | +| `App.Hr.SkillType` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import, Note | +| `App.Hr.SkillLevel`, `App.Hr.Skill` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import | +| `App.Hr.Department`, `App.Hr.JobPosition` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import | +| `App.Hr.OrgChart` | grup kökü | — (menü ve rota bu yetkiyi ister) | + +Çalışanın iş bilgileri ve yetkinlikleri kullanıcı ekranının yetkileriyle (`AbpIdentity.Users.*`) düzenlenir. +Hiçbir yetki role otomatik atanmaz. + +--- + +### 7. Entegrasyonlar (kim kullanıyor) + +| Tanım | Kullanan modüller | +| --- | --- | +| Departman / Pozisyon | İşe Alım (talep, ilan, teklif), Eğitim katılımcısı, Disiplin dosyası, Sağlık Kartı listesi, Performans değerlendirmesi, kullanıcı ekranı, Organizasyon Şeması | +| Yetenek / Seviye | Aday yetkinlikleri, eğitimin kazandırdıkları, Performans yetkinlik değerlendirmesi (seviye `Progress` = puan), kullanıcı dil ve yetkinlik listeleri | +| `Adm_T_UserSkill` | Performans Yönetimi tamamlanınca yönetici seviyesini buraya yazar (bkz. Performans Yönetimi bölümü) | +| Vardiya (`ShiftId`) | Bkz. Çalışma Takvimi ve Vardiyalar bölümü | + +--- + +### 8. Akış örneği + +1. İK **Departmanlar**'a "Kalite" departmanını şube Merkez, üst departman Üretim olarak ekler (ağaçta Üretim'in altında görünür). +2. **Pozisyonlar**'a "Kalite Şefi"ni departman Kalite, üst pozisyon Üretim Müdürü olarak ekler. +3. Kullanıcı detayının **İş Bilgileri** sekmesinde çalışanın departmanı Kalite, pozisyonu Kalite Şefi, işe giriş tarihi ve vardiyası girilir; **Eğitim ve Yetkinlik** sekmesine İngilizce B2 ve "Kaynak Uzmanı 4/5" eklenir. +4. **Organizasyon Şeması** Pozisyon modunda Kalite Şefi kartı Üretim Müdürü'nün altında, çalışanla birlikte görünür; şema JPG olarak dışa aktarılır. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Departman yöneticisi nerede?** Yok; hiyerarşi pozisyon ağacındadır. (Performans modülü bu yüzden yöneticiyi değerlendirme kaydında tutar.) + +**Şemada departman kartında neden tüm çalışanlar yok?** Departman modunda yalnız en üst pozisyondakiler gösterilir; herkes için Pozisyon modunu kullanın. + +**Şemadaki kart yerleri kaydedilmiyor.** Sürükleme yalnız görünümü değiştirir. + +**Teknik yetenekler için seviye seçilemiyor.** Seed'de Technical Skills tipine seviye tanımlı değil; kullanıcı yetkinliği 1–5 ölçeğiyle girilir. Performans modülünde bu tipe seviye eklenmesi gerekir. + +**"Languages" tipinin adını değiştirdim, dil listesi boşaldı.** Lookup'lar tip adını sabit kullanır (`TenantLanguageSkillValues`, `TechnicalSkillsValues`). + +Kontrol edilmeli (koddan tespit edilen tutarsızlıklar): +- Organizasyon Şeması API'si (`api/app/org-chart`) yalnız oturum ister, `App.Hr.OrgChart` yetkisini denetlemez; menü ve rota yetkiyle korunur. +- `BranchDepartmentValues` ve `JobPositionFullValues` lookup'larında açık kiracı koşulu yoktur; `JobPositionFullValues` departmandan bağımsız tüm kök pozisyonları da listeler. +- Yetenek alt formunun popup başlığı Seviye ekranının anahtarını kullanır (`ListFormSeeder_Hr.cs`). +- Yetenek Tipi/Seviye/Yetenek yetkileri `MultiTenancySide 2`, Departman/Pozisyon `3`'tür. +- Bir tipte birden çok varsayılan seviye işaretlenebilir. + +--- + +### 10. Dosyalar + +| Dosya | İçerik | +| --- | --- | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Hr.cs` | Beş ekranın ListForm tanımı | +| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Hr/Definitions/*.cs` | Entity'ler | +| `api/src/Sozsoft.Platform.Application/OrgChart/OrgChartAppService.cs`, `Application.Contracts/OrgChart/OrgChartDto.cs` | Şema API'si (`GET departments`, `GET job-positions`) | +| `ui/src/views/admin/hr/OrgChart.tsx`, `ui/src/services/orgChart.service.ts` | Şema sayfası | +| `ui/src/views/admin/user-management/Details.tsx`, `EducationSkillsTab.tsx` | Kullanıcı iş bilgileri ve yetkinlik sekmeleri | +| `api/src/Sozsoft.Platform.Application.Contracts/LookUpQueryValues.cs` | Şube/departman/pozisyon/yetenek lookup'ları | +| `configs/seeds/data/App.Hr.{Department,JobPosition,SkillType,Skill,SkillLevel}.json` | Seed | +| `configs/seeds/data/App.Menus.Routes.json` (`admin.hr.organization`) | Şema rotası | + +Bu tablolar migration'lıdır; ekranlar seeder'dan kurulduğu için Wizard Manager'dan silinmez. + + +## Personel Kaydı (Kimlik › Kullanıcılar › detay) + +Çalışanın özlük kaydı ayrı bir İK ekranında değil, kullanıcı detay sayfasındadır +(`/admin/users/detail/:userId`): iletişim ve ek bilgiler, askerlik, engellilik, nüfus/kimlik, doğum ve +aile, yabancı uyruklu belgeleri, organizasyon (departman/pozisyon/vardiya), sözleşme ve deneme süresi, +işten çıkış, sürücü belgesi, eğitim geçmişi, yabancı diller, yetenekler, yeterlilik belgeleri, eş ve +çocuklar, acil durum kişileri, banka ve ücret bilgileri, yan haklar, iş deneyimi. (Sağlık Kartı sekmesi +için bkz. **Sağlık Kartları** bölümü.) Tek değerli alanlar `AbpUsers` genişletme kolonlarında, +çok kayıtlılar `Adm_T_User*` tablolarındadır; diğer İK modüllerinin hepsi çalışanı buradan okur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK / özlük | Personelin bütün özlük, sözleşme, eğitim, aile ve mali bilgisini girer | Kimlik › Kullanıcılar › Detay | +| Sistem yöneticisi | Kullanıcıyı açar; listede temel alanları (departman, pozisyon, cinsiyet, adres…) düzenler | Kimlik › Kullanıcılar | +| Yönetici | Deneme süresi bitimine 15 gün kala bildirim alır | Bildirimler | + +Kapsam: kiracı. Rota yetkisi `AbpIdentity.Users.Update`. + +--- + +### 2. Analiz ve kararlar + +> §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan (`Details.tsx` ve sekme +> bileşenleri, `PlatformIdentityAppService`, `ListFormSeeder_Administration.cs`, entity'ler) okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yer | Ayrı "personel" tablosu yok; özlük = kullanıcı. Tek değerli alanlar ABP extra property olarak `AbpUsers` kolonları | +| Çok kayıtlı bilgiler | `Adm_T_User{WorkExperience,Education,Language,Skill,Certificate,FamilyMember,EmergencyContact,Benefit}`; detay sekmelerinde gömülü liste (`App.IdentityManagement.*`), yeni satırın `UserId`'si sayfa filtresinden dolar | +| Kaydetme | Her form sekmesi kendi formuyla bütün modeli `PUT /api/app/platform-identity/user` (`UpdateUserAsync`) ile gönderir; başka sekmede kaydedilmemiş değişiklik gitmez | +| Mali bilgiler | Ayrı DTO ve uç (`GetFinancialAsync` / `UpdateFinancialAsync`, `Users.Update` yetkisi) — intranet listelerine akan `UserInfoViewModel`'de taşınmasın diye | +| Deneme süresi | İşe giriş ile işe giriş + **4 ay** arasında olmalı (4857 s. İK md. 15; toplu sözleşmeyle 4 ay) — hem formda hem sunucuda | +| Koşullu alanlar | Tecil bitişi yalnız "Tecilli"de, sözleşme bitişi yalnız "Belirli Süreli"de, yabancı uyruklu bölümü yalnız TR dışı uyrukta, engellilik oranı/raporu yalnız "Engelli"de **görünür**; gizlenince değer silinmez | +| Ölçekler | Dil seviyesi `Hr_T_SkillLevel` ile, diğer yetenekler sabit 1–5 ile (bkz. **Organizasyon ve Yetkinlik** bölümü) | +| Saklama biçimleri | Engellilik raporu ve avatar dışındaki dosyalar base64 kolonda; ehliyet sınıfları `|` ile birleştirilmiş metin; medeni durum ve eğitim düzeyi Türkçe anahtar | + +--- + +### 3. Ekranlar ve sekmeler + +| Sekme (TR) | İçerik | Kayıt | +| --- | --- | --- | +| Genel | İletişim (e-posta, ikinci e-posta, ad, soyad, telefon, ikinci telefon, kullanıcı tipi İç/Dış), ek bilgiler (ev adresi, uyruk, cinsiyet), askerlik (durum: Yapıldı/Muaf/Tecilli/Yapılmadı + tecil bitişi), avatar (kırpma, ≤ 2 MB), engellilik (engelli, oran %, rapor PDF/JPG/PNG ≤ 5 MB) | `UpdateUserAsync` (+ avatar `UpdateAvatarAsync`) | +| Kimlik Bilgileri | Nüfus cüzdanı (kimlik no, seri no, veriliş yeri/tarihi, il, ilçe, köy, cilt, aile sıra, sıra no), doğum ve aile (doğum yeri/tarihi, baba/anne adı, medeni durum Bekar/Evli/Boşanmış/Dul, evlenme tarihi), yabancı uyruklu (pasaport no/geçerlilik, çalışma izni no/bitiş) | `UpdateUserAsync` | +| İş | Organizasyon (departman → pozisyon, sicil no, SGK no, vardiya grubu, PDKS kart no — sicil/kart no ve vardiya puantajın kişi eşlemesi ve vardiyasıdır, Puantaj ve Devam Takibi bölümü), sözleşme (çalışma şekli Tam/Yarı Zamanlı, sözleşme türü Belirsiz/Belirli, işe başlama, sözleşme bitişi, deneme süresi bitişi, kıdem başlangıcı), işten çıkış (tarih, SGK çıkış kodu, açıklama), sürücü belgesi (sınıflar çoklu M…G, no, veriliş, geçerlilik), iletişim kanalları (Rocket, Telegram) + **Daha Önce Çalıştığı Yerler** listesi | `UpdateUserAsync` + `App.IdentityManagement.UserWorkExperience` | +| Eğitim ve Yetenekler | En yüksek eğitim seviyesi + **Eğitim Geçmişi**, **Yabancı Diller**, **Yetenekler**, **Yeterlilik Belgeleri** listeleri | `UpdateUserAsync` + 4 liste | +| Aile / Acil Durum | **Eş ve Çocuklar**, **Acil Durum Kişileri** listeleri | 2 liste | +| Finansal | Banka adı, IBAN; ücret tipi Aylık/Günlük/Saatlik, brüt ücret, para birimi + **Yan Haklar** listesi | `UpdateFinancialAsync` + `App.IdentityManagement.UserBenefit` | +| Sağlık Kartı | Bkz. **Sağlık Kartları** bölümü | — | +| Puantaj | Yılın puantaj kartları + Aylık Puantaj, Günlük Puantaj, Günlük Hareketler listeleri; bkz. **Puantaj ve Devam Takibi** bölümü §3.4 | — | +| Eğitimler | Çalışanın eğitim katılımları (`App.Hr.TrainingParticipant`, `UserId` süzgeci); bkz. **Eğitimler** bölümü | — | +| Performans | Değerlendirmeler (`App.Hr.PerformanceReview`) ve gelişim planları (`App.Hr.DevelopmentPlan`), `EmployeeId` süzgeci; bkz. **Performans Yönetimi** bölümü | — | +| Disiplin | Disiplin dosyaları (`App.Hr.DisciplinaryCase`, `UserId` süzgeci); bkz. **Disiplin Dosyaları** bölümü | — | + +Gömülü listeler (hepsi menüsüz alt liste, `Adm_T_*`): + +| Liste | Alanlar | Kural | +| --- | --- | --- | +| `UserWorkExperience` | Firma*, iş kolu* (sektör), giriş*, çıkış, yaptığı iş (HTML) | Giriş tarihine göre azalan | +| `UserEducation` | Eğitim düzeyi* (İlkokul…Doktora), okul*, bölüm, başlangıç, mezuniyet, mezun (varsayılan evet) | — | +| `UserLanguage` | Dil* ("Languages" tipi yetenekler), seviye (dilin seviyeleri), not | Kullanıcı × dil tekil | +| `UserSkill` | Yetenek* (dil dışı tipler), seviye* 1–5 (Başlangıç…Uzman, varsayılan 3), not | `CHECK 1–5`; kullanıcı × yetenek tekil | +| `UserCertificate` | Belge* (`Hr_T_Certificate`), belge no, veren kurum, düzenleme, son kullanma, not | Son kullanmaya göre artan | +| `UserFamilyMember` | Yakınlık* (Eş/Çocuk), ad*, soyad, TC kimlik, doğum tarihi, çalışma durumu (Çalışıyor/Çalışmıyor/Öğrenci/Emekli), sigorta kapsamında, yan hak kapsamında | — | +| `UserEmergencyContact` | Ad soyad*, yakınlık* (Eş, Anne/Baba, Kardeş, Çocuk, Akraba, Arkadaş, Diğer), telefon* | — | +| `UserBenefit` | Yan hak türü* (`Hr_T_BenefitType`, **kod** saklanır), tutar, başlangıç, bitiş, not | — | + +Kullanıcı listesi (`AbpIdentity.Users`) popup'ında düzenlenen İK alanları: departman*, pozisyon*, +cinsiyet, ev adresi (+ avatar, e-posta, ad, soyad, tip, telefon, çalışma saati). Diğer özlük alanları +listede gizli kolon olarak durur. + +--- + +### 4. Veri modeli + +| Yer | İçerik | +| --- | --- | +| `AbpUsers` genişletme kolonları | Bütün form sekmesi alanları; sabitler `PlatformConsts.AbpIdentity.User.*`, erişim `AbpIdentityUserExtensions`, kolon tipleri `PlatformEfCoreEntityExtensionMappings` | +| `Adm_T_UserWorkExperience` | `CompanyName`, `SectorId` (FK Sector), `StartDate`, `EndDate`, `JobDescription` | +| `Adm_T_UserEducation` | `EducationLevel`, `SchoolName`, `Department`, `StartDate`, `EndDate`, `IsGraduated` | +| `Adm_T_UserLanguage` | `SkillId` (FK Skill), `SkillLevelId` (FK SkillLevel), `Note` | +| `Adm_T_UserSkill` | `SkillId`, `Level` (1–5), `Note` | +| `Adm_T_UserCertificate` | `CertificateId` (`Hr_T_Certificate`, FK'siz), `CertificateNo`, `IssuedBy`, `IssueDate`, `ExpiryDate`, `Note` | +| `Adm_T_UserFamilyMember` | `Relationship`, `Name`, `Surname`, `IdentityNumber`, `BirthDate`, `EmploymentStatus`, `IsInsuranceCovered`, `IsBenefitCovered` | +| `Adm_T_UserEmergencyContact` | `Name`, `Relationship`, `PhoneNumber` | +| `Adm_T_UserBenefit` | `BenefitType` (kod), `Amount`, `StartDate`, `EndDate`, `Note` | + +Entity'ler `Entities/Tenant/Administration/User*.cs` (`FullAuditedEntity, IMultiTenant`), EF +yapılandırması `PlatformDbContext.cs`. + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Deneme süresi | `HireDate ≤ ProbationEndDate ≤ HireDate + 4 ay`; formda gün bazında, sunucuda (`UpdateUserAsync`) tam zamanla | +| Departman değişimi | Pozisyon temizlenir; pozisyon listesi departmana göre süzülür | +| IBAN | Formda boşluk silinir, büyük harfe çevrilir, `^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$` deseni; sunucu yalnız normalleştirir | +| Engellilik raporu | ≤ 5 MB (yalnız formda), base64 olarak kolonda | +| Avatar | `{userId}.jpg` avatar blob kabına yazılır; boş gönderim siler | +| Deneme süresi hatırlatması | `ProbationReminderWorker` günlük çalışır; aktif, çıkışı olmayan ve deneme bitişi **bugün + 15 gün** olan kullanıcılar için `DenemeSuresiBitiyor` bildirimi üretir (tip yoksa atlar) | +| Doğum günü | `BirthDate` intranet panosundaki "Bugün Doğanlar" kutusunu besler (bkz. **Intranet** bölümü) | + +--- + +### 6. Yetki ve görünürlük + +| İşlem | Yetki | +| --- | --- | +| Detay sayfası (rota), liste "Detay" butonu | `AbpIdentity.Users.Update` | +| Gömülü listeler | okuma `AbpIdentity.Users`; ekle/güncelle/sil `AbpIdentity.Users.Update` (Yan Haklar alanlarında ekleme `Users.Create`) | +| Mali bilgiler, avatar | `AbpIdentity.Users.Update` (sunucuda) | +| Kullanıcı listesi ekle/güncelle | `Users.Create` / `Users.Update` | + +Özlük verisi kişisel veri, sağlık ve engellilik verisi özel nitelikli kişisel veridir (KVKK). Kullanıcı +yönetimi yetkisi yalnız İK ve sistem yöneticilerinde olmalıdır. + +**Kontrol edilmeli — güvenlik (koddan tespit edildi):** +- `PlatformIdentityAppService.GetByIdAsync` ve `UpdateUserAsync` yalnız oturum ister (`[Authorize]`); `Users.Update` yalnız arayüz rotasında denetlenir. Oturum açmış herhangi bir kullanıcı API'yi doğrudan çağırarak başka birinin özlük kaydını (engellilik raporu dahil) okuyup güncelleyebilir. +- Banka, IBAN ve ücret alanları `AbpIdentity.Users` listesinde gizli ama okunabilir/dışa aktarılabilir kolon olarak durur; liste okuma yetkisi olan kullanıcı kolon seçiciyle görebilir. +- Intranet doğum günü listesine giden `UserInfoViewModel` kimlik no, SGK no ve sağlık kartı alanlarını da taşır. + +--- + +### 7. Entegrasyonlar + +| Kullanan | Okuduğu | +| --- | --- | +| Tüm İK modülleri | Çalışan, departman, pozisyon | +| Organizasyon Şeması | Pozisyondaki kullanıcılar | +| Vardiyalar / Olay Günlüğü | `ShiftId` | +| Yeterlilik Belgeleri, Yan Hak Türleri, Sektörler, SGK çıkış kodları, Para Birimleri | Lookup kaynakları | +| Performans Yönetimi | Tamamlanan değerlendirme `Adm_T_UserSkill`'e yazar | +| İşe Alım | İşe alınan adayın kaydı kullanıcıya `UserId` ile bağlanır | +| Intranet | Doğum günleri, kullanıcı kartları | +| Bildirimler | Deneme süresi hatırlatması (`DenemeSuresiBitiyor`) | + +--- + +### 8. Akış örneği + +1. BT kullanıcıyı listeden açar (ad, e-posta, departman, pozisyon). İK **Detay**'a girer. +2. **Kimlik Bilgileri**: nüfus ve aile bilgileri; **Genel**: adres, uyruk, askerlik, avatar. +3. **İş**: sicil/SGK no, vardiya, sözleşme türü Belirsiz, işe başlama 01.10, deneme süresi bitişi 01.12 (4 ayı aşarsa kayıt reddedilir); önceki iş yerleri listesi. +4. **Eğitim ve Yetenekler**: lisans mezuniyeti, İngilizce B2, "Kaynak Uzmanı 4", forklift belgesi. +5. **Aile / Acil Durum**: eş ve çocuk (sigorta kapsamında), acil durum kişisi. +6. **Finansal**: banka/IBAN, aylık brüt ücret TRY; yemek kartı yan hakkı. +7. 15 Kasım'da yöneticilere deneme süresinin bitmek üzere olduğu bildirimi gider. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Detayda e-postayı değiştirdim, kaydolmadı.** `UpdateUserAsync` e-postayı yazmaz; e-posta kullanıcı listesindeki düzenlemeden değişir. + +**Başka sekmede yaptığım değişiklik kayboldu.** Her sekme ayrı kaydedilir; sekme değiştirmeden önce kaydedin. + +**Sözleşmeyi Belirsiz yaptım, bitiş tarihi hâlâ kayıtlı.** Koşullu alanlar yalnız gizlenir, değer silinmez. + +**Pozisyon listede zorunlu, detayda değil.** Doğru; kullanıcı listesi popup'ı zorunlu tutar. + +**Acil durum kişisinde ad kolonu "Doktor Adı Soyadı" görünüyor.** Alan başlığı yanlış dil anahtarını (`App.Listform.ListformField.FullName`) kullanıyor; düzeltilmeli. + +**Aile üyelerindeki sigorta/yan hak işaretleri bir yere gidiyor mu?** Şu an bunları okuyan bir ekran/rapor bulunmadı. + +--- + +### 10. Dosyalar + +| Dosya | İçerik | +| --- | --- | +| `ui/src/views/admin/user-management/Details.tsx`, `EducationSkillsTab.tsx`, `FamilyEmergencyTab.tsx`, `FinancialTab.tsx`, `userFormFields.tsx`, `useUserFieldLookup.ts` | Detay sayfası ve sekmeler | +| `ui/src/views/admin/user-management/HrRecordsTab.tsx`, `hrRecordTabs.ts` | Eğitimler / Performans / Disiplin sekmeleri: İK ekranları çalışana süzülmüş açılır; sekme, ekranlarından birini görme yetkisi varsa çizilir. Yeni bir İK modülü sekmesi `HR_RECORD_TABS`'a satır eklemekle açılır | +| `api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs` | `GetByIdAsync`, `UpdateUserAsync`, `Get/UpdateFinancialAsync`, `UpdateAvatarAsync` | +| `api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs`, `EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs` | Genişletme alanları | +| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/User*.cs` | Çok kayıtlı entity'ler | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` | `AbpIdentity.Users` ve `App.IdentityManagement.*` listeleri | +| `api/src/Sozsoft.Platform.Domain/BackgroundWorkers/ProbationReminderWorker.cs` | Deneme süresi hatırlatması | + + +## İşe Alım (`App.Hr.Recruitment`) + +Kadro talebinden işe alıma kadar uçtan uca süreç: onaylı kadro talebi → iş ilanı → aday havuzu +(CV, KVKK açık rızası) → başvuru (aşama panosu) → mülakat (takvim, kriter ağırlıklı puan) → +teklif (iç onay, teklif mektubu). Tamamı konfigürasyondur (Wizard + SQL + rapor şablonu); entity, +migration ya da React kodu yoktur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Talep eden yönetici | Kadro talebi açar, onaya gönderir | Kadro Talepleri | +| Onaycı | Kadro talebini ve teklifi onaylar / reddeder | Kadro Talepleri · Teklifler (Grid Workflow butonları) | +| İK / işe alım uzmanı | İlan açar, aday ve başvuruları yönetir, mülakat planlar, teklif hazırlar, aday kaydını personele bağlar | İlanlar · Adaylar · Başvurular · Mülakatlar · Teklifler | +| Mülakatçı | Kendisine atanan mülakatta kriter bazlı puan verir | Mülakatlar (+ bildirim) | +| İK yöneticisi | Aday kaynağı, ret sebebi, değerlendirme kriteri tanımlarını yönetir | İK › Tanımlar | + +Kapsam: kiracı (`IsTenant`). Şube, kayıtta veri olarak tutulur (satır süzmesi yoktur). + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Aşağıdaki kararlar üretilen +> artefaktlardan (wizard, SQL, seed, commit `16fd5df0` "İşe Alım modülü") okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Her adım ayrı Wizard ekranı; ilan ve aday ekranlarında başvuru alt formu, başvuruda mülakat ve teklif alt formu | +| Kadro talebi ve teklif onayı | **Grid Workflow** (`WorkflowDto`): Start → Approval (`Onay Bekliyor`) → Inform → End `Onaylandı` / `Reddedildi`. Onaycı **düğümün `Approver` değeridir** (seed'de platform admin e-postası); motor onaycıyı kayıttaki alandan okumaz — ListForm › Workflow sekmesinden değiştirilir | +| İlan kaynağı | İlan yalnızca **onaylı** (`ApprovalStatus = 'Onaylandı'`) kadro talebinden açılır; şube/departman/pozisyon/adet/çalışma şekli talepten `copy` ile dolar | +| Aday kimliği | E-posta kiracı içinde tekildir (filtreli unique index) | +| KVKK | Açık rıza **zorunlu**: formda zorunlu alan + tabloda `CHECK (KvkkConsent = 1)`; rıza tarihi/yöntemi/imzalı belge saklanır; satır butonu **KVKK Açık Rıza Formu** raporunu açar | +| Başvuru | Aday × ilan çifti tekildir; aşama **Todo (kanban)** panosunda yönetilir | +| Aşama ilerlemesi | Mülakat eklenince `Interview`, teklif eklenince `Offer`, teklif `Accepted` olunca `Hired` — SQL ile, **geri gitmez** | +| Mülakat puanı | Kriter başına 1–5; `OverallScore = Σ(puan × kriter ağırlığı) / Σ ağırlık`; başvurunun `AverageScore`'u mülakatların ortalaması | +| Mülakatçı bildirimi | Mülakat eklenince mülakatçıya `IseAlimMulakatAtandi` bildirimi (kanallar `UiActivity` + `Mail`) | +| Belge numaraları | `KT-YYYY-00001` (talep), `ILN-…` (ilan), `TKL-…` (teklif) — insert sonrası SQL, kiracı + yıl bazında | +| Personele dönüşüm | İş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 (otomatik kullanıcı açılmaz) | +| Kanban başlığı | `CandidateName` / `PostingTitle` başvuruya metin olarak kopyalanır (Todo başlığı metin kolon ister) | + +--- + +### 3. Menü ve ekranlar + +`İnsan Kaynakları › İşe Alım` (`App.Hr.Recruitment`, ikon `FcManager`) + +| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Görünümler | Widget'lar | +| --- | --- | --- | --- | --- | --- | +| 1 | Kadro Talepleri / Staff Requests | `App.Hr.StaffRequest` | — | Grid, Card, Pivot, Chart | Toplam · Onay Bekliyor · Onaylanan · Onaylı kadro adedi (Σ Headcount) | +| 2 | İlanlar / Job Postings | `App.Hr.JobPosting` | `JobApplication` (`Id → JobPostingId`) | Grid, Card, Pivot, Chart | Toplam · Yayında · Taslak · Kapalı | +| 3 | Adaylar / Candidates | `App.Hr.Candidate` | `JobApplication` (`Id → CandidateId`) | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif · Personele Dönüşen | +| 4 | Başvurular / Applications | `App.Hr.JobApplication` | `Interview`, `JobOffer` (`Id → ApplicationId`) | Grid, Card, Pivot, Chart, **Todo** | — (alt form olarak da kullanıldığı için yok) | +| 5 | Mülakatlar / Interviews | `App.Hr.Interview` | `InterviewScore` (`Id → InterviewId`, menüsüz) | Grid, Card, Pivot, Chart, **Scheduler** | — | +| 6 | Teklifler / Job Offers | `App.Hr.JobOffer` | — | Grid, Card, Pivot, Chart | — | + +Tanımlar `İnsan Kaynakları › Tanımlar` (`App.Hr.Definitions`) altında, verileri seed dosyasıyla aynalı: + +| Menü | `ListFormCode` | Seed | +| --- | --- | --- | +| Aday Kaynakları | `App.Hr.CandidateSource` | 7 kayıt: LinkedIn, Kariyer.net, Yenibiris, Şirket Web Sitesi, Referans, Kariyer Fuarı, Doğrudan Başvuru | +| Ret Sebepleri | `App.Hr.RejectionReason` | 8 kayıt; `RejectedBy` = Company / Candidate | +| Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | 6 kayıt (ağırlıklı): İletişim 1, Teknik Yetkinlik 2, Problem Çözme 1.5, Takım Çalışması 1, Motivasyon 1, Kurum Kültürüne Uyum 1 | + +Satır butonları (`DynamicReport`, `Raporlar` kategorisi): + +| Ekran | Buton | Rapor şablonu | Görünürlük | +| --- | --- | --- | --- | +| Adaylar | KVKK Açık Rıza Formu | `475c1ab4-4600-5ef2-a43e-1366ed89b0ed` | Her satır | +| Teklifler | Teklif Mektubu | `80d38666-423d-5e1d-8766-01f2c46be768` | `ApprovalStatus === 'Onaylandı'` | + +--- + +### 4. Veri modeli + +``` +Hr_T_StaffRequest ──< Hr_T_JobPosting ──< Hr_T_JobApplication >── Hr_T_Candidate ──> AbpUsers (UserId, personel) + │ + ├──< Hr_T_Interview ──< Hr_T_InterviewScore >── Hr_T_EvaluationCriterion + └──< Hr_T_JobOffer +``` + +| Tablo | Önemli kolonlar | Kural | +| --- | --- | --- | +| `Hr_T_StaffRequest` | `RequestNo`, `RequestDate`, `RequestedById`, `BranchId` → `DepartmentId` → `JobPositionId` (cascade), `Headcount`, `EmploymentType`, `ExpectedStartDate`, `Reason` (NewPosition/Replacement), `ReplacedUserId`, ücret aralığı + `CurrencyId`, `Qualifications` (HTML), onay alanları | `Reason ≠ Replacement` ise `ReplacedUserId` temizlenir (script) | +| `Hr_T_JobPosting` | `PostingNo`, `StaffRequestId`, `Title`, `Status` (Draft/Published/Closed/Cancelled), şube/departman/pozisyon, `Headcount`, `EmploymentType`, `WorkModel` (Office/Hybrid/Remote), `Location`, `PublishDate`, `ClosingDate`, `SourceIds` (yayın kanalları, çok değerli), açıklama/nitelikler (HTML) | Başlık boşsa pozisyon adı kopyalanır | +| `Hr_T_Candidate` | Kişisel bilgiler, fotoğraf, ülke → şehir, eğitim (`EducationLevel`, okul, bölüm, mezuniyet), deneyim, ücret beklentisi, `SourceId`, `SkillIds` (`Hr_T_Skill`, çok değerli), `CvDocument`, `UserId`, KVKK alanları | `UX (TenantId, Email)`; `CHECK (KvkkConsent = 1)` | +| `Hr_T_JobApplication` | `CandidateId`, `JobPostingId`, `CandidateName`, `PostingTitle`, `ApplicationDate`, `SourceId`, `OwnerUserId`, `AverageScore`, `Stage`, `RejectionReasonId`, `RejectionNote`, `SortOrder` | `UX (TenantId, CandidateId, JobPostingId)`; aşama `Rejected` değilse ret sebebi/notu temizlenir | +| `Hr_T_Interview` | `ApplicationId`, `Title`, `InterviewType` (Phone/Video/FaceToFace/Technical/Hr), `InterviewerUserId`, `StartDate`, `EndDate`, `Location`, `MeetingUrl`, `Status` (Planned/Completed/Cancelled/NoShow), `Recommendation` (Hire/Hold/Reject), `OverallScore` | Bitiş boşsa başlangıç + 1 saat (script) | +| `Hr_T_InterviewScore` | `InterviewId`, `CriterionId`, `Score`, `Comment` | `CHECK (Score BETWEEN 1 AND 5)`; `UX (InterviewId, CriterionId)` | +| `Hr_T_JobOffer` | `OfferNo`, `ApplicationId`, `CandidateName`, `OfferDate`, `ValidUntil`, `StartDate`, `GrossSalary` + `CurrencyId`, `Status` (Draft/Sent/Accepted/Declined/Expired), `ResponseDate`, pozisyon bilgileri, `BenefitCodes` (`Hr_T_BenefitType`), onay alanları | `CHECK (GrossSalary >= 0)`; durum Accepted/Declined olunca yanıt tarihi bugün (script) | + +--- + +### 5. İş kuralları ve hesaplar + +#### 5.1 Başvuru aşamaları + +``` +Applied → Screening → Interview → Offer → Hired + └──→ Rejected (her aşamadan, elle) +``` + +| Tetik | Etki (after-command SQL) | +| --- | --- | +| Mülakat eklendi | Başvuru `Applied`/`Screening` ise → `Interview` | +| Teklif eklendi | Başvuru `Applied`/`Screening`/`Interview` ise → `Offer`; teklif zaten `Accepted` ise → `Hired` | +| Teklif güncellendi (`Accepted`) | Başvuru henüz `Hired` değilse → `Hired` | +| Elle | Panodan sürükleme ya da formdan her aşama seçilebilir | + +Otomatik ilerleme yalnızca ileri gider; geri almak elle yapılır. + +#### 5.2 Puanlar + +- `Interview.OverallScore = Σ(Score × Criterion.Weight) / Σ Weight` (silinmemiş puanlar). +- `JobApplication.AverageScore = AVG(Interview.OverallScore)` (puanı olan mülakatlar). +- Puan eklenince, güncellenince ya da silinince ikisi de yeniden hesaplanır. + +#### 5.3 Metin kopyaları + +`CandidateName`, `PostingTitle` (başvuru), `Title` (mülakat = aday – ilan), `CandidateName` +(teklif) after-command ile yazılır. Aday, ilan ya da başvuru güncellendiğinde **tüm** değişmiş +kopyalar topluca düzeltilir (sorgu `@Id` ile değil fark koşuluyla çalışır). + +#### 5.4 Numaratörler + +`KT-`, `ILN-`, `TKL-` + yıl + 5 hane; kiracı ve yıl bazında `MAX + 1`. Numara yalnızca boşsa yazılır. + +#### 5.5 Onay akışı (Kadro Talebi, Teklif) + +Grid Workflow; durum `ApprovalStatus`, onaylayan `ApprovalUser`, tarih `ApprovalDate`, açıklama +`ApprovalDescription`. Onay/Ret butonlarını akış kendisi çizer. Onaycı düğümde sabittir +(`system@sozsoft.com` seed değeri) — gerçek onaycı ListForm › Workflow'dan girilmelidir. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Recruitment` ara yetkisinin +altında her ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; `App.Hr.InterviewScore` +mülakat yetkisinin altındadır. Tanımlar `App.Hr.Definitions` altındadır. Satır süzmesi yoktur — +ekran yetkisi olan tüm kayıtları görür. Hiçbir yetki role otomatik atanmaz. + +Önerilen dağıtım: + +| Rol | Yetkiler | +| --- | --- | +| Talep eden yöneticiler | `App.Hr.StaffRequest` (+ `.Create/.Update`) | +| Mülakatçılar | `App.Hr.Interview` (+ `.Update`), `App.Hr.InterviewScore` (+ `.Create/.Update/.Delete`) | +| İşe alım uzmanı | `App.Hr.Recruitment` dalının tamamı + üç tanım ekranı | +| Onaycı | Onaylayacağı ekranın kökü + `.Update` | + +KVKK: aday verisi kişisel veridir; Adaylar ekranının yetkisi yalnızca işe alım ekibine verilmelidir. + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `Sas_T_Branch`, `Hr_T_Department`, `Hr_T_JobPosition` | Şube → departman → pozisyon cascade (talep, ilan, teklif) | +| `Sas_H_Currency` | Ücret para birimi (varsayılan TRY) | +| `Sas_H_Country`, `Sas_H_City` | Aday adresi (ülke → şehir cascade) | +| `Hr_T_Skill` / `Hr_T_SkillType` | Aday yetkinlikleri (`SkillIds`) | +| `Hr_T_BenefitType` | Teklifteki yan haklar (`BenefitCodes`) | +| `AbpUsers` | Talep eden, ayrılan personel, sorumlu, mülakatçı, personele dönüşen aday | +| Bildirimler | Tip `IseAlimMulakatAtandi`; kurallar `Custom` + `UiActivity`/`Mail`; metin `App.Hr.Interview.Notification.{Subject,Message}`, yer tutucular `[Candidate]`, `[Posting]`, `[Date]` | +| Raporlar | KVKK Açık Rıza Formu, Teklif Mektubu (`DynamicReport`) | + +--- + +### 8. Akış örneği + +1. Satış müdürü **Kadro Talepleri**'nde "Satış Temsilcisi, 2 kişi, yeni pozisyon" talebini açar → + `KT-2026-00001`; onaya gönderir, onaycı onaylar → `Onaylandı`. +2. İK **İlanlar**'da talebi seçer; şube/departman/pozisyon/adet dolar, başlık pozisyon adı olur; + yayın kanallarını (LinkedIn, Kariyer.net) seçip durumu **Published** yapar → `ILN-2026-00001`. +3. Gelen adaylar **Adaylar**'a CV ve KVKK rızasıyla girilir; KVKK formu satır butonundan basılır. +4. İlanın **Başvurular** sekmesinden aday eklenir (`Applied`); kanban panosunda **Screening**'e çekilir. +5. Başvurunun **Mülakatlar** sekmesinden teknik mülakat planlanır → başvuru `Interview` olur, + mülakatçıya bildirim gider; mülakatçı kriterleri puanlar → genel ve ortalama puan hesaplanır. +6. **Teklifler**'de teklif hazırlanır → başvuru `Offer`; teklif onaya gider, onaylanınca + **Teklif Mektubu** basılır. +7. Aday kabul eder, teklif **Accepted** yapılır → başvuru `Hired`. BT kullanıcıyı açar, İK aday + kaydının **Personel** alanına bağlar ("Personele Dönüşen" kartı artar). + +--- + +### 9. Sık sorulanlar + +**İlan açarken kadro talebi listede yok.** Yalnızca onaylanmış (`ApprovalStatus = 'Onaylandı'`) talepler listelenir. + +**Onay butonu kimde görünüyor?** Akış düğümündeki `Approver`'da (seed'de admin). ListForm › Workflow'dan gerçek onaycıyı yazın. + +**Başvuru aşaması geri gitmedi.** Otomatik ilerleme yalnız ileri gider; geri almayı panodan ya da formdan elle yapın. + +**Ret sebebi alanı temizlendi.** Ret sebebi ve notu yalnızca `Rejected` aşamasında tutulur. + +**Aday kaydı kaydedilmiyor.** KVKK rızası işaretli olmalı (tablo da zorlar) ve e-posta kiracıda tekil olmalı. + +**Aynı aday aynı ilana ikinci kez eklenemiyor.** Aday × ilan tekildir. + +**Mülakat puanı nasıl hesaplanıyor?** Kriter ağırlıklı ortalama (§5.2); ağırlıklar İK › Tanımlar › Değerlendirme Kriterleri'nden. + +**İşe alınan aday otomatik personel olmuyor mu?** Hayır; kullanıcıyı BT açar, İK aday kaydına bağlar. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{StaffRequest,JobPosting,Candidate,JobApplication,Interview,InterviewScore,JobOffer,CandidateSource,RejectionReason,EvaluationCriterion}.sql` | Tablolar, CHECK ve tekil indeksler | +| `configs/seeds/wizard/{StaffRequest,JobPosting,Candidate,JobApplication,Interview,InterviewScore,JobOffer,CandidateSource,RejectionReason,EvaluationCriterion}.json` | 10 wizard | +| `configs/seeds/data/App.Hr.{CandidateSource,RejectionReason,EvaluationCriterion}.json` | Tanım verisi | +| `configs/seeds/data/App.Reports.ReportTemplates.json` | KVKK formu ve teklif mektubu şablonları | +| `configs/seeds/data/App.Notifications.Notification{Types,Rules}.json` | `IseAlimMulakatAtandi` tipi ve 2 kuralı | +| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | + +Kurulum: DB Migrate. Geri alma: Wizard Manager'dan wizard'lar silinir (alt formlar önce: `InterviewScore` +→ `Interview`/`JobOffer` → `JobApplication` → diğerleri); tablolar yalnızca onayda seçilirse düşer. +Rapor şablonları ve bildirim satırları elle kaldırılır. + + +## Çalışma Takvimi ve Vardiyalar (`App.Hr.WorkCalendar`, `App.Hr.Shift`) + +Çalışma zamanının iki temel tanımı: resmi tatil / yarım gün takvimi (yıllık tekrarlı ya da tek +seferlik) ve vardiya tanımları (saat aralığı, mola, gece vardiyası). Diğer modüller bu tanımları +lookup olarak kullanır. Tamamı konfigürasyondur (Wizard + seed); vardiya ayrıca kullanıcı kaydına +bağlanır. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK | Yılın tatil ve yarım günlerini girer, takvim görünümünden kontrol eder | Çalışma Takvimi | +| İK / üretim planlama | Vardiya tanımlarını yönetir, çalışanı vardiyaya bağlar | Vardiyalar · Kimlik › Kullanıcılar | + +Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur — takvim kiracının tamamı için geçerlidir. + +--- + +### 2. Analiz ve kararlar + +> Modüller §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan +> (wizard, seed, commit `130e23bc` "Disiplin Dosyaları, Çalışma Takvimi") okunmuştur. + +| Konu | Karar | +| --- | --- | +| Tatil tekrarı | Sabit tarihli resmi tatiller `RecurrenceRule = FREQ=YEARLY` ile **bir kez** girilir, her yıl tekrarlar; dini bayramlar ay takvimine bağlı olduğu için **her yıl ayrı** satırdır (tekrar kuralı boş) | +| Gün türü | `Holiday` (tam gün tatil) / `HalfDay` (arife, yarım gün) | +| Görünüm | Liste görünümlerine ek olarak **Scheduler** (takvim) görünümü; `AllDay` her zaman `true` | +| Vardiya saatleri | `StartTime` / `EndTime` `SS:dd` metin; çalışma süresi elle girilir (otomatik hesap yok) | +| Gece vardiyası | Bayrak (`IsNightShift`) — sağlık kartındaki "gece çalışabilir" sonucuyla birlikte değerlendirilir, otomatik kontrol yoktur | +| Vardiya bağı | Kullanıcı kaydında `ShiftId` alanı (`LookupQueryValues.TenantShiftValues`: "Ad (başlangıç-bitiş)") | +| Menü yeri | Çalışma Takvimi `İnsan Kaynakları` kökünde; Vardiyalar bir tanım olduğu için `İnsan Kaynakları › Tanımlamalar` altında (yetkisi de `App.Hr.Definitions`'ın altındadır) | + +--- + +### 3. Menü ve ekranlar + +| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | +| --- | --- | --- | --- | --- | +| Çalışma Takvimi / Work Calendar | `App.Hr.WorkCalendar` | `İnsan Kaynakları` (sıra 4, `FcCalendar`) | Grid, Card, Pivot, Chart, **Scheduler** | Toplam · Tatil · Yarım Gün | +| Vardiyalar / Shifts | `App.Hr.Shift` | `İnsan Kaynakları › Tanımlar` (sıra 11, `FcClock`) | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | + +Scheduler eşlemesi: metin `Name`, başlangıç `StartDate`, bitiş `EndDate`, tüm gün `AllDay`, +tekrar `RecurrenceRule`. + +Seed verisi: +- Çalışma takvimi, 16 satır (`data/App.Hr.WorkCalendar.json`): + - Yıllık tekrarlı tatiller: Yılbaşı, 23 Nisan, 1 Mayıs, 19 Mayıs, 15 Temmuz, 30 Ağustos, 29 Ekim. + - Yıllık tekrarlı yarım gün: 28 Ekim arifesi. + - Yıla özel satırlar: 2026 ve 2027 Ramazan/Kurban bayramları ve arifeleri. +- Vardiyalar, 3 satır (`data/App.Hr.Shift.json`): Sabah 08:00–16:00, Akşam 16:00–00:00, Gece 00:00–08:00 (gece vardiyası). + +--- + +### 4. Veri modeli + +| Tablo | Kolonlar | +| --- | --- | +| `Hr_T_WorkCalendar` | `Name`, `StartDate`, `EndDate`, `DayType` (Holiday/HalfDay), `RecurrenceRule` (boş / `FREQ=YEARLY`), `AllDay`, `IsActive` | +| `Hr_T_Shift` | `Name`, `StartTime`, `EndTime`, `BreakMinutes`, `LateToleranceMinutes`, `EarlyLeaveToleranceMinutes`, `WorkingHours`, `IsNightShift`, `IsActive` | +| `AbpUsers.ShiftId` | Çalışanın vardiyası (genişletme kolonu) | + +Entity yoktur (wizard tabloları); `sql/object/Hr_T_{WorkCalendar,Shift}.sql`. + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Takvim — yeni kayıt | Gün türü `Holiday`, tekrar `FREQ=YEARLY`, tüm gün, aktif | +| Takvim — çok günlü tatil | Başlangıç–bitiş aralığı olarak tek satırda girilebilir | +| Vardiya — yeni kayıt | Gece vardiyası hayır, aktif | + +| Vardiya — toleranslar | Geç kalma / erken çıkış toleransı (dk); boşsa Ayarlar › İnsan Kaynakları › Puantaj'daki genel değer | + +Takvim İzin Yönetimi'nin gün sayısını (İzin Yönetimi bölümü), takvim ve vardiya Puantaj ve Devam Takibi'nin +gün tipini, vardiya saatini, molasını ve toleransını (Puantaj ve Devam Takibi bölümü) besler. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Her ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`. +Hiçbir yetki role otomatik atanmaz. Takvimin okunması tüm çalışanlara açılabilir; düzenleme İK'da kalmalıdır. + +--- + +### 7. Entegrasyonlar + +| Kullanan | Nasıl | +| --- | --- | +| Kimlik › Kullanıcılar | `ShiftId` alanı vardiya lookup'ı | +| Olay Günlüğü (`App.Hr.EventLog`) | Olay kaydında vardiya seçimi | +| Sağlık Kartları | Vardiyalı / gece çalışabilir sonucu (bilgi; vardiya tanımıyla otomatik eşleşmez) | +| İzin Yönetimi | Takvim tatilleri izin gününden düşülür (`Hr_F_LeaveWorkDays`). Takvim satırı eklenince/değişince/silinince denk gelen izinlerin gün sayısı yeniden hesaplanır (`Hr_S_WorkCalendarAfterSave`) | +| Puantaj ve Devam Takibi | Tatil → Resmî tatil, arife → yarım vardiya (`Hr_F_WorkCalendarDayType`); vardiya saat/mola/tolerans → `Hr_V_AttendanceShift`. Takvim kaydı ilgili günleri hemen yeniden hesaplar (kapalı ay hariç); vardiya değişikliği gece işinde ya da Puantaj Dönemleri kaydında yansır | + +--- + +### 8. Akış örneği + +1. Yıl başında İK **Çalışma Takvimi**'nde o yılın dini bayram satırlarını ekler (sabit tatiller zaten yıllık tekrarlıdır) ve Scheduler görünümünde yılı kontrol eder. +2. Üretim için **Vardiyalar**'a "Hafta Sonu 08:00–20:00, mola 60 dk, çalışma 11 saat" eklenir. +3. Kullanıcı ekranında çalışanların **Vardiya** alanı güncellenir; Olay Günlüğü kayıtlarında da bu vardiyalar seçilir. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Ramazan Bayramı gelecek yıl görünmüyor.** Dini bayramlar yıla özeldir; her yıl yeni satır girilir. + +**Çalışma süresi neden hesaplanmıyor?** Vardiya saatleri metindir, süre elle girilir. + +**Takvim izin/puantaj hesabını etkiliyor mu?** Evet: izin gün sayısından tatiller düşülür, puantajda tatil +günü Resmî tatil, arife yarım gün sayılır. Takvim satırı kaydedilince denk gelen günlerin izin gün sayısı ve +puantajı hemen yeniden hesaplanır (yıllık tekrarlı satırda bu yıl ve gelecek yıl; kapalı puantaj ayı yazılmaz). +Bir satırın tarihi değiştirildiğinde eski tarihlerin puantajı gece işinde ya da Puantaj Dönemleri kaydında düzelir. + +**Vardiyalar nerede?** `İnsan Kaynakları › Tanımlamalar` altında (sıra 11); menü satırı, wizard dosyası ve +yetki ağacı aynı yeri gösterir. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{WorkCalendar,Shift}.sql` | Tablolar | +| `configs/seeds/wizard/{WorkCalendar,Shift}.json` | 2 wizard | +| `configs/seeds/data/App.Hr.{WorkCalendar,Shift}.json` | Takvim ve vardiya verisi (ekran kayıtları dosyaya aynalanır) | +| `api/src/Sozsoft.Platform.Application.Contracts/LookUpQueryValues.cs` (`TenantShiftValues`) | Kullanıcı ekranındaki vardiya lookup'ı | + +Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının lookup'ı tarafından okunduğu için düşürülmemelidir. + + +## İzin Yönetimi (`App.Hr.Leave`) + +İzin talebi, iki aşamalı onay (departman müdürü → İK), yıllık izin bakiyesi ve rapor (istirahat) +eşlemesi. **İnsan Kaynakları menüsü yalnız İK içindir**: tüm talepleri ve bakiyeleri İK izler. +Çalışan ve müdür izinle ilgili her şeyi **Intranet › Dashboard**'daki widget'lardan yapar. Wizard +ekranları, SQL nesneleri ve custom component widget'larıyla kuruludur. Çerçeve dışında iki ek +vardır (kullanıcı onayıyla): Grid Workflow'da kayıttan okunan onaycı (`@Kolon`) ve kullanıcı +detayındaki **İzinler** sekmesi. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Çalışan | Bakiyesini izler, izin talebi açar, taleplerinin onay durumunu takip eder, henüz karar verilmemiş talebini düzeltir/siler | Intranet panosu: **İzinlerim** widget'ı → İzin Talebi Oluştur · Taleplerim · Bakiyem · Profil › İzinlerim (bakiye + talepler salt okunur, İzin Talebi Oluştur) | +| Departman müdürü | Departmanının taleplerini onaylar/reddeder | Intranet panosu: **Ekibimin İzinleri** widget'ı → Ekibimin İzin Talepleri | +| İK | Tüm talepleri izler, ikinci onayı verir, çalışan adına talep girer, bakiyeleri izler, açılış/devir düzeltmesi girer, çalışma günlerini ve kademeleri ayarlar | İK › İzin Yönetimi › İzin Talepleri · İzin Bakiyeleri · Ayarlar › İnsan Kaynakları › İzin · Kullanıcı detayı › İzinler | +| Sağlık birimi | Raporu Sağlık Kartı'na girer; kayıt izin listesine onaylı düşer | İK › Sağlık Kartları › İstirahat Raporları | + +Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur. + +--- + +### 2. Analiz ve kararlar + +#### 2.1 Talep + +> İnsan Kaynakları › İzin Yönetimi. Kullanıcı Intranet Dashboard'dan kendi bakiye raporunu izler, +> izin talebi oluşturur, bir butonla taleplerini ve onay durumlarını takip eder (Performansım +> widget'ındaki Değerlendirmelerim gibi). İzin türüne göre gerekli alanlar doldurulur; bakiye +> yetmezse talep engellenir veya uyarı verilir; aynı tarihlerde çakışan talep oluşturulamaz. +> Sağlık Kartı › İstirahatler ile Rapor türündeki izin tek kayıttır. İzin bakiyesi kullanıcı +> kartında gösterilir. Alanlar: izin türü, başlangıç/bitiş tarihi ve saati, yarım gün, gün sayısı +> (otomatik), açıklama, ek belge, durum. Yıllık hak çalışma yılına göre hesaplanır. Onay önce +> departman müdürü (İş Pozisyonları'ndaki departman müdürü), sonra İK. Talep gelince yöneticiye +> bildirim gider. İK menüsü yalnız İK kullanır; widget'lar Aktif Anketler'in altına (sol kolon). + +#### 2.2 Depodan okunanlar (sorulmadı) + +- İzin türleri `Hr_T_LeaveType` (İK › Tanımlamalar): cinsiyet, yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün. +- Rapor kayıtları `Adm_T_UserSickLeave`; iki ekran kullanır: Sağlık Kartı (`App.Hr.HealthCardSickLeave`) ve kullanıcı detayı (`App.IdentityManagement.UserSickLeave`). +- Kıdem `AbpUsers.SeniorityStartDate` (boşsa `HireDate`), doğum `BirthDate`, cinsiyet `Gender`, departman/pozisyon `DepartmentId`/`JobPositionId`. +- Tatiller `Hr_T_WorkCalendar` (`Holiday` / `HalfDay`, `FREQ=YEARLY` tekrar). +- Pozisyon ağacı `Hr_T_JobPosition` (`DepartmentId` + `ParentId`); departmanda "müdür" alanı yoktur. +- Grid Workflow onaycıyı düğümde sabit tutuyordu — kayda göre değişen müdür için motor eki gerekti. + +#### 2.3 Keşif turu cevapları + +| # | Soru | Seçilen | +| --- | --- | --- | +| 1 | Onay akışı | Grid Workflow + motor eki: düğüm onaycısı `@Kolon` ise kayıttan okunur | +| 2 | Müdür nasıl bulunur | Departmanın en üst pozisyonu (üst pozisyonu başka departmanda ya da üstü olmayan); çalışan o pozisyondaysa bir üst pozisyonun sahibi; birden çok müdür varsa herhangi biri | +| 3 | Yıllık hak | İş Kanunu md.53 kademeleri + devir (kullanılmayan izin devreder) | +| 4 | Bakiye yetersiz | İzin türü bazında İK seçer: `BalanceExceedAction` = Engelle / Uyar ve kaydet | +| 5 | İK onaycısı | Düğümde sabit kullanıcı(lar) (İzin Talepleri akışının "İK Onayı" düğümü) | +| 6 | Gün sayısı | Ayarlar › İnsan Kaynakları › İzin'deki çalışma günleri + Çalışma Takvimi tatilleri (kullanıcı kararı: tüm İK ayarları bu grupta) | +| 7 | Rapor talebi | Onay akışından geçer; onaylanınca Sağlık Kartı'nda görünür (onay beklerken sağlık kartına ve puantaja düşmez), reddedilirse kalkar | +| 8 | Kullanıcı kartı | Kullanıcı detayına **İzinler** sekmesi (bakiye özeti + talepler + defter) | +| 9 | Üstü olmayan pozisyon (Genel Müdür) | Müdür adımı atlanır, talep doğrudan İK Onayı'na gider (üretim sırasında soruldu) | + +#### 2.4 Üretimde verilen kararlar + +| Konu | Karar | Neden | +| --- | --- | --- | +| Persona ekranında akış | **İzin Taleplerim** ekranında Workflow yoktur; ilk adımı (`Müdür Onayı` + müdür kullanıcı adları) kayıt sonrası prosedür yazar | Workflow alanlarını yazabilen persona ekranı, çalışanın durumu API ile "Onaylandı" yapmasına izin verirdi; alanlar İK yetkisine kilitli | +| Müdür ekranı | **Ekibimin İzin Talepleri** ayrı ekran, aynı akış başlıklarıyla; satır `ManagerIds` ile süzülür | Akış düğümleri ekrana bağlıdır, durum başlıkla eşleşir (`FindCurrentCriteria`) | +| İK onaycısının tek kaynağı | Kayıt sonrası prosedür İK adımına girerken onaycıyı **İzin Talepleri** akışının "İK Onayı" düğümünden okur | Ekibimin İzin Talepleri akışındaki İK düğümü ayrı düzenlenirse sapma olmasın | +| Yöneticinin geçişleri | Müdür yalnız Müdür Onayı → İK Onayı / Reddedildi yapabilir; başka geçiş geri alınır | Workflow alanları müdür ekranında yazılabilir olmak zorunda (motor ekranın kayıt yolunu kullanır) | +| Bakiye defteri | Hak ediş yılı başına satır; 0. yıl düzeltmeler ve ilk hak edişten önceki kullanım | Devirli kümülatif bakiyenin denetlenebilir dökümü | +| Açılış bakiyesi | **Bakiye Düzeltmeleri** (± gün) | Devirli hesapta sistem öncesi kullanım girilmezse geçmiş bütün yıllar kullanılmamış görünür | +| Bildirim | Uygulama içi + toast (`IzinTalebiOnayBekliyor`, `IzinTalebiSonuclandi`); Workflow `Inform` düğümü kullanılmadı | Inform yalnız e-posta gönderir ve onaycısı sabittir | +| Ek belge | `dxImageUpload` (base64, `nvarchar(MAX)`), listede gizli | Platform standardı | +| En üst pozisyon | Prosedür `RequiresManagerApproval`'ı yazar (1 = müdür onayı gerekir, 0 = atlanır); İzin Talepleri akışında Başlangıç ile Müdür Onayı arasında bu kolona bakan karşılaştırma düğümü vardır, çalışanın kendi talebinde prosedür durumu doğrudan İK Onayı yapar | Motorun karşılaştırma düğümü yalnız sayısal kolon okur (`EvaluateCondition`) ve satırı ekranın sorgusundan alır; kolon İzin Talepleri'nde gizli alandır | +| Form günü | Gün formda tarayıcıda önizlenir (hafta içi gün, yarım günde 0,5), kalıcı değer prosedürün hesabıdır; İzin Türü lookup'ı cascade değildir | Cascade ebeveyni çocuğu kilitler ve değiştiğinde temizler; ayrıntı §5.1 | +| Bildirim başlığı | Bildirim panelinde ve etkinlik kaydında tip adı yerine kaydın `Subject`'i gösterilir (bütün modüller) | Tip adı (`PerformansDurumDegisti`) koddur; konu çevrilmiş metindir | + +#### 2.5 Varsayılan kalanlar + +- Çalışma günleri Pzt–Cum; kademeler 14 / 20 / 26, genç/yaşlı en az 20 (ayarlarda değiştirilir). +- İzin türü varsayılanı: yıllık izinden düşen ya da yıllık sınırı olan türler **Engelle**, diğerleri **Uyar ve kaydet** (seed). +- Rapor kaydı `SickLeaveType = Disease`, gün sayısı takvim günü (Sağlık Kartı kuralı); izin talebindeki gün çalışma günüdür. + +--- + +### 3. Menü ve ekranlar + +#### 3.1 İK menüsü + +`İnsan Kaynakları › İzin Yönetimi` (`App.Hr.Leave`, sıra 14, `FcOvertime`) — yalnız İK. + +| Sıra | Menü (TR / EN) | `ListFormCode` | Wizard | Kaynak | Alt formlar | Widget'lar | +| --- | --- | --- | --- | --- | --- | --- | +| 1 | İzin Talepleri / Leave Requests | `App.Hr.LeaveRequest` | `LeaveRequest.json` | `Hr_T_LeaveRequest` | — | Müdür Onayında · İK Onayında · Onaylanan (bu yıl) · Reddedilen (bu yıl) | +| 2 | İzin Bakiyeleri / Leave Balances | `App.Hr.LeaveBalance` | `LeaveBalance.json` | `Hr_V_LeaveSummary` (salt okunur) | `LeaveBalanceAdjustment`, `LeaveBalanceYear` (`Id → EmployeeId`) | Çalışan · Toplam Kalan Gün · Eksi Bakiye · Onay Bekleyen Gün | + +Menüsüz alt formlar: **Bakiye Düzeltmeleri** (`App.Hr.LeaveBalanceAdjustment`, `Hr_T_LeaveBalanceAdjustment`), +**İzin Defteri** (`App.Hr.LeaveBalanceYear`, `Hr_V_LeaveBalanceYear`, salt okunur). + +Görünümler: hepsi Grid, Card, Pivot, Chart. + +#### 3.2 Çalışana ve müdüre ait ekranlar (menüsüz) + +| Ekran | `ListFormCode` | Satır süzmesi | Yapılabilen | +| --- | --- | --- | --- | +| İzin Taleplerim | `App.Hr.MyLeaveRequest` | `EmployeeId = @USERID` | Ekle; karar verilmeden düzelt/sil. `EmployeeId` sunucuda `@USERID` ile yazılır | +| Bakiyem | `App.Hr.MyLeaveBalance` | `EmployeeId = @USERID` | Defteri görür | +| Ekibimin İzin Talepleri | `App.Hr.TeamLeaveRequest` | `ManagerIds` içinde kullanıcı | Müdür adımında Onayla / Reddet | + +Talep formu doğrudan açılır: `/admin/form/App.Hr.MyLeaveRequest`. + +#### 3.3 Intranet › Dashboard widget'ları + +Sol kolon (`Column: 0`), Aktif Anketler'in (30) altında; kayıtlar `data/App.DeveloperKit.IntranetWidgets.json`. + +| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Butonlar | +| --- | --- | --- | --- | --- | +| `my-leave` · 35 | `MyLeaveWidget` | `App.Hr.MyLeaveRequest` | Kalan / kullanılan / onay bekleyen gün, sonraki hak ediş, süren ilk 3 talep ve durumu | İzin Talebi Oluştur · Taleplerim · Bakiyem | +| `team-leave` · 36 | `TeamLeaveWidget` | `App.Hr.TeamLeaveRequest` | Onayımı bekleyen talep sayısı ve ilk 5'i, bugün izinde olanlar | Onay Bekleyenler | + +Bileşenler code modunda, rotasızdır; veriyi ekranların kendi sorgusundan okur +(`GET /api/app/list-form-select/select`). Bakiye kartları `App.Hr.MyLeaveBalance` yetkisi yoksa gizlenir. + +#### 3.4 Kullanıcı detayı › İzinler + +`ui/src/views/admin/user-management/LeaveTab.tsx`: İzin Bakiyeleri satırından altı kart (hak edilen, +düzeltme, kullanılan, bekleyen, kalan, kullanılabilir), altında kullanıcıya süzülmüş **İzin Talepleri** +ve **İzin Defteri** listeleri. Her parça kendi ekran yetkisiyle görünür; İK buradan çalışan adına talep +ekleyebilir (yeni satırın `EmployeeId`'si süzgeçten dolar). + +#### 3.5 Ayarlar + +Ayarlar › İnsan Kaynakları › İzin (`App.HrSettings` › `App.HrSettings.Leave`, sağlayıcılar `T|G|D`): + +| Kod | Varsayılan | +| --- | --- | +| `App.HrSettings.Leave.Work{Monday…Sunday}` | Pzt–Cum `True`, Cmt–Paz `False` | +| `App.HrSettings.Leave.AnnualDays1To5` / `AnnualDays5To15` / `AnnualDays15Plus` | 14 / 20 / 26 | +| `App.HrSettings.Leave.MinDaysYoungOld` | 20 | + +SQL tarafı ayarı `dbo.Hr_F_HrSetting` ile ABP'nin sırasıyla okur (kiracı → genel → tanım varsayılanı). + +--- + +### 4. Veri modeli + +``` +AbpUsers ──< Hr_T_LeaveRequest >── Hr_T_LeaveType + │ └── Adm_T_UserSickLeave (SickLeaveId, Rapor türünde) + └──< Hr_T_LeaveBalanceAdjustment +Hr_V_LeaveBalanceYear (defter) ──▶ Hr_V_LeaveSummary (çalışan başına toplam) +``` + +| Nesne | Önemli kolonlar | Kural | +| --- | --- | --- | +| `Hr_T_LeaveRequest` | `RequestNo`, `EmployeeId`/`EmployeeName`/`DepartmentId`/`JobPositionId`, `LeaveTypeId`, `StartDate`/`EndDate` (tarih+saat), `IsHalfDay`, `HalfDayPart` (Morning/Afternoon), `Days` (0,5 adımlı), `Description`, `DocumentFileName`/`DocumentContent`, `BalanceWarning`, `SickLeaveId`, `ManagerIds`/`ManagerUserNames`, `RequiresManagerApproval` (int, 1/0), `ApprovalStatus`/`ApprovalUser`/`ApprovalDate`/`ApprovalDescription`, `LastNotifiedStatus`, `IsActive` | `EndDate ≥ StartDate`; kiracı + tam audit | +| `Hr_T_LeaveBalanceAdjustment` | `EmployeeId`, `AdjustmentDate`, `Days` (≠ 0, ±), `Reason`, `IsActive` | — | +| `Hr_T_LeaveType` (+ kolon) | `BalanceExceedAction` (`Block`/`Warn`, varsayılan `Block`) | Kayıpsız `ALTER ADD` | +| `Hr_V_LeaveBalanceYear` | `Id` (`{EmployeeId}-{YearNo}`), `YearNo`, `AccrualDate`, `PeriodEndDate`, `EntitledDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `CumulativeRemainingDays`, `NextAccrualDate`, `NextAccrualDays` | Görünüm | +| `Hr_V_LeaveSummary` | `Id` (= kullanıcı), `ServiceYears`, `EntitledDays`, `AdjustmentDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `AvailableDays`, `NextAccrualDate/Days`, `IsActive` | Görünüm | + +Durum değerleri (Workflow düğüm başlıkları): `Onaya Gönderildi` · `Müdür Onayı` · `İK Onayı` · `Onaylandı` · `Reddedildi`. + +--- + +### 5. İş kuralları ve hesaplar + +#### 5.1 Gün sayısı (`Hr_F_LeaveWorkDays`) + +Başlangıç–bitiş tarihleri (saat dikkate alınmaz) arasındaki her gün: ayarlarda çalışma günü değilse 0; +Çalışma Takvimi'nde `Holiday` ise 0, `HalfDay` ise 0,5; aksi 1. Yıllık tekrarlı satır başlangıç +yılından itibaren her yıl aynı gün/aya düşer. Yarım gün talepte sonuç en fazla 0,5'tir. + +Formda gün veri girerken dolar (Başlangıç, Bitiş ve Yarım Gün alanlarının `EditorScript`'i, `custom` tarifi). +Bu bir önizlemedir: iki tarih arasındaki hafta içi günler sayılır, yarım günde 0,5 yazılır; Çalışma Günleri +ayarı ve Çalışma Takvimi tatilleri formda düşülmez. Kayıtta prosedür günü `Hr_F_LeaveWorkDays` ile yeniden +hesaplar ve kayıtlı değer odur. + +| Olay | Formda | +| --- | --- | +| Başlangıç / Bitiş değişir | Gün yeniden hesaplanır; yarım gün açıkken Başlangıç değişirse Bitiş onu izler | +| Yarım Gün işaretlenir | Bitiş = Başlangıç, Gün 0,5, Yarım Gün Dilimi açılır | +| Yarım Gün kaldırılır | Dilim temizlenip kilitlenir, Gün tam gün olarak hesaplanır | + +Notlar: + +- **Dilim kilidi `custom` kuralıdır** (`readOnly` tarifi değil). Grid popup'ında editörler yeniden çizilince + kural açılış olayıyla (`isReady`) tekrar çalışır; o anda form verisi güncel değildir (`form.getEditor` popup + editörünü döndürmez) ve tarif Yarım Gün'ü eski hâliyle okuyup kilidi geri kapatırdı. Kural bu çalışmada + değeri grid'in düzenlenen satırından (`editor.component.cellValue`) okur; form sayfasında form verisinden. +- **Dilimin script'i yoktur.** Form sayfası script'li bir editör değişince `formData`'yı baştan yazar; bu sırada + açılır liste temizlenip yeniden dolar ve script'i olsaydı kendini tetikleyip sonsuz döngüye girerdi. + Tutarlılığı prosedür sağlar: yarım gün değilse dilim silinir, yarım günde boş dilim `Morning` olur. +- **İzin Türü düz bir lookup'tır**, cascade kullanılmaz: bool ebeveyn `false` iken çocuğu kilitler, tarih + değişince değeri silerdi. + +#### 5.2 Yıllık hak ve bakiye (`Hr_V_LeaveBalanceYear`) + +| Değer | Formül | +| --- | --- | +| Hak ediş tarihi | Kıdem başlangıcı + n yıl (n = 1, 2, …), bugün ve (varsa) işten çıkış tarihine kadar | +| Hak edilen | n ≤ 5 → `AnnualDays1To5`; 6 ≤ n ≤ 14 → `AnnualDays5To15`; n ≥ 15 → `AnnualDays15Plus`. Hak ediş tarihindeki yaş ≤ 18 ya da ≥ 50 ise en az `MinDaysYoungOld` | +| Kullanılan / bekleyen | Yıllık izinden düşen türdeki onaylı / onay bekleyen taleplerin günü; talep başlangıcının düştüğü hak ediş dönemine yazılır | +| 0. yıl | Düzeltmelerin toplamı ve ilk hak edişten önce başlayan talepler | +| Kalan | Σ(hak edilen + düzeltme) − Σ kullanılan (devirli) | +| Kullanılabilir | Kalan − onay bekleyen | + +#### 5.3 Kayıt sonrası (`Hr_S_LeaveRequestAfterSave`) + +Her ekleme/güncellemede (Workflow kararı dahil) çalışır; `THROW` kaydı geri alır. + +1. Çalışan adı, departman, pozisyon kullanıcı kartından; talep no `IZN-YYYY-00001`. (İK formunda çalışan seçilince departman ve pozisyon formda da hemen dolar: Çalışan lookup'ı iki kolonu döndürür, `copy` tarifi yazar.) +2. Müdür (§2.3 karar 2) bulunur → `ManagerIds`, `ManagerUserNames`. Bulunamazsa: çalışanın pozisyonunun üst pozisyonu yoksa (Genel Müdür) `RequiresManagerApproval = 0` yazılır ve müdür adımı atlanır; değilse ve talep müdür adımına kadar ise `THROW 51110` (yapılandırma eksik). +3. Müdür ekranından izinsiz geçiş önceki duruma geri alınır. +4. Çalışanın yeni talebi `Müdür Onayı`'na (müdür adımı atlanıyorsa `İK Onayı`'na) alınır; adıma girerken onaycı yazılır (müdür adımı → `ManagerUserNames`, İK adımı → İzin Talepleri akışının "İK Onayı" düğümü). +5. Gün sayısı hesaplanır. +6. Talep sonuçlanmamışsa doğrulanır: + +| Kod | Kural | +| --- | --- | +| 51111 | Tür cinsiyeti çalışana uymuyor | +| 51112 | Tür yarım güne izin vermiyor | +| 51113 | Yarım günde başlangıç ve bitiş aynı gün olmalı | +| 51114 | Tür belge istiyor, belge yok | +| 51115 | Aralıkta çalışma günü yok | +| 51116 | Reddedilmemiş başka bir talep ya da talebe bağlı olmayan istirahat aynı güne düşüyor (aynı günün iki ayrı yarısı serbest) | +| 51117 | Yıllık izinden düşen türde gün > kullanılabilir bakiye, ya da türün yıllık sınırı aşılıyor — tür `Block` ise; `Warn` ise kayıt yapılır, uyarı `BalanceWarning`'e yazılır | +| 51118 | Talebin (yeni ya da eski) tarihleri kapalı puantaj dönemine düşüyor — ekleme, düzeltme, karar ve silme reddedilir (`Hr_F_TimesheetPeriodClosed`; eski tarihleri `Hr_S_LeaveRequestGuard` denetler) | +| 51119 | Tarihler çalışanın işe giriş – işten çıkış aralığının dışında | + +7. Rapor (`Code = Sick`) türünde talep **onaylandığında** istirahat satırı açılır/güncellenir; reddedilen, onay bekleyen ya da türü değişen talebin istirahati kalkar. Rapor türü dışındaki talebin gün sayısı rapora denk gelen günleri saymaz (`Hr_F_LeaveNetDays`); rapor değişince çalışanın diğer taleplerinin gün sayısı yenilenir (`Hr_S_LeaveDaysRefresh`). +8. Silinen talep (silme sonrası komut aynı prosedürü çağırır): bağlı istirahat kalkar, puantaj yeniden hesaplanır. +9. Durum bildirim taşıyan bir değere geçtiyse bir kez bildirim gider, `LastNotifiedStatus` güncellenir. +10. Puantaj: talebin günleri yeniden hesaplanır; tarihi değişen talebin eski günlerini hesap kendisi aralığa katar. + +#### 5.4 Satır koruması (`Hr_S_LeaveRequestGuard`, before-command) + +| Aktör | Kural | +| --- | --- | +| Çalışan | Yalnız kendi talebi (`51100`); durum `Onaya Gönderildi`/`Müdür Onayı` değilse düzeltme/silme yok (`51101`) | +| Müdür | Silemez (`51102`); `ManagerIds` içinde olmalı (`51103`); talep `Müdür Onayı`'nda olmalı (`51104`) | +| İK | Serbest | +| Hepsi | Talebin kayıttaki (eski) tarihleri kapalı puantaj dönemine düşüyorsa düzeltme/silme yok (`51118`) | + +Alan kilidi: persona ekranlarında çalışanın/müdürün değiştirmemesi gereken alanların yazma yetkisi +`App.Hr.LeaveRequest.Create/.Update`'e bağlıdır; sunucu yetkisi olmayan alanı düşürür. Bu yüzden +çalışan/müdür rolüne İzin Talepleri'nin `.Create/.Update` yetkisi verilmez. + +#### 5.5 Rapor ↔ izin (tek kayıt) + +| Nereden | Ne olur | +| --- | --- | +| İzin talebi, tür Rapor | Onayda `Adm_T_UserSickLeave` satırı açılır (`SickLeaveId`); onaylı talep güncellenince güncellenir, silinince/reddedilince kalkar | +| Sağlık Kartı › İstirahat Raporları ya da kullanıcı detayı › İstirahatler | `Hr_S_LeaveSickLeaveSync`: onaylı Rapor talebi açılır (onay akışına girmez), güncellemede tarih/gün, silmede (silme sonrası komut aynı prosedürü çağırır) talep kalkar. Rapora denk gelen yıllık izin günleri bakiyeye döner. Kapalı puantaj ayına düşen rapor kaydedilmez (`51120`). Kiracıda `Sick` kodlu tür yoksa eşleme yapılmaz | +| Çalışma Takvimi | Takvim satırı kaydedilince denk gelen taleplerin gün sayısı yeniden hesaplanır (`Hr_S_WorkCalendarAfterSave`) | + +#### 5.6 Onay akışı (Grid Workflow) + +`Onaya Gönderildi` (Start) → `Müdür Onayı Gerekli mi?` (Compare, `RequiresManagerApproval = 1`) → +evet: `Müdür Onayı` (Approval, `@ManagerUserNames`) / hayır: doğrudan `İK Onayı` (Approval, seed'de +`system@sozsoft.com`) → `Onaylandı` (End); iki onay adımının reddi → `Reddedildi` (End). +Karşılaştırma düğümü yalnız İzin Talepleri akışındadır (akış İK grid'inden eklenen kayıtta orada başlar); +Ekibimin İzin Talepleri akışı başlatılmaz, yalnız müdür adımından ilerler. Akış iki ekranda aynı başlıklarla durur. İK onaycısı İzin +Talepleri › ListForm › Workflow › "İK Onayı" düğümünden değiştirilir (§2.4). + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Dal `App.Hr.Leave` → `App.Hr.LeaveRequest`, `App.Hr.LeaveBalance` +(altında `LeaveBalanceAdjustment`, `LeaveBalanceYear`). Kökte menüsüz `App.Hr.MyLeaveRequest`, +`App.Hr.MyLeaveBalance`, `App.Hr.TeamLeaveRequest`. Ayar: `App.HrSettings` › `App.HrSettings.Leave` +(Administration grubu, `App.Setting` altında). Her ekranda `.Create/.Update/.Delete/.Export/.Import/.Note`. +**Hiçbir yetki role otomatik atanmaz.** + +| Rol | Verilecek yetkiler | +| --- | --- | +| Tüm çalışanlar | `App.Hr.MyLeaveRequest` (+ `.Create/.Update/.Delete`), `App.Hr.MyLeaveBalance` | +| Müdürler | Yukarıdakiler + `App.Hr.TeamLeaveRequest` (+ `.Update` — Workflow kararı güncelleme yetkisi ister) | +| İK | `App.Hr.Leave` dalının tamamı + `App.HrSettings.Leave` | + +Widget'lar liste okuma yetkisiyle görünür (İzinlerim `App.Hr.MyLeaveRequest`, Ekibimin İzinleri `App.Hr.TeamLeaveRequest`). + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `AbpUsers` | Çalışan, kıdem, doğum tarihi, cinsiyet, departman/pozisyon; onaycı kullanıcı adları | +| `Hr_T_JobPosition` / `Hr_T_Department` | Departman müdürü çözümü | +| `Hr_T_LeaveType` | Tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı) | +| `Hr_T_WorkCalendar` | Tatil ve yarım günler | +| `AbpSettings` / `Sas_H_SettingDefinition` | Çalışma günleri ve kademeler | +| `Adm_T_UserSickLeave` | Rapor eşlemesi | +| Puantaj ve Devam Takibi | `Hr_S_LeaveRequestAfterSave` sonunda talebin günleri `Hr_S_TimesheetCalculate` ile yeniden hesaplanır: onaylı izin İzinli, rapor Raporlu gün olur; ücretli izne denk gelen tatil İzinli değil tatil, ücretsiz izin hafta sonu dahil İzinli yazılır. Tarihi değişen ya da silinen talebin eski günleri aynı işlemde düzelir (Puantaj ve Devam Takibi bölümü §7.1). Kapalı puantaj ayına düşen talep değiştirilemez; onay bekleyen talebi olan ay kapatılamaz. Çalışma günü ayarları puantajda hafta tatilini de belirler | +| Bildirimler | `IzinTalebiOnayBekliyor` (müdür / İK onaycısı), `IzinTalebiSonuclandi` (çalışan); kurallar `Custom` + `UiActivity`/`UiToast`. Metinler `App.Hr.Leave.Notification.{Approval,Result}.{Subject,Message}` (TR), yer tutucular `[Employee]`, `[LeaveType]`, `[StartDate]`, `[EndDate]`, `[Days]`, `[Status]`. Yazan: `Hr_S_LeaveNotify` | + +--- + +### 8. Akış örneği + +1. İK Ayarlar › İnsan Kaynakları › İzin'de Cumartesi'yi çalışma günü yapar (gerekirse); eski çalışanlar için İzin Bakiyeleri › Bakiye Düzeltmeleri'ne sistem öncesi kullanılan günleri eksi olarak girer. +2. Muhasebe Şefi panodaki **İzinlerim** widget'ında kalan 18 günü görür, **İzin Talebi Oluştur** ile 3 günlük yıllık izin açar. +3. Gün kayıtta 3 hesaplanır, talep `Müdür Onayı`'na düşer, Muhasebe Müdürü bildirim alır. +4. Müdür **Ekibimin İzinleri** → Onay Bekleyenler'den talebi seçip **Onayla** der → talep `İK Onayı`'na geçer, İK onaycısı bildirim alır. +5. İK İzin Talepleri'nde onaylar → `Onaylandı`; çalışan bildirim alır, bakiye 15'e iner. +6. Çalışan rapor alır, Rapor türünde talep açıp raporu ekler → Sağlık Kartı › İstirahat Raporları'nda görünür; aynı onay akışından geçer. +7. Sağlık birimi başka bir raporu doğrudan Sağlık Kartı'na girer → İzin Talepleri'nde onaylı Rapor talebi olarak görünür. + +--- + +### 9. Sık sorulanlar + +**"Departman müdürü bulunamadı" hatası.** Çalışanın kullanıcı kartında departman ve pozisyon dolu olmalı; departmanın en üst pozisyonunda (ya da üst pozisyonlarda) aktif bir kullanıcı bulunmalı (§5.3 adım 2). Üst pozisyonu olmayan çalışan (Genel Müdür) bu hatayı almaz; talebi doğrudan İK onayına gider. + +**Genel Müdür'ün talebini kim onaylar?** Müdür adımı atlanır, yalnız İK onaylar (§2.3 karar 9). + +**Gün sayısı beklenenden az.** Hafta sonu, ayarlarda kapalı gün ve Çalışma Takvimi tatilleri sayılmaz; arife 0,5 sayılır. + +**Bakiye çok yüksek görünüyor.** Devirli hesap kıdem başlangıcından bugüne bütün yılları sayar; sistem öncesi kullanılan izin Bakiye Düzeltmeleri'ne eksi olarak girilmelidir. + +**Bakiyem/İzinlerim'de kıdem uyarısı.** Kullanıcı kartında Kıdem Başlangıç ya da İşe Giriş tarihi yok. + +**Talebimi değiştiremiyorum.** Müdür karar verdikten sonra çalışan değiştiremez/silemez (`51101`); İK ile görüşülür. + +**Müdür Onayla butonunu görmüyor.** Rolünde `App.Hr.TeamLeaveRequest.Update` olmalı; talep `Müdür Onayı`'nda ve kullanıcı o departmanın müdürü olmalı. + +**İK onaycısı nasıl değişir?** İzin Talepleri › ListForm › Workflow › "İK Onayı" düğümü. Ekibimin İzin Talepleri'ndeki aynı düğüm akışı ilerletir; onaycı kayda İzin Talepleri düğümünden yazılır. + +**Bildirim gelmiyor.** Kiracıda `IzinTalebiOnayBekliyor` / `IzinTalebiSonuclandi` tipi ve `Custom` kuralları olmalı (yeni kiracıya kopyalanır, mevcut kiracıda Administration › Bildirimler'den eklenir). + +**Kullanıcı detayındaki İstirahatler'den girilen rapor izinlere düşmüyor.** O ekranın kancaları C# seeder'dadır (`ListFormSeeder_Administration`); daha önce kurulmuş bir veritabanında ekran yeniden kurulmadıkça kanca yoktur. Sağlık Kartı ekranı wizard'dır ve migrate ile güncellenir. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_LeaveRequest.sql`, `Hr_T_LeaveBalanceAdjustment.sql`, `Hr_T_LeaveType.sql` (`BalanceExceedAction`) | Tablolar | +| `…/Hr_F_HrSetting.sql`, `Hr_F_LeaveWorkDays.sql` | Ayar okuma, gün sayısı | +| `…/Hr_V_LeaveBalanceYear.sql`, `Hr_V_LeaveSummary.sql` | Bakiye görünümleri | +| `…/Hr_S_LeaveRequestAfterSave.sql`, `Hr_S_LeaveRequestGuard.sql`, `Hr_S_LeaveNotify.sql`, `Hr_S_LeaveSickLeaveSync.sql` | Prosedürler | +| `configs/seeds/wizard/{LeaveRequest,MyLeaveRequest,TeamLeaveRequest,LeaveBalance,LeaveBalanceAdjustment,LeaveBalanceYear,MyLeaveBalance}.json` | 7 wizard; `LeaveType.json` (alan), `HealthCardSickLeave.json` (kancalar) | +| `configs/seeds/data/App.DeveloperKit.CustomComponents/{23744edc-eda9-512e-8079-fe2e8e5fd2a8,3b7b16c6-aa96-5765-8e19-fe5e727feb52}.json` | `MyLeaveWidget`, `TeamLeaveWidget` | +| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json`, `App.SettingDefinitions.json`, `App.Notifications.Notification{Types,Rules}.json`, `App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json`, `App.Hr.LeaveType.json` | Seed satırları | +| `api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs` | `@Kolon` onaycı | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` | Kullanıcı detayı istirahat kancaları | +| `ui/src/views/admin/listForm/workflow/WorkflowCriteria.tsx` | Tasarımcıda alan onaycısı seçeneği | +| `ui/src/views/admin/user-management/LeaveTab.tsx`, `Details.tsx` | İzinler sekmesi | + +Kurulum: DB Migrate (SQL nesneleri, ekranlar `WizardDataSeeder`, satırlar `ListFormSeedDataApplier`), +ardından rollere yetki (§6). Ayar tanımları uygulama yeniden başlayınca ayar ekranında görünür. + +Geri alma: Wizard Manager'dan 7 wizard silinir (alt formlar önce); tabloları düşürmek onayda seçilirse olur. +Widget bileşenleri ve pano kayıtları, bildirim tip/kural satırları, ayar tanımları, `Hr_F_*`/`Hr_V_*`/`Hr_S_Leave*` +nesneleri elle kaldırılır. `BalanceExceedAction` kolonu kalır (kayıpsız ekleme geri alınmaz). + + +## Puantaj ve Devam Takibi (`App.Hr.Attendance`) + +Günlük giriş/çıkış hareketlerinden (PDKS, Excel aktarımı, elle giriş) çalışan × gün puantajı; +personel bazlı aylık puantaj, dönem kapanışı ve PDKS'nin hareket gönderdiği uç. Kişi eşlemesi kullanıcı +kartındaki PDKS Kart No / Sicil No alanlarıyladır. +İzin Yönetimi (onaylı izin → İzinli), Sağlık Kartı (istirahat → Raporlu), Çalışma Takvimi (resmî +tatil / arife) ve Vardiyalar (saat, mola, tolerans) puantajın girdisidir. Çalışan kendi puantajını +**Intranet › Dashboard**'daki **Puantajım** widget'ından izler; İK menüsü İK içindir. Wizard ekranları, +SQL nesneleri, custom component widget'ı, Custom Endpoint ve zamanlanmış işle kuruludur. Çerçeve dışında +tek ek vardır (kullanıcı onayıyla): kullanıcı detayındaki **Puantaj** sekmesi. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Çalışan | Seçtiği ayın net saatini, geç kalma/erken çıkış dakikasını, fazla mesaisini, devamsız/izinli/raporlu günlerini ve yıllık toplamı (270 saatlik fazla mesai sınırıyla) görür | Intranet panosu: **Puantajım** widget'ı → Puantajım (aylar) → ayın günleri · Profil › Puantajım (aylık puantaj salt okunur) | +| İK | Hareketleri izler/düzeltir, elle takip edilen çalışanın gelmediği günü işaretler, aylık puantajı izler, ayı yeniden hesaplar ve kapatır, çalışanın PDKS Kart No'sunu kullanıcı kartına (İş sekmesi) girer, toleransı ve fazla mesai kurallarını ayarlar | İK › Puantaj ve Devam Takibi · Ayarlar › İnsan Kaynakları › Puantaj · Kullanıcı detayı › Puantaj | +| PDKS (servis kullanıcısı) | Kart okutmalarını toplu gönderir | `POST /api/app/custom-endpoint/hr/attendance/` | + +Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur. + +--- + +### 2. Analiz ve kararlar + +#### 2.1 Talep + +> Human Resources → Puantaj ve Devam Takibi modülü: günlük hareketler, personel bazlı aylık puantaj. +> Intranet › Dashboard'da aylık puantajıma ulaşabileceğim, ilgili ayın durumunu ve yıllık toplamı gösteren +> widget (sol kolon, anket tarafı). Kolonlar: ilk giriş, son çıkış, net çalışma süresi, mola düşümü, geç +> kalma (dk), erken çıkış (dk), fazla mesai (saat), gün tipi (çalışma, hafta tatili, resmî tatil, izinli, +> raporlu, devamsız). Tolerans vardiya bazında (ör. 10 dk), ayarlardan dinamik. Haftalık 45 saati aşan +> çalışma fazla mesaidir, ücreti %50 zamlıdır (4857 md. 41), yıllık üst sınır 270 saat; ayarlardan +> yönetilir. Veri elle yazılabilir ya da PDKS'den akabilir. Kullanıcı detayında İzinler gibi bir Puantaj +> sekmesi. Diğer modüllerle core koda dokunmadan entegre olmalı. + +#### 2.2 Depodan okunanlar (sorulmadı) + +- Vardiya `Hr_T_Shift` (`StartTime`/`EndTime` `SS:dd` metin, `BreakMinutes`, `WorkingHours`, gece vardiyası); çalışanın vardiyası `AbpUsers.ShiftId`. +- Tatiller `Hr_T_WorkCalendar` (`Holiday` / `HalfDay`, `FREQ=YEARLY`); hafta tatili İzin Yönetimi'nin `App.HrSettings.Leave.Work{Gün}` ayarları. +- Onaylı izin `Hr_T_LeaveRequest.ApprovalStatus = 'Onaylandı'`; rapor `Adm_T_UserSickLeave`. +- İstihdam `AbpUsers.HireDate` / `TerminationDate`; departman/pozisyon `DepartmentId` / `JobPositionId`. +- Kullanıcı kartında (İş sekmesi) PDKS Kart No (`AbpUsers.PdksCardNo`) ve Sicil No (`RegistrationNo`) alanları var; ayrı kart tablosu açılmadı. +- Zamanlanmış işin saklı yordamı parametresiz çağrılır (`PlatformBackgroundWorker`); Custom Endpoint gövdesindeki dizi ham JSON metni olarak bağlanır. + +#### 2.3 Keşif turu cevapları + +| # | Soru | Seçilen | +| --- | --- | --- | +| 1 | Veri modeli | Ham hareket (`Hr_T_AttendanceLog`) + hesaplanan gün (`Hr_T_Timesheet`); İK günü elle düzeltebilir, düzeltilen gün yeniden hesapta ezilmez | +| 2 | Tolerans yeri | Vardiyada (`LateToleranceMinutes`, `EarlyLeaveToleranceMinutes`), boşsa Ayarlar › Puantaj (10 dk) | +| 3 | Geç kalma dakikası | Tolerans aşılırsa dakikanın tamamı yazılır, aşılmazsa 0 | +| 4 | Fazla mesai | Haftalık (Pzt–Paz) birikim 45 saati aştığı günden itibaren aşan kısım o günlere; hafta tatili ve resmî tatildeki çalışmanın tamamı; yıllık 270 saati aşan satır işaretlenir (engellemez) | +| 5 | PDKS | Excel import + API ucu (Custom Endpoint); kişi eşlemesi kullanıcı kartındaki PDKS Kart No, Sicil No ya da kullanıcı adıyla | +| 6 | Mola | `MAX(vardiya molası, gün içi okutulan çıkış→giriş aralıkları)` | +| 7 | Hesap zamanı | Hareket kaydında (o hafta) + gece işi (okutmasız günler) + dönem kaydı (ay) | +| 8 | Kapanış | İK ayı kilitler, onay akışı yok; müdür ekranı/widget'ı yok | +| 9 | Kullanıcı detayı sekmesi | Core istisnası onaylandı (`Details.tsx` + `TimesheetTab.tsx`, İzinler sekmesi emsali) | +| 10 | Elle takip (üretim sırasında) | Elle takipte yalnız gelinmeyen gün yazılır; yazılmayan iş günü "geldi" kabul edilir | + +#### 2.4 Üretimde verilen kararlar + +| Konu | Karar | Neden | +| --- | --- | --- | +| Takip türü | Çalışan bazında otomatik: kullanıcı kartında PDKS Kart No'su olan çalışan **ilk PDKS/aktarım okutmasının gününden itibaren** okutmayla takip edilir (okutmasız iş günü Devamsız); diğerleri elle takip edilir (kayıtsız iş günü vardiya saatleriyle `IsAssumed`). Elle girilen hareket takip türünü değiştirmez | Ayrı bir ayar gerektirmez; kartın sonradan verilmesi geçmiş günleri devamsıza çevirmez | +| Gün sınırı | Hareketin iş günü vardiya bitişi ile bir sonraki başlangıç arasındaki boşluğun ortasından ayrılır (`Hr_V_AttendanceShift.DayOffset`) | Gece vardiyasının 23:50 okutması vardiyanın başladığı ertesi güne yazılır | +| Okutma yönü | `In` / `Out` / `Auto`; `Auto` sıraya göre giriş/çıkış sayılır | PDKS'lerin çoğu yön göndermez | +| Elle düzeltme | Günlük Puantaj'da kaydedilen gün `IsManual = 1` olur; otomatiğe dönmek için satır silinir (yeniden hesap aynı günü kurar) | Ekrandan "elle mi" bilgisini ayrıca istemeden yeniden hesabın düzeltmeyi ezmesini önler | +| Kapalı dönem | Hesap kapalı ayın günlerini yazmaz, yalnız haftalık birikime alır; ekrandan gelen hareket/gün değişikliği `THROW` ile geri alınır; PDKS/gece işi okutmayı `ClosedPeriod` hatasıyla işaretler | PDKS gönderimi tek bir eski okutma yüzünden durmasın | +| Kurulum sırası | Vardiya çözümü view'dadır (`Hr_V_AttendanceShift`) | SQL nesneleri dosya adına göre kurulur; `Hr_F_*` fonksiyonları `Hr_T_*` tablolarından önce oluşur | +| Gece işi kapsamı | `Scope = Host ve Kiracılar`; prosedür veritabanındaki bütün kiracıları işler ve aynı gün işlenen kiracıyı dönemin `NightlyAt` değeriyle atlar | Saklı yordam kiracı parametresi almaz | +| İzin entegrasyonu | `Hr_S_LeaveRequestAfterSave` ve `Hr_S_LeaveSickLeaveSync` sonunda talebin/raporun günleri yeniden hesaplanır | Onaylı izin ve rapor anında puantaja düşer; çekirdek koda dokunulmaz | +| Aylık özet anahtarı | `PeriodKey = {EmployeeId}-{YYYYMM}` hem view'ın `Id`'si hem günlük satırın kolonudur | Alt form ilişkisi tek alanla kurulur | +| Widget sınıfları | Bileşen sınıfları `className` literalleriyle yazılır, koşullu kısım dizge birleştirmeyle eklenir | Safelist üreteci şablon dizgisindeki ifadeyi sınıf sanır | + +#### 2.5 Varsayılan kalanlar + +- Varsayılan vardiya 08:00–18:00, mola 60 dk (vardiyası olmayan çalışan için, ayarlarda değişir). +- İzinli/raporlu gün haftalık 45 saat birikimine 0 katkı verir; o gün okutma varsa net süre birikime girer. +- Yarım gün izinli günde geç/erken yazılmaz; arifede (`HalfDay`) vardiya süresinin yarısında biter. +- Yalnız giriş okutması olan gün `IsIncomplete` (Eksik Okutma) işaretlenir, net süre 0'dır. + +--- + +### 3. Menü ve ekranlar + +#### 3.1 İK menüsü + +`İnsan Kaynakları › Puantaj ve Devam Takibi` (`App.Hr.Attendance`, sıra 15, `FcAlarmClock`) — yalnız İK. + +| Sıra | Menü (TR / EN) | `ListFormCode` | Kaynak | Alt formlar | Widget'lar | +| --- | --- | --- | --- | --- | --- | +| 1 | Günlük Hareketler / Attendance Events | `App.Hr.AttendanceLog` | `Hr_T_AttendanceLog` | — | Bugün · PDKS (bu ay) · Manuel (bu ay) · Hatalı | +| 2 | Günlük Puantaj / Daily Timesheet | `App.Hr.Timesheet` | `Hr_T_Timesheet` | — | Devamsız gün · Geç kalınan gün · Fazla mesai saati · Eksik okutma (bu ay) | +| 3 | Aylık Puantaj / Monthly Timesheet | `App.Hr.TimesheetMonthly` | `Hr_V_TimesheetMonthly` (salt okunur) | `App.Hr.Timesheet` (`Id → PeriodKey`) | Çalışan · Fazla mesai · Devamsız gün (bu ay) · Yıllık sınırı aşan | +| 4 | Puantaj Dönemleri / Timesheet Periods | `App.Hr.TimesheetPeriod` | `Hr_T_TimesheetPeriod` | — | Açık · Kapalı · Toplam | + +Görünümler: hepsi Grid, Card, Pivot, Chart. Günlük Puantaj'da ekleme yoktur (günleri hesap kurar). +Koşullu biçim: gün tipi (Devamsız kırmızı, Raporlu mor, İzinli mavi, tatiller gri), geç/erken/fazla +mesai > 0, hareket hatası, aylık satırda yıllık sınırın aşılması (satır). + +#### 3.2 Çalışana ait ekranlar (menüsüz) + +| Ekran | `ListFormCode` | Satır süzmesi | Yapılabilen | +| --- | --- | --- | --- | +| Puantajım | `App.Hr.MyTimesheet` | `EmployeeId = @USERID` (`Hr_V_TimesheetMonthly`) | Ayları görür; detayda ayın günleri | +| Puantaj Günlerim | `App.Hr.MyTimesheetDay` | `EmployeeId = @USERID` (`Hr_T_Timesheet`) | Puantajım'ın sekmesi (`Id → PeriodKey`), salt okunur | + +#### 3.3 Intranet › Dashboard widget'ı + +Sol kolon (`Column: 0`), İzinlerim'in (35/36) altında; kayıt `data/App.DeveloperKit.IntranetWidgets.json`. + +| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Buton | +| --- | --- | --- | --- | --- | +| `my-timesheet` · 37 | `MyTimesheetWidget` | `App.Hr.MyTimesheet` | Ay seçici (varsayılan içinde bulunulan ay); net saat, çalışılan gün, fazla mesai, geç kalma dk, erken çıkış dk, devamsız gün; izinli/raporlu/tatil günü; yıl toplamı (net saat, geç kalma, devamsız) ve fazla mesai / yıllık sınır çubuğu | Puantajım | + +Bileşen code modunda, rotasızdır; veriyi Puantajım ekranının sorgusundan okur (`GET /api/app/list-form-select/select`). + +#### 3.4 Kullanıcı detayı › Puantaj + +`ui/src/views/admin/user-management/TimesheetTab.tsx`: içinde bulunulan yılın sekiz kartı (çalışma günü, +net saat, fazla mesai — yıllık sınırı aşınca kırmızı —, geç kalma, erken çıkış, devamsız, izinli, raporlu), +altında kullanıcıya süzülmüş **Aylık Puantaj**, **Günlük Puantaj** ve **Günlük Hareketler** listeleri. Her +parça kendi ekran yetkisiyle görünür; yeni hareket satırının `EmployeeId`'si süzgeçten dolar. + +#### 3.5 Ayarlar + +Ayarlar › İnsan Kaynakları › Puantaj (`App.HrSettings` › `App.HrSettings.Attendance`, sağlayıcılar `T|G|D`): + +| Kod | Varsayılan | Kullanım | +| --- | --- | --- | +| `App.HrSettings.Attendance.LateToleranceMinutes` | 10 | Vardiyada tolerans yoksa | +| `App.HrSettings.Attendance.EarlyLeaveToleranceMinutes` | 10 | Vardiyada tolerans yoksa | +| `App.HrSettings.Attendance.WeeklyLimitHours` | 45 | Haftalık fazla mesai sınırı | +| `App.HrSettings.Attendance.OvertimeRate` | 1.5 | Zamlı fazla mesai saati çarpanı (Aylık Puantaj) | +| `App.HrSettings.Attendance.AnnualOvertimeLimitHours` | 270 | Yıllık sınır (işaret, widget çubuğu) | +| `App.HrSettings.Attendance.DefaultShiftStart` / `DefaultShiftEnd` | 08:00 / 18:00 | Vardiyası olmayan çalışan | +| `App.HrSettings.Attendance.DefaultBreakMinutes` | 60 | Vardiyası (ya da vardiya molası) olmayan çalışan | + +Hafta tatili İzin Yönetimi'nin çalışma günü ayarlarından (`App.HrSettings.Leave.Work{Gün}`) okunur. + +--- + +### 4. Veri modeli + +| Tablo / nesne | Kolonlar | Not | +| --- | --- | --- | +| `AbpUsers` (mevcut) | `PdksCardNo`, `RegistrationNo`, `ShiftId`, `HireDate`, `TerminationDate` | Kişi eşlemesi, vardiya, istihdam aralığı | +| `Hr_T_AttendanceLog` | `EmployeeId` (boş olabilir), `CardNo`, `EventTime` (yerel saat), `Direction` (In/Out/Auto), `Source` (Manual/Pdks/Import), `DeviceCode`, `Note`, `WorkDate` (hesaplanır), `IsProcessed`, `ProcessError` (UnknownCard/ClosedPeriod) | `IsProcessed = 0` satırları işlenmeyi bekler | +| `Hr_T_Timesheet` | `EmployeeId`, `WorkDate`, `PeriodYear`, `PeriodMonth`, `PeriodKey`, `ShiftId`, `DayType` (Work/WeeklyOff/Holiday/Leave/Sick/Training/Absent), `LeaveTypeId` (izinli/raporlu günün türü), `TrainingId` (eğitim günü), `FirstIn`, `LastOut`, `BreakMinutes`, `NetMinutes`, `NetHours`, `LateMinutes`, `EarlyLeaveMinutes`, `OvertimeHours`, `IsManual`, `IsIncomplete`, `IsAssumed`, `Note`, `CalculatedAt` | Çalışan × gün tek etkin satır | +| `Hr_T_TimesheetPeriod` | `PeriodYear`, `PeriodMonth`, `Status` (Open/Closed), `CalculatedAt`, `ClosedAt`, `ClosedById`, `NightlyAt`, `Note` | Kiracıda yıl+ay tekil (prosedür denetler) | +| `Hr_T_Shift` (+) | `LateToleranceMinutes`, `EarlyLeaveToleranceMinutes` | Vardiyalar ekranında düzenlenir | +| `Hr_V_AttendanceShift` | Çalışanın dakika cinsinden vardiyası, mola, toleranslar, `DayOffset` | Varsayılanlar ayardan | +| `Hr_V_TimesheetMonthly` | Çalışan × ay toplamları, `UnpaidLeaveDays` (ücretsiz türdeki izinli gün — bordroda eksik gün), `TrainingDays`, `OvertimePaidHours`, `YearOvertimeHours`, `AnnualOvertimeLimit`, `IsOverAnnualLimit`, `PeriodStatus` | `Id = PeriodKey` | + +Entity yoktur (wizard tabloları); `sql/object/`. + +--- + +### 5. İş kuralları ve hesaplar + +#### 5.1 Prosedürler + +| Nesne | Ne yapar | Çağıran | +| --- | --- | --- | +| `Hr_S_TimesheetCalculate @TenantId, @EmployeeId, @From, @To, @ActorId` | Aralığı tam haftalara genişletip (bugünle sınırlı) çalışan × gün satırlarını kurar/günceller; kapalı ayı yazmaz | Aşağıdakilerin hepsi, izin ve rapor prosedürleri | +| `Hr_S_AttendanceProcess @FailOnClosed` | İşlenmemiş hareketlerde kart → çalışan, iş günü, hata; etkilenen günleri (eski + yeni) yeniden hesaplar | Günlük Hareketler kayıt/silme, PDKS ucu, gece işi | +| `Hr_S_AttendanceImport @TenantId, @UserId, @Items` | PDKS gönderimini (`CardNo`, `RegistrationNo` ya da `UserName`; `EventTime`, `Direction`, `DeviceCode`) yazar, tekrarı atlar; `Received/Inserted/Skipped/Errors` döner | Custom Endpoint | +| `Hr_S_TimesheetPeriodAfterSave @PeriodId, @ActorId` | Yıl/ay doğrulama ve tekillik; açık dönemde ayı yeniden hesaplar; kapatmada son hesap + kilit | Puantaj Dönemleri kayıt | +| `Hr_S_TimesheetNightly` | Kart numarası sonradan girilen "Kart tanımsız" okutmaları yeniden kuyruğa alır ve işler; her kiracı için ayın dönemini açar, dünün ayını ve kapanmamışsa önceki ayı hesaplar | Zamanlanmış iş `Timesheet Nightly` (02:00) | +| `Hr_F_WorkCalendarDayType @TenantId, @Day` | Güne düşen `Holiday` / `HalfDay` | Hesap | +| `Hr_F_TimesheetPeriodClosed @TenantId, @From, @To` | Aralığın değdiği aylardan biri kapalı dönem mi | İzin, rapor ve izin guard prosedürleri | +| `Hr_S_TrainingSync @TrainingId, @UserId, @ActorId` | Katılımcının (boşsa bütün katılımcıların) eğitim günlerini yeniden hesaplar, bağlı gelişim aksiyonunu tamamlar | Eğitimler ve Katılımcılar kayıt/silme | +| `Hr_S_WorkCalendarAfterSave @CalendarId, @ActorId` | Takvim satırına denk gelen izinlerin gün sayısını ve puantajı yeniden hesaplar | Çalışma Takvimi kayıt/silme | + +#### 5.2 Günün hesabı + +1. **Gün tipi** (öncelik sırasıyla): + 1. rapor (Sağlık Kartı istirahati; takvim günü, hafta sonu dahil) → `Sick`; + 2. onaylı **ücretsiz** izin (`LeaveType.IsPaid = 0`: ücretsiz izin, doğum izni; takvim günü) → `Leave`; + 3. takvim tatili → `Holiday`; ayarda çalışma günü değil → `WeeklyOff`; + 4. onaylı **ücretli** izin → `Leave` (ücretli izne denk gelen tatil izin günü değildir, 4857 md. 56 — izin gün sayısıyla aynı kural); yarım gün izinde okutma varsa `Work`; + 5. okutma var → `Work`; + 6. eğitime "Katıldı" işaretli katılımcı → `Training` (vardiya saatleriyle, `IsAssumed`); + 7. elle takip edilen çalışan → `Work` (`IsAssumed`, vardiya saatleri); geçmiş gün → `Absent`; kartlı çalışanın okutmasız bugünü yazılmaz. + + İzinli/raporlu günde `LeaveTypeId`, eğitim gününde `TrainingId` yazılır. İstihdam dışındaki okutmasız gün yazılmaz. +2. **İlk giriş / son çıkış**: ilk `In` (yoksa ilk okutma) / son `Out` (ilk girişten sonraysa). +3. **Mola** = `MAX(vardiya molası, ilk giriş–son çıkış arasındaki çıkış→giriş aralıkları)`, brüt süreyi aşamaz; elle düzeltilen günde girilen mola. +4. **Net** = son çıkış − ilk giriş − mola. +5. **Geç kalma** = ilk giriş − vardiya başlangıcı, tolerans aşılırsa tamamı; **erken çıkış** = vardiya bitişi (arifede yarı süre) − son çıkış, tolerans aşılırsa tamamı. Yalnız `Work` gününde; eğitim günü haftalık birikime çalışma gibi girer. +6. **Fazla mesai** = `WeeklyOff`/`Holiday` gününde net sürenin tamamı; diğer günlerde haftanın kümülatif netinin sınırı aştığı kısım (`max(0, kümülatif − sınır) − max(0, önceki kümülatif − sınır)`). +7. Kaynağı kalkan gün: tek çalışanlık hesap, artık hiçbir izin/rapor/katılımla örtüşmeyen `Leave`/`Sick`/`Training` günlerini (talebin tarihi değişti, rapor ya da katılım silindi) aralığa katar; eski günler aynı işlemde düzelir. +8. Aylık view: `OvertimePaidHours = OvertimeHours × OvertimeRate`; `YearOvertimeHours` ocaktan o aya birikim; `IsOverAnnualLimit` sınır aşımı. + +#### 5.3 Ekran komutları + +| Ekran | Komut | +| --- | --- | +| Günlük Hareketler | Ekle/düzenle/sil sonrası satır işlenmemiş işaretlenir → `Hr_S_AttendanceProcess 1` (kapalı dönemde kayıt geri alınır) | +| Günlük Puantaj | Düzenle/sil öncesi kapalı dönem kontrolü; düzenleme sonrası `IsManual = 1, IsAssumed = 0` ve günün haftası yeniden hesaplanır; silme sonrası gün otomatik yeniden kurulur | +| Puantaj Dönemleri | Kayıt sonrası `Hr_S_TimesheetPeriodAfterSave`; kapalı dönem silinemez; ayda onay bekleyen izin varsa kapatılamaz | + +Hata kodları: 51200 (kapalı döneme hareket), 51201 (kapalı dönemin günü), 51210 (PDKS gövdesi), 51220–51223 +(dönem; 51223 onay bekleyen izin), 51118 (kapalı döneme izin), 51120 (kapalı döneme rapor). + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Kök `App.Hr.Attendance` (sıra 9); dört ekran altında, her biri +`.Create/.Update/.Delete/.Export/.Import/.Note` ile. `App.Hr.MyTimesheet` (sıra 10) kökte, +`App.Hr.MyTimesheetDay` onun altında. Ayar yetkisi `App.HrSettings.Attendance` (`App.Administration` +grubu, `App.HrSettings` altında). Hiçbir yetki role otomatik atanmaz. + +| Rol | Yetkiler | +| --- | --- | +| Tüm çalışanlar | `App.Hr.MyTimesheet`, `App.Hr.MyTimesheetDay` (widget ve Puantajım) | +| İK | `App.Hr.Attendance` dalının tamamı, `App.HrSettings.Attendance` | +| PDKS servis kullanıcısı | `PDKS` rolü + `App.DeveloperKit.CustomEndpoints.Post` | + +--- + +### 7. Entegrasyonlar + +| Modül | Yön | Nasıl | +| --- | --- | --- | +| Kimlik › Kullanıcılar | → puantaj | PDKS Kart No / Sicil No kişi eşlemesi, vardiya, işe giriş/çıkış; kart numarası değişikliği gece işinde yansır | +| İzin Yönetimi | → puantaj | `Hr_S_LeaveRequestAfterSave` (kayıt, karar, silme) sonunda talebin günleri — tarihi değiştiyse eski günleri de — yeniden hesaplanır; onaylı izin `Leave` | +| Sağlık Kartı › İstirahatler | ↔ izin, → puantaj | `Hr_S_LeaveSickLeaveSync` (kayıt, silme) raporu onaylı Rapor talebine eşler, rapora denk gelen izin günlerini bakiyeye döndürür (`Hr_S_LeaveDaysRefresh`), günleri yeniden hesaplar; rapor `Sick` | +| Eğitimler | → puantaj | Katıldı işaretli katılımcının eğitim günleri `Training`; eğitim/katılımcı kaydı `Hr_S_TrainingSync` ile hemen yansır | +| Çalışma Takvimi | → izin, → puantaj | Tatil `Holiday`, arife `HalfDay` (yarım vardiya); takvim kaydı denk gelen izinlerin gün sayısını ve puantajı hemen yeniler (`Hr_S_WorkCalendarAfterSave`) | +| Vardiyalar / kullanıcı vardiyası | → puantaj | Saat, mola, tolerans; değişiklik gece işinde ya da dönem kaydında yansır | +| İzin ayarları | → puantaj | Hafta tatili günleri | +| PDKS | → hareket | Custom Endpoint `POST /api/app/custom-endpoint/hr/attendance/` (`data/App.DeveloperKit.CustomEndpoints.json`, `PermissionsJson`: rol `PDKS`) | +| Excel | → hareket | Günlük Hareketler import'u aynı kayıt yolundan (`InsertAfterCommand`) geçer; `Source` boş gelir ve `Import` yazılır | +| Intranet | ← puantaj | `my-timesheet` widget'ı | +| Kullanıcı detayı | ← puantaj | Puantaj sekmesi | + +#### 7.1 Çakışma kuralları (modüller birbirine zıt sonuç vermez) + +| Durum | Kural | Nerede | +| --- | --- | --- | +| Raporlu gün | Devamsız yazılmaz; `Sick` her şeyin önündedir (okutma olsa da) | `Hr_S_TimesheetCalculate` | +| Yıllık izin sırasında rapor | Rapora denk gelen izin günü izinden sayılmaz, bakiyeye döner; puantajda `Sick` | `Hr_F_LeaveNetDays`, `Hr_S_LeaveDaysRefresh` | +| Rapor talebi onay beklerken | Sağlık kartına ve puantaja düşmez; onayla istirahat kaydı oluşur, redde kalkar | `Hr_S_LeaveRequestAfterSave` | +| Ücretli izne denk gelen tatil | Puantajda `Holiday`/`WeeklyOff`; izin gün sayısına girmez (4857 md. 56) | hesap + `Hr_F_LeaveWorkDays` | +| Ücretsiz izin / doğum izni | Hafta tatili ve genel tatil dahil `Leave` (ücret doğmaz); aylıkta `UnpaidLeaveDays` | hesap + aylık view | +| Eğitime katılan | Okutması yoksa devamsız değil `Training`; okutması varsa `Work` | hesap | +| Kapalı puantaj ayı | İzin talebi ve rapor eklenemez/değiştirilemez/silinemez (51118, 51120); onay bekleyen izni olan ay kapatılamaz (51223) | guard + kayıt prosedürleri + dönem kaydı | +| İstihdam dışı | İzin tarihleri işe giriş – işten çıkış arasında olmalı (51119); puantaj istihdam dışında gün yazmaz | `Hr_S_LeaveRequestAfterSave`, hesap | +| Takvime sonradan girilen bayram | Denk gelen izinlerin gün sayısı ve puantaj hemen yenilenir | `Hr_S_WorkCalendarAfterSave` | + +PDKS gövdesi: + +```json +{ "Items": [ { "CardNo": "000123", "EventTime": "2026-10-05T08:02:00", "Direction": "In", "DeviceCode": "GATE-1" } ] } +``` + +`Items` dizi ya da JSON metni olabilir; `CardNo` yerine `UserName` gönderilebilir. Endpoint kaydı +kiracıya aittir (`CustomEndpoint` `IMultiTenant`): seed satırı host'a kurulur, kiracıda Developer Kit › +Custom Endpoints'ten aynı SQL ve parametrelerle eklenir. + +--- + +### 8. Akış örneği + +1. İK üretim çalışanlarının kullanıcı kartına (İş sekmesi) PDKS Kart No girer; ofis çalışanlarında alan boştur (elle takip). +2. PDKS her 5 dakikada okutmaları uca gönderir; **Günlük Hareketler**'e düşer, Günlük Puantaj o hafta için güncellenir. Tanımsız kart "Kart tanımsız" görünür; numara kullanıcı kartına girilince gece işi okutmayı işler. +3. Gece 02:00'de iş dünü kurar: kartlı çalışanın okutmasız iş günü Devamsız, elle takip edilen çalışanın günü vardiya saatleriyle Varsayılan çalışma. +4. Ofis çalışanı bir gün gelmez; İK **Günlük Puantaj**'da o günü Devamsız yapar (gün Elle olur). +5. Ay sonunda İK **Aylık Puantaj**'ı kontrol eder, yıllık sınırı aşanları görür; **Puantaj Dönemleri**'nde ayı Kapalı yapar. +6. Çalışan panodaki **Puantajım**'da ayını ve yıl toplamını görür, butonla aylarına ve günlerine iner. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Okutması olmayan çalışan neden hep "geldi" görünüyor?** Kullanıcı kartında PDKS Kart No yoksa (ya da henüz PDKS okutması gelmediyse) elle takip edilir; gelinmeyen gün Günlük Puantaj'da işaretlenir. İlk PDKS okutmasından itibaren okutmayla takip edilir. + +**Düzelttiğim gün neden yeniden hesapta değişmiyor?** Elle düzeltilen gün korunur. Otomatiğe döndürmek için satırı silin. + +**Vardiya/takvim/ayar değişti, puantaj eski.** Gece işi dünün ve önceki ayın günlerini yeniler; hemen yansıtmak için Puantaj Dönemleri'nde ilgili ayı kaydedin. + +**Kapalı aya PDKS okutması geldi.** Okutma `Kapalı dönem` hatasıyla kalır; dönem açılıp kaydedilirse hareket ekranından düzenlenerek işlenir. + +**Fazla mesai hafta tatilinde neden tamamı?** Talepte istenen kural (hafta tatili ve resmî tatilde çalışma fazla mesaidir); haftalık 45 saat birikimine bu günler katılmaz. + +**İzin talebinin tarihi değişti, eski günler ne olur?** Aynı kayıtta düzelir: tek çalışanlık hesap kaynağı kalmayan izinli/raporlu/eğitim günlerini aralığa katar. + +**Hasta raporu alan çalışan devamsız mı yazılır?** Hayır. Rapor günleri (hafta sonu dahil) `Raporlu`dur; aynı güne izin ya da okutma düşse bile rapor önce gelir. Yıllık izindeyken rapor alındıysa o günler izinden düşmez, bakiyeye döner. + +**Eğitimdeki çalışan devamsız görünüyor.** Katılımcı satırında durum "Katıldı" olmalıdır; "Katılmadı/Mazeretli" günler normal hesaplanır. + +**Çalışma Takvimi kaydı sonrası hangi günler yenilenir?** Satırın tarihleri (yıllık tekrarlıda bu yıl ve gelecek yıl). Tarihi değiştirilen satırın eski günleri gece işinde ya da dönem kaydında düzelir. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{AttendanceLog,Timesheet,TimesheetPeriod}.sql` | Tablolar | +| `configs/seeds/sql/object/Hr_T_Shift.sql` | Vardiya toleransı kolonları | +| `configs/seeds/sql/object/Hr_V_{AttendanceShift,TimesheetMonthly}.sql` | View'lar | +| `configs/seeds/sql/object/Hr_F_{WorkCalendarDayType,TimesheetPeriodClosed,LeaveNetDays}.sql` | Takvim günü türü, kapalı dönem, rapordan arınmış izin günü | +| `configs/seeds/sql/object/Hr_S_{TimesheetCalculate,AttendanceProcess,AttendanceImport,TimesheetPeriodAfterSave,TimesheetNightly}.sql` | Hesap ve tetikler | +| `configs/seeds/sql/object/Hr_S_{LeaveRequestAfterSave,LeaveRequestGuard,LeaveSickLeaveSync,LeaveDaysRefresh}.sql` | İzin/rapor → puantaj tetiği, kapalı dönem guard'ı, rapor → izin günü | +| `configs/seeds/sql/object/Hr_S_{TrainingSync,WorkCalendarAfterSave}.sql` | Eğitim ve takvim → puantaj tetiği | +| `configs/seeds/wizard/{LeaveRequest,MyLeaveRequest,HealthCardSickLeave,Training,TrainingParticipant,WorkCalendar}.json` | Tetik komutları (silme dahil) | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` (`UserSickLeave`) | Kullanıcı detayındaki istirahat listesinin silme tetiği | +| `configs/seeds/wizard/{AttendanceLog,Timesheet,TimesheetMonthly,TimesheetPeriod,MyTimesheet,MyTimesheetDay}.json` | 6 wizard | +| `configs/seeds/wizard/Shift.json` | Tolerans alanları | +| `configs/seeds/data/App.DeveloperKit.CustomComponents/1bca19aa-e144-5e4c-b23b-9eddd4dafd19.json` | `MyTimesheetWidget` | +| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json` | `my-timesheet` | +| `configs/seeds/data/App.DeveloperKit.CustomEndpoints.json` | PDKS ucu | +| `configs/seeds/data/App.BackgroundWorkers.RecurringJobs.json` | `Timesheet Nightly` | +| `configs/seeds/data/App.SettingDefinitions.json` | `App.HrSettings.Attendance.*` | +| `configs/seeds/data/{App.Menus.Menu,Abp.Identity.Permissions,App.Languages.LanguageText}.json` | Menü, yetki, dil | +| `ui/src/views/admin/user-management/{TimesheetTab,Details}.tsx` | Kullanıcı detayı › Puantaj | + +Geri alma: Wizard Manager'dan altı ekran silinir; widget, endpoint, iş ve ayar satırları kendi +ekranlarından kaldırılır. İzin/rapor prosedürlerindeki `Hr_S_TimesheetCalculate` çağrısı kaldırılmadan +prosedür silinmemelidir. Tablolar düşürülmez. + + +## Sağlık Kartları (`App.Hr.HealthCard`) + +İşyeri hekimliği için çalışan sağlık kartı: soy/özgeçmiş, anamnez, laboratuvar ve fizik muayene +bulguları, çalışmaya elverişlilik sonucu (vardiya/gece çalışması dahil), periyodik muayeneler, +revir (hasta protokol defteri) başvuruları ve istirahat raporları. Kart ayrı bir tablo değildir: +tek kayıtlık bölümler doğrudan çalışanın kullanıcı satırında (`AbpUsers` genişletme kolonları), +çok kayıtlı bölümler `Adm_T_User*` tablolarındadır. Tamamı konfigürasyon + platformun kullanıcı +detay ekranıdır. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İşyeri hekimi / sağlık personeli | Kartı doldurur, periyodik muayene ve revir başvurusu girer, elverişlilik sonucunu yazar | Sağlık Kartları (detay sekmeleri) | +| İK | Kart durumunu izler, istirahat raporlarını girer; hekim, hastane ve bölüm tanımlarını yönetir | Sağlık Kartları · İK › Tanımlar | +| Sistem yöneticisi | Aynı veriyi kullanıcı detayında görür | Kimlik › Kullanıcılar › detay › Sağlık Kartı sekmesi | + +Kapsam: kiracı. Liste, kiracının **tüm kullanıcılarıdır** (aktif/pasif); satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, +> entity, `HealthCardTab.tsx`) okunmuştur. + +| Konu | Karar | +| --- | --- | +| Veri yeri | Kart başına tek değer taşıyan alanlar (kan grubu, anamnez, muayene bulguları, sonuç) **`AbpUsers` genişletme kolonlarıdır** — ayrı kart tablosu yok | +| Liste | Sağlık Kartları ekranı `AbpUsers` üzerinde salt okunur listedir (ekle/düzenle/sil kapalı); kart bilgileri detaydaki sekmelerden düzenlenir | +| Tek kayıtlık sekmeler | Soy/Özgeçmiş, Laboratuvar–Fizik Muayene, Anamnez, Sonuç: aynı kullanıcı satırını düzenleyen alt formlar (`Id → Id`, yalnız güncelleme) | +| Çok kayıtlı sekmeler | Periyodik Muayeneler, Hasta Protokol Defteri, İstirahat Raporları: `Adm_T_UserPeriodicExamination`, `Adm_T_UserPatientProtocol`, `Adm_T_UserSickLeave` (`Id → UserId`) | +| İkinci giriş | Kullanıcı detayındaki **Sağlık Kartı** sekmesi (`HealthCardTab.tsx`) aynı kolonları ve aynı üç tabloyu (`App.IdentityManagement.User{PeriodicExamination,PatientProtocol,SickLeave}` listeleriyle) düzenler | +| Hekim | Kurum doktoru tanımı (`Hr_T_Doctor`); periyodik muayenede seçilince diploma no kopyalanır | +| Koşullu alanlar | Anamnezde "evet" denmeyen sorunun not alanı, protokolde sonuç "Sevk" değilse sevk yeri kilitlidir (`readOnly` script) | + +--- + +### 3. Menü ve ekranlar + +| Menü (TR / EN) | `ListFormCode` | Yer | Kaynak | Alt formlar | +| --- | --- | --- | --- | --- | +| Sağlık Kartları / Health Cards | `App.Hr.HealthCard` | `İnsan Kaynakları` (sıra 7, `FcInspection`) | `AbpUsers` | aşağıdaki 7 sekme | + +| Sekme | `ListFormCode` (menüsüz) | Kaynak | İlişki | Düzenleme | +| --- | --- | --- | --- | --- | +| Soy / Özgeçmiş | `App.Hr.HealthCardHistory` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | +| Laboratuvar – Fizik Muayene | `App.Hr.HealthCardLabPhysical` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | +| Anamnez | `App.Hr.HealthCardAnamnesis` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | +| Sonuç | `App.Hr.HealthCardResult` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | +| Periyodik Muayeneler | `App.Hr.HealthCardPeriodicExamination` | `Adm_T_UserPeriodicExamination` | `Id → UserId` | Ekle/düzenle/sil | +| Hasta Protokol Defteri | `App.Hr.HealthCardPatientProtocol` | `Adm_T_UserPatientProtocol` | `Id → UserId` | Ekle/düzenle/sil | +| İstirahat Raporları | `App.Hr.HealthCardSickLeave` | `Adm_T_UserSickLeave` | `Id → UserId` | Ekle/düzenle/sil; kayıt sonrası İzin Yönetimi'ne eşlenir (İzin Yönetimi bölümü §5.5) | + +Widget'lar (liste): Toplam · Aktif · Pasif kullanıcı. + +Tanımlar (`İnsan Kaynakları › Tanımlamalar`): + +| Menü | `ListFormCode` | Seed | +| --- | --- | --- | +| Kurum Doktorları | `App.Hr.Doctor` | 1 kayıt (diploma, işyeri hekimi belge no/tarihi, T.C. kimlik) | +| Hastaneler | `App.Hr.Hospital` | 45 kurum (devlet/özel hastaneler, sağlık ocağı, işyeri hekimliği…) | +| Hastane Bölümleri | `App.Hr.HospitalDepartment` | 31 bölüm | + +--- + +### 4. Veri modeli + +| Yer | Alanlar | +| --- | --- | +| `AbpUsers` — kimlik (liste) | `Name`, `Surname`, `IdentityNumber`, `BirthDate`, `Gender`, `BloodType`, `Email`, `PhoneNumber`, `DepartmentId`, `JobPositionId`, `HireDate`, `SskNo`, `IsActive` | +| `AbpUsers` — soy/özgeçmiş | Anne/baba/kardeş/çocuk sağlık durumu (Alive/Disease/Deceased) + not, `BloodType` (8 grup), `ChronicDisease`, tetanoz/hepatit/diğer aşı | +| `AbpUsers` — anamnez | Şikâyetler (`Complaint*`: göğüs ağrısı, balgamlı öksürük, nefes darlığı, çarpıntı, eklem/bel ağrısı, ishal/kabızlık), tanılar (`Diagnosis*`: diyabet, kalp, böbrek, sarılık, ülser, işitme, görme, sinir sistemi, deri, besin zehirlenmesi), evet/hayır + not soruları (hastanede yatış, ameliyat, iş kazası, meslek hastalığı muayenesi, malulen emeklilik, süren tedavi), sigara/alkol (None/Occasionally/Normal/Quit + not) | +| `AbpUsers` — lab/fizik | `Lab*` (biyolojik, kan, idrar, radyolojik, odyometri, SFT, psikolojik, diğer), `Exam*` (duyu, göz, KBB, deri, kalp-damar, solunum, sindirim, ürogenital, kas-iskelet, nörolojik, psikiyatrik, diğer, tansiyon, nabız, boy, kilo) | +| `AbpUsers` — sonuç | `FitForWorkJob`, `FitForWorkCondition`, `FitnessDoctorId`, `ShiftWorkFit`, `NightWorkFit`, `ShiftNightDoctorId` | +| `Adm_T_UserPeriodicExamination` | `UserId`, `ExamDate`, `Examination`, `Result`, `DoctorId`, `DoctorDiplomaNo` | +| `Adm_T_UserPatientProtocol` | `UserId`, `SequenceNo`, `ProtocolDate`, `ProtocolType` (Disease/WorkAccident/OccupationalDisease/Control/Other), `ProtocolResult` (TreatmentDischarged/Rest/Referral), `RestDays`, `ReferralPlace`, `DoctorId` | +| `Adm_T_UserSickLeave` | `UserId`, `StartDate`, `EndDate`, `Days`, `SickLeaveType` (Disease/WorkAccident/OccupationalDisease/Maternity), `Institution`, `Clinic`, `SickLeaveReason` | +| `Hr_T_Doctor` / `Hr_T_Hospital` / `Hr_T_HospitalDepartment` | Tanımlar | + +Entity'ler: `Entities/Tenant/Administration/User{PeriodicExamination,PatientProtocol,SickLeave}.cs`; +genişletme kolonları `AbpIdentityUserExtensions` ve EF genişletme eşlemeleri. + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Anamnez | Evet/hayır sorusu işaretli değilse not alanı salt okunur; sigara/alkol "Kullanmıyor" ise not kilitli | +| Periyodik muayene | Yeni satırda tarih bugün; hekim seçilince diploma no kopyalanır | +| Protokol | Yeni satırda tarih bugün; sonuç "Sevk" değilse sevk yeri kilitli | +| İstirahat | `Days = days(Başlangıç, Bitiş)` (bitiş dahil); bitiş başlangıçtan önceyse uyarı | +| Liste | Kayıt eklenemez/silinemez — kartın sahibi kullanıcı kaydıdır | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. `App.Hr.HealthCard` kökü; yedi sekme onun altındadır. Tanımlar +`App.Hr.Definitions` altındadır. Kullanıcı detayındaki sekme, kullanıcı ekranının yetkileriyle +(`AbpIdentity.Users` / `.Update`) çalışır. Hiçbir yetki role otomatik atanmaz. + +Sağlık verisi **özel nitelikli kişisel veridir** (KVKK md. 6): Sağlık Kartları ve alt sekmelerinin +yetkisi yalnız işyeri hekimi ve yetkili sağlık personeline verilmelidir. Kullanıcı detayına erişen +yöneticiler de bu sekmeyi görebileceği için kullanıcı yönetimi yetkisi de buna göre sınırlanmalıdır. + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `AbpUsers` (+ `Hr_T_Department`, `Hr_T_JobPosition`) | Kartın sahibi ve kimlik bilgisi | +| Kullanıcı detayı (`views/admin/user-management/HealthCardTab.tsx`) | Aynı verinin ikinci düzenleme yeri | +| `Hr_T_Doctor` | Periyodik muayene, protokol, sonuç hekimleri | + +Hastane ve hastane bölümü tanımları **henüz hiçbir sekmeye bağlı değildir** (istirahatte kurum/klinik +serbest metindir). Bildirim, periyodik muayene hatırlatması ya da rapor şablonu yoktur. + +--- + +### 8. Akış örneği + +1. İşe giren çalışanın kartı listede hazırdır (kullanıcı açıldığı anda). Hekim **Soy/Özgeçmiş** ve + **Anamnez** sekmelerini doldurur. +2. İşe giriş muayenesi bulguları **Laboratuvar – Fizik Muayene**'ye, kararı **Sonuç**'a yazılır + (vardiyalı/gece çalışabilir + hekimler). +3. Yıllık kontrol **Periyodik Muayeneler**'e eklenir. +4. Çalışan revire gelince **Hasta Protokol Defteri**'ne kayıt açılır (tür Hastalık, sonuç İstirahat, 1 gün). +5. Dışarıdan alınan rapor **İstirahat Raporları**'na girilir; gün sayısı hesaplanır. + +--- + +### 9. Sık sorulanlar + +**Listeye neden kayıt eklenemiyor?** Kart kullanıcı kaydıdır; yeni çalışan Kimlik › Kullanıcılar'dan açılır. + +**Sağlık kartı verisi nerede tutuluyor?** Tek değerli alanlar `AbpUsers` kolonlarında, muayene/protokol/istirahat ayrı tablolarda (§4). + +**Kullanıcı detayındaki Sağlık Kartı sekmesiyle bu ekran aynı mı?** Evet; aynı veriyi iki yerden düzenlerler. + +**Hastane tanımı nerede kullanılıyor?** Şu an hiçbir yerde; ileride istirahat/sevk alanlarına lookup olarak bağlanmak üzere duruyor. + +**İstirahat raporu izinlere yansıyor mu?** Evet, tek kayıttır: buradan (ya da kullanıcı detayındaki İstirahatler'den) girilen rapor İK › İzin Yönetimi'nde onaylı Rapor (`Sick`) talebi olur; çalışanın Intranet'ten açtığı Rapor talebi de bu sekmeye düşer (`Hr_S_LeaveSickLeaveSync`, ayrıntı İzin Yönetimi bölümü §5.5). Rapor yıllık izin bakiyesinden düşmez; yıllık izindeyken alınan raporun günleri izinden sayılmaz, bakiyeye döner. Çalışanın rapor talebi sağlık kartına onaylanınca düşer. Raporun günleri (hafta sonu dahil) puantajda Raporlu olur, devamsız yazılmaz (`Hr_S_LeaveSickLeaveSync` sonunda yeniden hesap, Puantaj ve Devam Takibi bölümü §7.1). Kapalı puantaj ayına düşen rapor kaydedilemez/silinemez; önce İK dönemi açar. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/wizard/HealthCard{,History,LabPhysical,Anamnesis,Result,PeriodicExamination,PatientProtocol,SickLeave}.json` | 8 wizard | +| `configs/seeds/wizard/{Doctor,Hospital,HospitalDepartment}.json`, `data/App.Hr.{Doctor,Hospital,HospitalDepartment}.json` | Tanım ekranları ve verisi | +| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/User{PeriodicExamination,PatientProtocol,SickLeave}.cs` | Çok kayıtlı sekmelerin entity'leri (migration'lı) | +| `ui/src/views/admin/user-management/HealthCardTab.tsx` | Kullanıcı detayındaki sekme | + +Kart sekmelerini kaldırmak wizard'ları siler; `AbpUsers` kolonları ve `Adm_T_User*` tabloları +entity/migration'a bağlı olduğu için kalır. + + +## Eğitimler (`App.Hr.Trainings`) + +Şirket içi ve dışı eğitimlerin kaydı: eğitim tipi → konu tanımları, eğitim oturumu (tarih/saat, +süre, yer, eğitmen, maliyet, kazandırdığı yetkinlikler), katılımcılar (katılım durumu, puan, +katılım belgesi) ve eğitim dosyaları. Tamamı konfigürasyondur (Wizard + rapor şablonu); entity, +migration ya da React kodu yoktur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK / eğitim sorumlusu | Tip ve konu tanımlar, eğitim açar, katılımcı ekler, katılım/puan girer, dosya yükler, katılım belgesi basar | Eğitim Tipleri · Eğitim Konuları · Eğitimler | +| Yönetim | Eğitim adedi, açık/kapalı durum ve toplam maliyeti izler (widget, Pivot, Chart) | Eğitimler | + +Kapsam: kiracı (`IsTenant`). Eğitim bir şubeye bağlıdır (`BranchId` zorunlu); satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan +> (wizard, SQL, seed, commit `36546d0c` "Human Resources -> Eğitim bilgileri") okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Wizard ekranları; eğitim kaydının altında Katılımcılar ve Dosyalar sekmeleri (menüsüz alt formlar) | +| Tanımlar | Tip ve konu tanımları İK › Tanımlar'da değil **Eğitimler** dalının içindedir; konu bir tipe bağlıdır ve tip seçimine göre süzülür | +| Süre | `Toplam Süre (saat) = gün sayısı (bitiş dahil) × günlük saat (bitiş – başlangıç saati)` — formda hesaplanır | +| Maliyet | Altı kalem (yer, eğitmen, konaklama, ulaşım, ikram, diğer) toplanarak `CostTotal` formda hesaplanır | +| Yetkinlik | Eğitimin kazandırdığı yetkinlikler `SkillIds` (çok değerli, `Hr_T_Skill`) olarak saklanır; çalışan profiline (`Adm_T_UserSkill`) **yazılmaz** | +| Katılımcı | Personel seçilince işe giriş tarihi, departman ve pozisyon kullanıcı kaydından kopyalanır (eğitim anındaki hâli saklanır) | +| Katılım durumu | Attended / NotAttended / Excused; varsayılan **Attended** | +| Katılım belgesi | Yalnızca `Attended` satırda görünen satır butonu → **Katılım Belgesi** raporu (`DynamicReport`) | +| Dosyalar | Belge türü `Hr_T_DocumentType` (ortak İK tanımı); dosya içeriği base64 (`dxImageUpload`) | + +--- + +### 3. Menü ve ekranlar + +`İnsan Kaynakları › Eğitimler` (`App.Hr.Trainings`, ikon `FcGraduationCap`) + +| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Görünümler | Widget'lar | +| --- | --- | --- | --- | --- | --- | +| 1 | Eğitim Tipleri / Training Types | `App.Hr.TrainingType` | — | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | +| 2 | Eğitim Konuları / Training Subjects | `App.Hr.TrainingSubject` | — | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | +| 3 | Eğitimler / Trainings | `App.Hr.Training` | `TrainingParticipant`, `TrainingFile` (`Id → TrainingId`, menüsüz) | Grid, Card, Pivot, Chart | Toplam · Açık · Kapalı · Toplam Maliyet | + +Seed verisi: 8 eğitim tipi (Oryantasyon, İş Başı, Teknik Oryantasyon, Grup, Firma Dışı, Eğitim +İçerikli Sosyal Faaliyet, Akademi, Rotasyon) ve 18 eğitim konusu (`data/App.Hr.{TrainingType,TrainingSubject}.json`). + +Satır butonu: Katılımcılar › **Katılım Belgesi** — rapor `3840a20d-3233-4d17-bc06-ccfd8d87b32a`, +görünürlük `AttendanceStatus === 'Attended'`. + +--- + +### 4. Veri modeli + +``` +Hr_T_TrainingType ──< Hr_T_TrainingSubject + │ │ + └──────< Hr_T_Training >──── Sas_T_Branch + ├──< Hr_T_TrainingParticipant >── AbpUsers (+ Department, JobPosition) + └──< Hr_T_TrainingFile >── Hr_T_DocumentType +``` + +| Tablo | Önemli kolonlar | Kural | +| --- | --- | --- | +| `Hr_T_TrainingType` | `Name`, `IsActive` | — | +| `Hr_T_TrainingSubject` | `TrainingTypeId`, `Name`, `IsEvaluated` (değerlendirilsin mi), `IsActive` | — | +| `Hr_T_Training` | `TrainingTypeId`, `TrainingSubjectId` (tipe göre cascade), `EntryDate`, `BranchId`, `StartDate`, `EndDate`, `StartTime`, `EndTime`, `TotalHours`, `Status` (Open/Closed), `TrainerName`, `TrainingPlace`, `TrainingInstitution`, `Description`, `SkillIds`, `CostPlace`, `CostTrainer`, `CostAccommodation`, `CostTransport`, `CostCatering`, `CostOther`, `CostTotal` | Bitiş başlangıçtan önce olamaz (form) | +| `Hr_T_TrainingParticipant` | `TrainingId`, `UserId`, `HireDate`, `DepartmentId`, `JobPositionId`, `AttendanceStatus`, `EvaluationScore`, `ExamScore`, `LeaveDate`, `Note` | — | +| `Hr_T_TrainingFile` | `TrainingId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` | Dosya zorunlu | + +Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır. + +--- + +### 5. İş kuralları ve hesaplar + +Hesapların tamamı `EditorScript`'tir (sunucu tarafında after-command yoktur): + +| Alan | Kural | +| --- | --- | +| `EntryDate` | Yeni kayıtta bugün | +| `Status` | Yeni kayıtta `Open` | +| `TotalHours` | Başlangıç/bitiş tarihi ya da saatlerinden biri değişince `round(days(StartDate, EndDate) × hours(StartTime, EndTime), 2)`; dört alan dolu olmalı | +| `EndDate` | Başlangıçtan önceyse uyarı + değişiklik geri alınır | +| `CostTotal` | Altı maliyet kaleminden biri değişince toplam | +| Katılımcı `UserId` | Seçilince `HireDate`, `DepartmentId`, `JobPositionId` kopyalanır | +| `AttendanceStatus` | Yeni satırda `Attended` | +| Dosya `FileDate` | Yeni satırda bugün | +| Tip/Konu `IsActive`, `IsEvaluated` | Yeni kayıtta `true` | + +Saat hesabı aynı günlük saat aralığının her gün tekrarlandığını varsayar; gün sayısına bitiş günü dahildir. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Trainings` ara yetkisinin +altında üç ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; `TrainingParticipant` ve +`TrainingFile` `App.Hr.Training` altındadır. Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. + +| Rol | Yetkiler | +| --- | --- | +| Eğitim sorumlusu | `App.Hr.Trainings` dalının tamamı | +| Bölüm yöneticisi (izleme) | `App.Hr.Training` + `App.Hr.TrainingParticipant` (salt okuma) | + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `Sas_T_Branch` | Eğitimin şubesi | +| `AbpUsers` | Katılımcı; işe giriş tarihi, departman, pozisyon kopyası | +| Kullanıcı detayı › Eğitimler | Katılımcılar ekranı çalışana süzülmüş açılır; satır eklemek çalışanı eğitime katılımcı yapar (Personel Kaydı bölümü) | +| `Hr_T_Department`, `Hr_T_JobPosition` | Katılımcının o anki birimi (Pivot kırılımı) | +| `Hr_T_Skill` / `Hr_T_SkillType` | Eğitimin kazandırdığı yetkinlikler | +| `Hr_T_DocumentType` | Eğitim dosyası türü | +| Raporlar | Katılım Belgesi (`DynamicReport`, `Raporlar` kategorisi) | +| Performans Yönetimi | Gelişim planı aksiyonu bir eğitime bağlanabilir (`Hr_T_DevelopmentPlan.TrainingId`); çalışan o eğitimde **Attended** ise aksiyon kendiliğinden tamamlanır: plan kaydında ve katılımcı kaydında (`Hr_S_DevelopmentPlanSync`, `Hr_S_TrainingSync`; bkz. Performans Yönetimi bölümü) | +| Puantaj ve Devam Takibi | **Katıldı** işaretli katılımcının başlangıç–bitiş arasındaki iş günleri puantajda `Eğitimde` (vardiya saatleriyle) yazılır, okutması olmadığı için devamsız sayılmaz. Eğitim ya da katılımcı eklenince, değişince, silinince `Hr_S_TrainingSync` günleri hemen yeniden hesaplar (Puantaj ve Devam Takibi bölümü §7.1) | + +--- + +### 8. Akış örneği + +1. İK **Eğitimler**'de "İş Sağlığı ve Güvenliği" kaydını açar: tip Grup Eğitimi, konu İSG, şube + Merkez, 3–4 Kasım 09:00–17:00 → toplam süre 16 saat; eğitmen ve yer maliyetini girer → toplam + maliyet hesaplanır; kazandırdığı yetkinliği (İSG) seçer. +2. **Katılımcılar** sekmesine personeli ekler; departman/pozisyon kopyalanır, durum Katıldı. +3. Gelmeyen personeli **Katılmadı**, raporlu olanı **Mazeretli** yapar; sınav/değerlendirme puanlarını girer. +4. Katılanların satırından **Katılım Belgesi** basılır; imzalı liste **Dosyalar** sekmesine yüklenir. +5. Eğitim **Kapalı** yapılır; widget'taki toplam maliyete eklenir. + +--- + +### 9. Sık sorulanlar + +**Toplam süre hesaplanmıyor.** Başlangıç/bitiş tarihi ve başlangıç/bitiş saatinin dördü de dolu olmalı. + +**Katılım belgesi butonu görünmüyor.** Yalnızca katılım durumu "Katıldı" olan satırda çıkar. + +**Eğitim konusu listesi boş.** Konu, seçilen eğitim tipine göre süzülür; önce tip seçin. + +**Eğitimdeki yetkinlik çalışan profiline yazılıyor mu?** Hayır; `SkillIds` eğitimin bilgisidir. Profil, Performans Yönetimi'nde tamamlanan değerlendirmeden güncellenir. + +**Katılımcının departmanı sonradan değişti, eğitimde eski görünüyor.** Bilinçli: eğitim anındaki birim saklanır. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{TrainingType,TrainingSubject,Training,TrainingParticipant,TrainingFile}.sql` | Tablolar | +| `configs/seeds/wizard/{TrainingType,TrainingSubject,Training,TrainingParticipant,TrainingFile}.json` | 5 wizard | +| `configs/seeds/data/App.Hr.{TrainingType,TrainingSubject}.json` | Tanım verisi | +| `configs/seeds/data/App.Reports.ReportTemplates.json` | Katılım Belgesi şablonu | +| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | + +Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar (`TrainingParticipant`, `TrainingFile`) +önce, sonra `Training`, `TrainingSubject`, `TrainingType` silinir; tablolar yalnızca onayda seçilirse +düşer. Gelişim planlarındaki `TrainingId` bağları silinmez, boşa düşer. + + +## Performans Yönetimi (`App.Hr.Performance`) + +Dönem bazlı performans süreci: İK dönemi açar, çalışan hedeflerini ve öz değerlendirmesini yapar, +yönetici değerlendirir, isteğe bağlı 360 derece geri bildirim toplanır, İK kalibre eder, sonuç +gelişim planına ve çalışanın yetkinlik profiline yansır. **İnsan Kaynakları menüsü İK +departmanınındır** (şartları belirler, değerlendirmeleri takip eder ve girer); çalışan ve yönetici +kendisiyle ilgili her şeyi **Intranet › Dashboard**'daki widget'lardan takip eder. Tamamı konfigürasyondur (Wizard + Custom +Component + SQL nesneleri); yeni entity, migration ya da React kodu yoktur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK | Dönem ve yetkinlik seti tanımlar, tüm değerlendirmeleri izler, 360 değerlendiricisi atar, kalibre eder, gelişim planlarını izler | Dönemler · Tüm Değerlendirmeler · Kalibrasyon · Gelişim Planları · Performans Dereceleri | +| Çalışan | Hedeflerini girer, gerçekleşeni ve öz değerlendirmesini yazar, yöneticiye gönderir, gelişim aksiyonlarının ilerlemesini günceller | Intranet panosu: **Performansım** widget'ı → Değerlendirmelerim · Gelişim Planım · Profil › Performansım (Değerlendirmelerim · Hedeflerim · Gelişim Planım · 360 Taleplerim salt okunur) | +| Yönetici | Hedefleri onaylar, yetkinlik seviyesini ve yorumunu verir, kalibrasyona gönderir, gelişim aksiyonu planlar | Intranet panosu: **Ekibimin Performansı** widget'ı → Ekibimin Değerlendirmeleri | +| 360 değerlendiricisi | Kendisine atanan çalışanın yetkinliklerini puanlar ve gönderir | Intranet panosu: **360 Taleplerim** widget'ı → 360 Taleplerim | + +Kapsam: kiracı (`IsTenant`). Şube/birim kırılımı yoktur. + +--- + +### 2. Analiz ve kararlar + +#### 2.1 Talep + +> İnsan Kaynakları › Performans Yönetimi: değerlendirme dönemi tanımı, hedefler (KPI/OKR, ağırlık %, +> gerçekleşme), yetkinlik değerlendirmesi (Skill Types üzerinden), öz değerlendirme + yönetici +> değerlendirmesi, isteğe bağlı 360 derece, kalibrasyon ekranı, gelişim planı; uygulamanın diğer +> özellikleriyle entegre. + +#### 2.2 Depodan okunanlar (sorulmadı) + +- Çalışan = `AbpUsers` (`DepartmentId`, `JobPositionId` taşır). +- Yetkinlik zinciri `Hr_T_SkillType → Hr_T_Skill → Hr_T_SkillLevel` (`Progress` 0–100); çalışan profili `Adm_T_UserSkill` (`Level` 1–5). +- Kök menü `App.Hr`, izin grubu `App.Hr`, modül `Hr`; tanımlar `App.Hr.Definitions` altında. +- **Yönetici ilişkisi ne `AbpUsers`'ta ne `Hr_T_Department`'ta vardır** — bu yüzden sorudur. + +#### 2.3 Keşif turu cevapları + +| # | Soru | Seçilen | Gerekçe | +| --- | --- | --- | --- | +| 1 | Ekran yapısı | Wizard ekranları + çalışana ait özet (Custom Component) | Liste/form kalıbına sığan her şey Wizard; özet ilk sürümde İK menüsünde "Performansım" panosuydu, §2.4'teki kararla Intranet widget'larına taşındı | +| 2 | Yönetici nereden gelir | Değerlendirme kaydında seçilir (`ManagerId`, `AbpUsers` lookup) | Platform tablosu şeması değişmez (çerçeve içi) | +| 3 | Genel puan formülü | Dönemde ağırlık tanımlı: Genel = Hedef puanı × a + Yetkinlik puanı × b | Dönem bazında değiştirilebilir (varsayılan 60/40) | +| 4 | Akış | Durum alanıyla, onaysız (WorkflowDto yok) | Geçiş kuralları prosedürde | +| 5 | Yetkinlik ölçeği | `SkillLevel` + `Progress %`; tamamlanınca `UserSkill`'e yazılır | Skill Types'ın kendi seviyeleri kullanılır, profil güncel kalır | +| 6 | Hedef gerçekleşme | Yönlü, %150 tavanlı | Artan/Azalan hedef ayrımı, aşım ödüllendirilir ama sınırlıdır | +| 7 | 360 | Dönem bayrağı, bilgi amaçlı | Ortalama gösterilir, genel puana girmez | +| 8 | Görünürlük | Rol + kullanıcı süzmesi | İK hepsini, diğerleri kendi/ekibinin kaydını görür | + +#### 2.4 Onaylanan tariften sapmalar (üretimde verilen kararlar) + +| Tarifte | Üretilen | Neden | +| --- | --- | --- | +| Gelişim planında Gantt | **Scheduler** (takvim) + Todo | Gantt `ParentIdExpr` ister; aksiyonlar arasında hiyerarşi yok | +| Derece ölçeği "Performans › Tanımlar" | **İK › Tanımlar** (`App.Hr.Definitions`) | İK tanımlarının (aday kaynağı, değerlendirme kriteri…) mevcut yeri | +| Dönem ekranında "Değerlendirmeler" sekmesi | Yalnız **Yetkinlik Seti** sekmesi | Widget'lı menü ekranı alt form olamaz (standing default 13); değerlendirmeler Tüm Değerlendirmeler'de döneme göre süzülür | +| Persona alt formları | Hedef/yetkinlik/gelişim için İK, çalışan, yönetici olmak üzere **üçer ayrı menüsüz ekran** | Alan kilidi ve satır süzmesi ekran bazındadır | +| Todo kart başlığı | `EmployeeName` kolonu eklendi (prosedür doldurur) | Todo başlığı metin kolon ister (İşe Alım'daki `CandidateName` kalıbı) | +| Eğitim entegrasyonu | Plan eğitime katılımcı **yazmaz**; çalışan eğitime "Katıldı" işlenmişse plan kendiliğinden tamamlanır | `Hr_T_TrainingParticipant.AttendanceStatus` "planlandı" değeri taşımıyor | +| "Performansım" panosu ve persona listeleri İK › Performans Yönetimi menüsünde | Persona listeleri **menüsüz**; özetleri Intranet › Dashboard'da üç ayrı widget (Performansım, Ekibimin Performansı, 360 Taleplerim), widget'taki bağlantı listeyi açar | İK menüsü İK departmanınındır; çalışan kendisiyle ilgili bilgiyi Intranet'ten takip eder (kullanıcı kararı, 2026-10-04). Widget içeriği özet + bağlantıdır; pano kolonları dar olduğu için liste gömülmez | + +#### 2.5 Varsayılan kalanlar + +- Derece ölçeği (host seed'i): 1 Beklentinin Çok Altında 0–50 (%5) · 2 Geliştirilmeli 50–70 (%15) · 3 Beklenen Düzeyde 70–90 (%60) · 4 Beklentinin Üstünde 90–110 (%15) · 5 Olağanüstü 110+ (%5). Alt sınır dahil, üst sınır hariç. +- Ağırlık toplamı 100 değilse kayıt engellenmez; yalnızca hedef belirleme aşamasından çıkış engellenir. +- Bildirim kanalları: `UiActivity` + `UiToast`. + +--- + +### 3. Menü ve ekranlar + +#### 3.1 İK menüsü + +`İnsan Kaynakları › Performans Yönetimi` (`App.Hr.Performance`, ikon `FcBullish`) — yalnız İK. + +| Sıra | Menü (TR / EN) | `ListFormCode` | Wizard dosyası | Alt formlar | Görünümler | +| --- | --- | --- | --- | --- | --- | +| 1 | Değerlendirme Dönemleri / Review Periods | `App.Hr.PerformancePeriod` | `PerformancePeriod.json` | `PerformancePeriodSkill` | Grid, Card, Pivot, Chart | +| 2 | Tüm Değerlendirmeler / All Reviews | `App.Hr.PerformanceReview` | `PerformanceReview.json` | `PerformanceGoal`, `PerformanceCompetency`, `PerformanceFeedback` (→ `PerformanceFeedbackScore`), `ReviewDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | +| 3 | Kalibrasyon / Calibration | `App.Hr.PerformanceCalibration` | `PerformanceCalibration.json` | — | Grid, Card, Pivot, Chart | +| 4 | Gelişim Planları / Development Plans | `App.Hr.DevelopmentPlan` | `DevelopmentPlan.json` | — | Grid, Card, Pivot, Chart, Todo, Scheduler | +| — | Performans Dereceleri (İK › Tanımlar) | `App.Hr.PerformanceRating` | `PerformanceRating.json` | — | Grid, Card, Pivot, Chart; veri `data/App.Hr.PerformanceRating.json` ile aynalı | + +Widget şeritleri: + +| Ekran | Kartlar | +| --- | --- | +| Dönemler | Toplam · Aktif · Kalibrasyonda · Kapanan | +| Tüm Değerlendirmeler | Toplam · Hedef/Öz Değerlendirme · Yönetici Değerlendirmesinde · Kalibrasyonda · Tamamlanan | +| Kalibrasyon | Kalibrasyonda · Tamamlanan · Ortalama Puan · Ortalama Kalibre Puan | +| Gelişim Planları | Toplam · Açık Aksiyon · Geciken · Tamamlanan | + +#### 3.2 Çalışana ait ekranlar (menüsüz) + +Menüde yer almazlar; Intranet panosundaki widget'tan `/admin/list/{ListFormCode}` adresiyle açılırlar. +Menüsüz wizard olduklarından widget şeritleri yoktur (deploy menüsüz ekranın `Widgets`'ını düşürür); +özetleri panodaki widget'tadır. + +| Ekran (TR / EN) | `ListFormCode` | Wizard dosyası | Satır süzmesi | Alt formlar | Görünümler | +| --- | --- | --- | --- | --- | --- | +| Değerlendirmelerim / My Reviews | `App.Hr.MyPerformanceReview` | `MyPerformanceReview.json` | `EmployeeId = @USERID` | `MyPerformanceGoal`, `MyPerformanceCompetency`, `MyDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | +| Ekibimin Değerlendirmeleri / Team Reviews | `App.Hr.TeamPerformanceReview` | `TeamPerformanceReview.json` | `ManagerId = @USERID` | `TeamPerformanceGoal`, `TeamPerformanceCompetency`, `TeamDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | +| 360 Taleplerim / My 360 Requests | `App.Hr.My360Feedback` | `My360Feedback.json` | `ReviewerId = @USERID` | `My360FeedbackScore` | Grid, Card, Pivot, Chart | +| Gelişim Planım / My Development Plan | `App.Hr.MyDevelopmentPlan` | `MyDevelopmentPlan.json` | `EmployeeId = @USERID` | — (Değerlendirmelerim'in sekmesi; widget'tan tek liste olarak da açılır) | Grid | + +#### 3.3 Intranet › Dashboard widget'ları + +`Sas_T_IntranetWidget` kayıtları (`data/App.DeveloperKit.IntranetWidgets.json`, `SourceType: 1` = +Custom) üç custom component'i sağ kolona (`Column: 2`) yerleştirir. Widget'ı yalnız `PermissionName` +yetkisi olan kullanıcı alır (sunucu süzer, `IntranetAppService.GetWidgetsAsync`); kullanıcı panoda +yerini değiştirebilir, gizleyebilir. + +| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Açtığı liste | +| --- | --- | --- | --- | --- | +| `my-performance` · 70 | `MyPerformanceWidget` | `App.Hr.MyPerformanceReview` | Aktif (tamamlanmamış) değerlendirmenin aşaması ve hedef/yetkinlik/genel puanı; tamamlanan sayısı ve ortalama puanı; `App.Hr.MyDevelopmentPlan` yetkisi varsa açık ve geciken gelişim aksiyonu | Değerlendirmelerim, Gelişim Planım | +| `team-performance` · 80 | `TeamPerformanceWidget` | `App.Hr.TeamPerformanceReview` | Değerlendirmemi bekleyen (`ManagerReview`), hedef/öz değerlendirmede, tamamlanan, toplam; bekleyen ilk 5 çalışanın adı | Ekibimin Değerlendirmeleri | +| `my-360-feedback` · 90 | `My360FeedbackWidget` | `App.Hr.My360Feedback` | Bekleyen ve gönderilen 360 talebi | 360 Taleplerim | + +Bileşenler code modundadır ve rotasızdır (`RoutePath: null`). Veriyi ekranın kendi sorgusundan okur +(`GET /api/app/list-form-select/select?listFormCode=…`): satır süzmesi (`DefaultFilter`), kiracı ve +liste yetkisi ListForm'da kalır, bileşen yalnızca sayar — ayrı endpoint ya da SQL yoktur. Başlıklar +`App.DashboardWidget.{MyPerformance,TeamPerformance,My360Feedback}`, boş durum ve aktif değerlendirme +metinleri `App.DashboardWidget.Performance.*`; kart etiketleri İK şeritlerindeki +`App.Hr.Performance.Widget.*` anahtarlarıdır. + +--- + +### 4. Veri modeli + +Hepsi `sql/object/Hr_T_*.sql`; kiracı + tam audit + `IsActive`, `Guid` anahtar. + +``` +Hr_T_PerformancePeriod ──< Hr_T_PerformancePeriodSkill >── Hr_T_Skill + │ + └──< Hr_T_PerformanceReview >── AbpUsers (EmployeeId, ManagerId) + │ └── Hr_T_PerformanceRating (RatingId) + ├──< Hr_T_PerformanceGoal + ├──< Hr_T_PerformanceCompetency >── Hr_T_Skill / Hr_T_SkillLevel ×3 + ├──< Hr_T_PerformanceFeedback ──< Hr_T_PerformanceFeedbackScore >── Hr_T_SkillLevel + └──< Hr_T_DevelopmentPlan >── Hr_T_Skill / Hr_T_Training / Hr_T_Certificate / AbpUsers (Mentor) +``` + +| Tablo | Önemli kolonlar | Tekillik / kural | +| --- | --- | --- | +| `Hr_T_PerformanceRating` | `Level`, `Name`, `MinScore`, `MaxScore`, `Color`, `TargetDistribution` | `(TenantId, Level)` tekil; `MinScore < MaxScore` | +| `Hr_T_PerformancePeriod` | `StartDate`, `EndDate`, `SelfReviewDueDate`, `ManagerReviewDueDate`, `GoalWeight`, `CompetencyWeight`, `Is360Enabled`, `Status` | Ağırlık toplamı = 100 (CHECK); `Status` ∈ Planned, Active, Calibration, Closed | +| `Hr_T_PerformancePeriodSkill` | `PeriodId`, `SkillId`, `ExpectedLevelId` | `(PeriodId, SkillId)` tekil | +| `Hr_T_PerformanceReview` | `PeriodId`, `EmployeeId`, `EmployeeName`, `ManagerId`, `DepartmentId`, `JobPositionId`, `Status`, `LastStatus`, `GoalScore`, `CompetencyScore`, `Feedback360Score`, `OverallScore`, `CalibratedScore`, `RatingId`, yorumlar, gönderim tarihleri | `(PeriodId, EmployeeId)` tekil; `Status` ∈ GoalSetting, SelfReview, ManagerReview, Calibration, Completed; `CalibratedScore` 0–150 | +| `Hr_T_PerformanceGoal` | `GoalType` (KPI/OKR), `Title`, `Direction` (Increasing/Decreasing), `Unit`, `TargetValue`, `ActualValue`, `Weight`, `AchievementRate` | `TargetValue > 0`, `0 < Weight ≤ 100` | +| `Hr_T_PerformanceCompetency` | `SkillId`, `ExpectedLevelId`, `SelfLevelId`, `ManagerLevelId`, `Score` | `(ReviewId, SkillId)` tekil | +| `Hr_T_PerformanceFeedback` | `ReviewerId`, `Relation` (Peer/Subordinate/Superior/InternalCustomer), `Status` (Pending/Submitted), `Score`, `Comment`, `SubmittedDate` | `(ReviewId, ReviewerId)` tekil | +| `Hr_T_PerformanceFeedbackScore` | `FeedbackId`, `SkillId`, `LevelId`, `Comment` | `(FeedbackId, SkillId)` tekil | +| `Hr_T_DevelopmentPlan` | `EmployeeId`, `ReviewId`, `SkillId`, `Title`, `ActionType`, `TrainingId`, `CertificateId`, `MentorId`, `StartDate`, `DueDate`, `Status`, `Progress` | `ActionType` ∈ Training, Mentoring, Project, Reading, Certificate, Other; `Status` ∈ Planned, InProgress, Completed, Cancelled; `Progress` 0–100 | + +Seviye listeleri (`ExpectedLevelId`, `SelfLevelId`, `ManagerLevelId`, `LevelId`) seçilen yetkinliğin +`SkillTypeId`'sine göre süzülür (lookup cascade `SkillId` → `@param0`). + +--- + +### 5. İş kuralları ve hesaplar + +#### 5.1 Formüller (`Hr_S_PerformanceReviewRecalc`) + +| Değer | Formül | +| --- | --- | +| Hedef gerçekleşme % | Artan: `Gerçekleşen / Hedef × 100` · Azalan: `Hedef / Gerçekleşen × 100` (gerçekleşen ≤ 0 ise 150) · sonuç **0–150** aralığına kırpılır · gerçekleşen boşsa boş | +| Hedef puanı | `Σ(Gerçekleşme% × Ağırlık) / 100` (gerçekleşmesi boş hedef 0 sayılır; hedef yoksa boş) | +| Yetkinlik satır puanı | Yönetici seviyesinin `Hr_T_SkillLevel.Progress` değeri | +| Yetkinlik puanı | Puanı dolu yetkinlik satırlarının ortalaması | +| 360 satır puanı | Değerlendiricinin verdiği seviyelerin `Progress` ortalaması | +| 360 ortalaması | `Status = Submitted` geri bildirimlerin ortalaması — **genel puana girmez** | +| Genel puan | `(Hedef puanı × GoalWeight + Yetkinlik puanı × CompetencyWeight) / 100` (eksik bileşen 0; ikisi de boşsa boş) | +| Derece | `COALESCE(KalibrePuan, GenelPuan)` değerinin düştüğü aralık (`MinScore ≤ x < MaxScore`, aynı kiracının aktif dereceleri) | + +Formda gerçekleşme % anlık önizlenir (`ActualValue`/`TargetValue`/`Direction` alanlarının +`EditorScript`'i); kalıcı değer her kayıtta prosedürle yeniden hesaplanır. Dönemde ağırlık +alanlarından biri değişince diğeri `100 - x` olur (`EditorScript`). + +#### 5.2 Durum akışı (`Hr_S_PerformanceReviewAfterSave`) + +``` +GoalSetting ──(Yönetici)──▶ SelfReview ──(Çalışan)──▶ ManagerReview ──(Yönetici)──▶ Calibration ──(İK)──▶ Completed + ▲ ◀──(Yönetici iade)──┘ ◀──(Yönetici iade)──┘ +``` + +| Aktör (ekran) | İzinli geçişler | +| --- | --- | +| İK (Tüm Değerlendirmeler, Kalibrasyon) | Her geçiş | +| Çalışan (Değerlendirmelerim) | SelfReview → ManagerReview | +| Yönetici (Ekibimin Değerlendirmeleri) | GoalSetting → SelfReview · SelfReview → GoalSetting · ManagerReview → SelfReview · ManagerReview → Calibration | + +- **GoalSetting'ten çıkış** için en az bir hedef olmalı ve ağırlık toplamı tam **100** olmalıdır (her aktör için). +- İzinsiz geçiş hata vermez, **kayıt sonrası durum `LastStatus`'a geri alınır** (kayıt yenilenince eski aşama görünür). +- Geçiş damgaları: → ManagerReview `SelfSubmittedDate`, → Calibration `ManagerSubmittedDate`, → Completed `CompletedDate`. +- → **Completed**: yönetici seviyeleri `Adm_T_UserSkill`'e yazılır (`Level = ⌈Progress / 20⌉`, 1–5; var olan kayıt güncellenir, `Note = "Performans: {Dönem}"`). +- Her kayıtta: `EmployeeName`/`DepartmentId`/`JobPositionId` çalışandan tamamlanır, dönemin eksik yetkinlikleri eklenir, puanlar yeniden hesaplanır. +- Todo panosunda kartı sürüklemek de aynı kuraldan geçer. + +#### 5.3 Satır ve aşama güvenliği (`Hr_S_PerformanceGuard`, before-command) + +Persona ekranları satırı `DefaultFilter` ile süzer; kayıt uçları satırı yalnızca `Id` ile +güncellediği için aynı kural yazma tarafında prosedürle uygulanır. Kural dışı istek +`THROW 51000–51005` ile reddedilir. + +| Aktör | Sahiplik | Değerlendirme kaydı | Hedef / Yetkinlik | Gelişim planı | 360 | +| --- | --- | --- | --- | --- | --- | +| Çalışan | `EmployeeId = kullanıcı` | GoalSetting, SelfReview | GoalSetting, SelfReview | Her aşama (yalnız ilerleme/not) | — | +| Yönetici | `ManagerId = kullanıcı` | GoalSetting, SelfReview, ManagerReview | aynı | Her aşama | — | +| Değerlendirici | `Feedback.ReviewerId = kullanıcı` | — | — | — | GoalSetting → ManagerReview arası | +| İK | — | Serbest | Serbest | Serbest | Serbest | + +Dönem `Closed` ise İK dışındaki her yazma reddedilir. "Gelişim Planım" guard prosedüründen değil, +yalnızca satırın `EmployeeId`'sini denetleyen komuttan geçer (`THROW 51020`); aksiyon dönemden +bağımsız olabildiği için kapalı dönemde de ilerleme güncellenebilir. + +**Alan kilidi:** persona ekranında çalışanın/yöneticinin değiştirmemesi gereken alanlar salt +okunur çizilir **ve** yazma yetkisi İK ekranının `.Create`/`.Update` yetkisine bağlanır; +sunucu, kullanıcının yetkisi olmayan alanı güncelleme isteğinden düşürür (`ListFormFieldManager.CanUpdate`). + +| Ekran | Düzenlenebilir alanlar | +| --- | --- | +| Değerlendirmelerim | `Status`, `SelfComment` | +| Hedeflerim | Yönetici yorumu ve gerçekleşme % dışında hepsi | +| Yetkinliklerim | `SelfLevelId`, `SelfComment` (ekleme/silme yok) | +| Gelişim Planım | `Status`, `Progress`, `EmployeeNote` (ekleme/silme yok) | +| Ekibimin Değerlendirmeleri | `Status`, `ManagerComment` | +| Ekip Hedefleri | Öz yorum ve gerçekleşme % dışında hepsi | +| Ekip Yetkinlikleri | Öz seviye ve öz yorum dışında hepsi (ekleme/silme var) | +| Ekip Gelişim Planı | Çalışan notu dışında hepsi | +| 360 Taleplerim | `Status`, `Comment`; puan satırlarında `LevelId`, `Comment` | +| Kalibrasyon | `Status`, `CalibratedScore`, `CalibrationNote` | + +#### 5.4 Kancalar + +| Ekran | Komut | Ne çalışır | +| --- | --- | --- | +| Dönemler | Insert/UpdateAfter | `Hr_S_PerformancePeriodActivate` — dönem **Active** ise kiracının aktif her kullanıcısına değerlendirme açar (var olana dokunmaz), dönemin yetkinlik setini eksik değerlendirmelere kopyalar, yeni açılanlara bildirim gönderir | +| Yetkinlik Seti | Insert/UpdateAfter | Aynı prosedür (sonradan eklenen yetkinlik açık değerlendirmelere eklenir) | +| Değerlendirme ekranları | InsertAfter / UpdateAfter | `Hr_S_PerformanceReviewAfterSave @rid, @kullanıcı, N'Hr' \| 'Employee' \| 'Manager'` | +| Persona ekranları | Insert/Update/DeleteBefore | `Hr_S_PerformanceGuard` | +| Hedef / Yetkinlik / 360 ekranları | After | `Hr_S_PerformanceReviewRecalc` | +| 360 (İK) | InsertBefore | Dönemde 360 kapalıysa ya da değerlendirici çalışanın kendisiyse reddeder | +| 360 (İK) | InsertAfter | `Hr_S_PerformanceFeedbackOpen` — değerlendirmenin yetkinlikleri için puan satırlarını açar, değerlendiriciye bildirim gönderir | +| 360 ekranları | UpdateAfter | `Status = Submitted` iken `SubmittedDate` damgalanır, puan yeniden hesaplanır | +| Gelişim planı ekranları | Insert/UpdateAfter | `Hr_S_DevelopmentPlanSync` — eğitime "Katıldı" işlenen ya da `Completed` aksiyonu %100 ve Tamamlandı yapar | + +Güncelleme komutunda `@Id` bir dizidir (`IN @Id` ile açılır); aktör `UpdateFieldsDefaultValue` +ile yazılan `@LastModifierId`'den okunur. Ekleme komutunda `@Id` tekildir, aktör `@CreatorId`'dir. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Her ekranın kök yetkisi + `.Create/.Update/.Delete/.Export/.Import/.Note` +Menüsüz alt formların yetkisi ana ekranın altındadır; menüsüz persona ekranlarının +(Değerlendirmelerim, Ekibimin Değerlendirmeleri, 360 Taleplerim) yetkisi menü dalı olmadığından +`App.Hr` grubunun kökündedir (deploy menüsüz ekranı böyle yazar). +**Hiçbir yetki role otomatik atanmaz** — rol ekranından verilir. + +Önerilen dağıtım: + +| Rol | Verilecek yetkiler | +| --- | --- | +| Tüm çalışanlar | `App.Hr.MyPerformanceReview` (+ `.Update`), `App.Hr.MyPerformanceGoal` (+ `.Create/.Update/.Delete`), `App.Hr.MyPerformanceCompetency` (+ `.Update`), `App.Hr.MyDevelopmentPlan` (+ `.Update`), `App.Hr.My360Feedback` (+ `.Update`), `App.Hr.My360FeedbackScore` (+ `.Update`) | +| Yöneticiler | Yukarıdakiler + `App.Hr.TeamPerformanceReview` (+ `.Update`), `App.Hr.TeamPerformanceGoal`, `App.Hr.TeamPerformanceCompetency`, `App.Hr.TeamDevelopmentPlan` (+ `.Create/.Update/.Delete`) | +| İK | `App.Hr.Performance` dalının tamamı + `App.Hr.PerformanceRating` | + +Persona ekranlarındaki kilitli alanlar İK ekranının yetkisine bağlı olduğundan, çalışan/yönetici +rolüne **İK ekranlarının `.Update`/`.Create` yetkisi verilmez**; verilirse persona ekranlarında +kilitli alanlar o kullanıcı için yazılabilir hâle gelir. + +Intranet widget'ı listenin okuma yetkisiyle görünür: Performansım `App.Hr.MyPerformanceReview`, +Ekibimin Performansı `App.Hr.TeamPerformanceReview`, 360 Taleplerim `App.Hr.My360Feedback`. Ayrı +widget yetkisi yoktur — listeyi açamayan kullanıcıya özet de gösterilmez. + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `AbpUsers` | Çalışan, yönetici, değerlendirici, mentor; departman/pozisyon kopyası | +| Kullanıcı detayı › Performans | Değerlendirmeler ve Gelişim Planları ekranları çalışana süzülmüş açılır (Personel Kaydı bölümü) | +| `Hr_T_Department`, `Hr_T_JobPosition` | Değerlendirmenin organizasyon kırılımı (Pivot/Chart) | +| `Hr_T_SkillType` / `Hr_T_Skill` / `Hr_T_SkillLevel` | Dönem yetkinlik seti, beklenen/öz/yönetici/360 seviyeleri, puan (`Progress`) | +| `Adm_T_UserSkill` | Tamamlanan değerlendirmenin yönetici seviyeleri kullanıcı profiline yazılır | +| `Hr_T_Training` / `Hr_T_TrainingParticipant` | Gelişim aksiyonu bir eğitime bağlanır; katılım "Katıldı" ise aksiyon tamamlanır | +| `Hr_T_Certificate` | Sertifika aksiyonları | +| Bildirimler | Tipler `PerformansDurumDegisti`, `Performans360Talebi`; kurallar `Custom` + `UiActivity`/`UiToast` (yalnız kanalı belirler). Metinler `App.Hr.Performance.Notification.{Status,Feedback}.{Subject,Message}` (TR), yer tutucular `[Employee]`, `[Period]`, `[Status]`. Yazan: `Hr_S_PerformanceNotify` | + +Bildirim alıcıları: → GoalSetting / SelfReview / Completed çalışana; → ManagerReview / Completed +yöneticiye; dönem aktivasyonunda yeni açılan her değerlendirmenin çalışanına; 360 eklenince +değerlendiriciye. + +--- + +### 8. Akış örneği + +1. İK **Yetkinlik Seti**'ni hazırlar (ör. İletişim → beklenen B2), **Dönemler**'de "2026 Yıl Sonu"nu + 60/40 ağırlık ve 360 açık olarak girer, durumu **Aktif** yapar → tüm aktif çalışanlara + değerlendirme açılır, yetkinlikler kopyalanır, çalışanlar bildirim alır. +2. İK **Tüm Değerlendirmeler**'de her kaydın **Yönetici**'sini seçer. +3. Çalışan Intranet panosundaki **Performansım** widget'ından **Değerlendirmelerim**'i açar, + **Hedeflerim**'de hedeflerini girer (ağırlık toplamı 100). +4. Yönetici **Ekibimin Performansı** widget'ından **Ekibimin Değerlendirmeleri**'ni açar, hedefleri gözden geçirir, durumu **Öz Değerlendirme** + yapar → çalışan bildirim alır. +5. Çalışan gerçekleşenleri, öz seviyelerini ve yorumunu girer, durumu **Yönetici Değerlendirmesi** + yapar → yönetici bildirim alır. +6. İK 360 sekmesinde değerlendirici ekler → değerlendiriciler panodaki **360 Taleplerim** widget'ından talebi açıp puanlayıp gönderir. +7. Yönetici seviyeleri ve yorumu girer, gelişim aksiyonu planlar (ör. "İleri Excel" eğitimi), + durumu **Kalibrasyon** yapar. +8. İK **Kalibrasyon**'da dağılımı (Chart/Pivot, derece × departman) hedef dağılımla karşılaştırır, + gerekenlerin **Kalibre Puan**ını girer, durumu **Tamamlandı** yapar → derece kesinleşir, + yetkinlikler `UserSkill`'e yazılır, çalışan ve yönetici bildirim alır. +9. Çalışan eğitime "Katıldı" işlendiğinde gelişim aksiyonu bir sonraki kayıtta kendiliğinden tamamlanır. + +--- + +### 9. Sık sorulanlar + +**Durumu değiştirdim ama kayıt eski aşamaya döndü.** O geçiş sizin rolünüze açık değil (§5.2) ya da +hedef belirlemeden çıkarken ağırlık toplamı 100 değil. Geçersiz geçiş hata vermez, geri alınır. + +**"Değerlendirme bu aşamada bu işlem için açık değil" hatası.** Guard tablosu (§5.3): çalışan +yönetici değerlendirmesi başladıktan sonra hedef/yetkinlik değiştiremez; kalibrasyon ve sonrası +yalnız İK'dadır; dönem kapalıysa yalnız İK yazar. + +**Genel puan neden hedef puanından düşük/yüksek?** Genel = (Hedef × GoalWeight + Yetkinlik × +CompetencyWeight) / 100. Yetkinlik puanı yalnızca yönetici seviyesinden gelir; öz seviye ve 360 +puana girmez. + +**Gerçekleşme %150'de kalıyor.** Tavan bilinçlidir (§2.3, karar 6). + +**Derece boş.** Kiracıda derece ölçeği tanımlı değil. Host seed'i (`data/App.Hr.PerformanceRating.json`) +host içindir; her kiracı İK › Tanımlar › Performans Dereceleri'ni kendisi girer. + +**Teknik yetkinlikte seviye listesi boş.** Seed'de "Technical Skills" tipine seviye tanımlı değildir +(Organizasyon ve Yetkinlik bölümü §9). İK › Tanımlamalar › Yetenek Tipleri › Teknik Yetenekler › Seviyeler'e +`Progress` değerli seviyeler eklenmeden bu yetkinlikler puanlanamaz. + +**Yöneticiyi kim belirliyor?** İK, değerlendirme kaydındaki `ManagerId` alanından. Platformda +kullanıcı/departman üzerinde yönetici ilişkisi yoktur (§2.2). + +**Yeni işe giren çalışana değerlendirme nasıl açılır?** Aktif dönem kaydını yeniden kaydetmek +eksik değerlendirmeleri açar; ya da İK Tüm Değerlendirmeler'den elle ekler. + +**360 puanı neden genel puanda yok?** Karar 7: bilgi amaçlıdır; `Feedback360Score` olarak gösterilir. + +**Bildirim gelmiyor.** Kiracıda `PerformansDurumDegisti` / `Performans360Talebi` tipi ve `Custom` +kuralları olmalı; yeni kiracıya host seed'inden kopyalanır, mevcut kiracıda Administration › +Bildirimler'den eklenir. + +**Değerlendirmelerim / Ekibimin Değerlendirmeleri menüde yok.** Bilinçli: İK menüsü İK içindir (§2.4). +Çalışan ve yönetici Intranet › Dashboard'daki widget'tan açar. Widget görünmüyorsa rolüne liste +yetkisi verilmemiştir (§6) ya da kullanıcı widget'ı panoda gizlemiştir (tasarım modundan geri açılır). + +**Çalışan kendi gelişim aksiyonunu ekleyemiyor.** "Gelişim Planım" ekleme kapalıdır; aksiyonu +yönetici (Ekip Gelişim Planı) ya da İK açar. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_Performance{Rating,Period,PeriodSkill,Review,Goal,Competency,Feedback,FeedbackScore}.sql`, `Hr_T_DevelopmentPlan.sql` | Tablolar, CHECK ve tekil indeksler | +| `configs/seeds/sql/object/Hr_S_Performance{Notify,ReviewRecalc,PeriodActivate,Guard,ReviewAfterSave,FeedbackOpen}.sql`, `Hr_S_DevelopmentPlanSync.sql` | Prosedürler | +| `configs/seeds/wizard/{PerformanceRating,PerformancePeriodSkill,PerformancePeriod,PerformanceGoal,PerformanceCompetency,PerformanceFeedbackScore,PerformanceFeedback,ReviewDevelopmentPlan,PerformanceReview,MyPerformanceGoal,MyPerformanceCompetency,MyDevelopmentPlan,MyPerformanceReview,TeamPerformanceGoal,TeamPerformanceCompetency,TeamDevelopmentPlan,TeamPerformanceReview,My360FeedbackScore,My360Feedback,PerformanceCalibration,DevelopmentPlan}.json` | 21 wizard (List) | +| `configs/seeds/data/App.DeveloperKit.CustomComponents/{b2d9fa60-b052-5039-a0fc-146f4e5b2e8c,98a5c0b9-c8d6-5e83-ae76-d9ccb5b70cba,d669129d-52fe-56e1-972d-d20fe1b3360e}.json` | `MyPerformanceWidget`, `TeamPerformanceWidget`, `My360FeedbackWidget` (code modu, rotasız) | +| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json` | `my-performance`, `team-performance`, `my-360-feedback` pano kayıtları | +| `configs/seeds/data/App.Hr.PerformanceRating.json` | 5 kademeli derece ölçeği | +| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları (wizard'lara ait) | +| `configs/seeds/data/App.Notifications.Notification{Types,Rules}.json` | 2 tip, 4 kural | +| `ui/safelist.txt` | Widget bileşenlerinin Tailwind sınıfları (`twSafelistGenerator` derlemede yeniler) | + +Kurulum: DB Migrate (tablolar/prosedürler `sql/object`, ekranlar `WizardDataSeeder`, satırlar +`ListFormSeedDataApplier`). Ardından rollere yetki verilir (§6). + +Geri alma: Wizard Manager'dan talebin wizard'ları silinir (alt formlar önce); tabloyu düşürmek +yalnızca onayda seçilirse olur. Widget bileşenleri ve pano kayıtları, bildirim tip/kural satırları, derece seed'i ve +`Hr_S_*` prosedürleri elle kaldırılır. `Adm_T_UserSkill`'e yazılmış seviyeler kullanıcı verisidir, +geri alınmaz. + + +## Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) + +Personel disiplin süreci: olay tutanağı (personel, tarih/saat/yer, tanıklar, tutanağı tutan) → +savunma talebi ve savunma → karar (ceza türü, yürürlük/tebliğ, ücret kesintisi) → belgeler. Tamamı +konfigürasyondur (Wizard + SQL); entity, migration ya da React kodu yoktur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| İK / disiplin kurulu sekreteryası | Dosya açar, tutanağı yazar, savunma ister, savunmayı ve kararı işler, belgeleri yükler, dosyayı kapatır | Disiplin Dosyaları | +| Yönetici (tutanağı tutan) | Olayı kaydeder | Disiplin Dosyaları | +| İK yöneticisi | Ceza türü tanımlarını yönetir | İK › Tanımlar › Ceza Türleri | + +Kapsam: kiracı (`IsTenant`). Satır süzmesi yoktur; disiplin kaydı hassas veridir, görünürlük yalnızca yetkiyle sınırlanır. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, +> SQL, seed, commit `130e23bc` "Disiplin Dosyaları, Çalışma Takvimi") okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Tek menü ekranı (dosya) + üç menüsüz alt form: Savunmalar, Kararlar, Belgeler | +| Menü yeri | Dosya ekranı doğrudan `İnsan Kaynakları` kökünde; ceza türü İK › Tanımlar'da | +| Dosya durumu | Open → AwaitingDefense → Decided → Closed; **elle** değiştirilir (Todo panosunda sürükleyerek ya da formdan). Savunma/karar girilmesi durumu otomatik değiştirmez | +| Savunma süresi | Son savunma tarihi = talep tarihi + **2 gün** (formda önerilir, değiştirilebilir); talep tarihinden önce olamaz | +| Ceza türü | Ağırlık (`Severity` 1–5) sırasıyla listelenir; karar ekranında yalnız aktif türler | +| Ücret kesintisi | Kararda tutar olarak saklanır; bordroya aktarım yoktur | +| Tanıklar | Çok değerli kullanıcı seçimi (`WitnessUserIds`, `dxTagBox`) | +| Dosya numarası | `DSP-YYYY-00001` (kiracı + yıl bazında, insert sonrası SQL) | +| Onay akışı, bildirim, rapor | Yok | + +--- + +### 3. Menü ve ekranlar + +| Menü (TR / EN) | `ListFormCode` | Yer | Alt formlar | Görünümler | Widget'lar | +| --- | --- | --- | --- | --- | --- | +| Disiplin Dosyaları / Disciplinary Cases | `App.Hr.DisciplinaryCase` | `İnsan Kaynakları` (sıra 10, `FcHighPriority`) | `DisciplinaryDefense`, `DisciplinaryDecision`, `DisciplinaryFile` (`Id → CaseId`) | Grid, Card, Pivot, Chart, **Todo** | Toplam · Açık · Savunma Bekleniyor · Kapanan (Karara Bağlandı + Kapandı) | +| Ceza Türleri / Penalty Types | `App.Hr.DisciplinaryPenaltyType` | `İnsan Kaynakları › Tanımlar` | — | Grid, Card, Pivot, Chart | — (tanım listesi) | + +Todo panosu: başlık `Subject`, açıklama `IncidentDescription`, tarih `IncidentDate`, sütun sırası +`Open, AwaitingDefense, Decided, Closed`. + +Seed verisi (`data/App.Hr.DisciplinaryPenaltyType.json`): Sözlü Uyarı (1), Yazılı Uyarı (2), İhtar (3), +Kınama (3), Ücret Kesintisi (4), Fesih (5). + +--- + +### 4. Veri modeli + +``` +AbpUsers ──< Hr_T_DisciplinaryCase ──< Hr_T_DisciplinaryDefense + (UserId, ReportedById, ├──< Hr_T_DisciplinaryDecision >── Hr_T_DisciplinaryPenaltyType + WitnessUserIds) └──< Hr_T_DisciplinaryFile >── Hr_T_DocumentType +``` + +| Tablo | Önemli kolonlar | +| --- | --- | +| `Hr_T_DisciplinaryPenaltyType` | `Name`, `Severity`, `Description`, `IsActive` | +| `Hr_T_DisciplinaryCase` | `CaseNo`, `UserId`, `DepartmentId`, `JobPositionId`, `IncidentDate`, `IncidentTime`, `IncidentPlace`, `ReportedById`, `Status`, `Subject`, `IncidentDescription` (HTML tutanak), `WitnessUserIds` | +| `Hr_T_DisciplinaryDefense` | `CaseId`, `RequestDate`, `DueDate`, `ResponseDate`, `Status` (Requested/Submitted/NotSubmitted), `DefenseText` (HTML) | +| `Hr_T_DisciplinaryDecision` | `CaseId`, `DecisionDate`, `PenaltyTypeId`, `EffectiveDate`, `NotificationDate`, `DeductionAmount`, `Status` (Draft/Final), `DecisionText` (HTML) | +| `Hr_T_DisciplinaryFile` | `CaseId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` | + +Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır. + +--- + +### 5. İş kuralları ve hesaplar + +| Yer | Kural | +| --- | --- | +| Dosya — yeni kayıt | Olay tarihi bugün, tutanağı tutan oturumdaki kullanıcı, durum `Open` | +| Dosya — personel seçimi | Departman ve pozisyon kullanıcı kaydından kopyalanır (olay anındaki hâli saklanır) | +| Dosya — insert sonrası | `CaseNo = 'DSP-' + yıl + '-' + 5 hane` (kiracı + yıl içinde `MAX + 1`, yalnız boşsa) | +| Savunma — yeni kayıt | Talep tarihi bugün, durum `Requested`, son tarih talep + 2 gün | +| Savunma — tarih kontrolü | Son tarih talep tarihinden önceyse uyarı + değişiklik geri alınır | +| Karar — yeni kayıt | Karar tarihi bugün, durum `Draft` | +| Belge — yeni kayıt | Tarih bugün | + +Tavsiye edilen kullanım sırası: dosya `Open` → savunma istenince `AwaitingDefense` → karar +`Final` olunca `Decided` → tebliğ ve belgeler tamamlanınca `Closed`. Bu sıra sistemce zorlanmaz. + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. `App.Hr.DisciplinaryCase` kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; +`DisciplinaryDefense`, `DisciplinaryDecision`, `DisciplinaryFile` onun altındadır. Ceza türü +`App.Hr.Definitions` altındadır. Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. + +| Rol | Yetkiler | +| --- | --- | +| İK disiplin sorumlusu | Dosya + üç alt form (tam) + ceza türü | +| Tutanak tutan yönetici | `App.Hr.DisciplinaryCase` (+ `.Create`) — ancak bu yetki tüm dosyaları gösterir | + +Disiplin verisi kişisel ve hassas veridir; okuma yetkisi dar tutulmalıdır. + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `AbpUsers` | Personel, tutanağı tutan, tanıklar | +| Kullanıcı detayı › Disiplin | Disiplin Dosyaları ekranı çalışana süzülmüş açılır (Personel Kaydı bölümü) | +| `Hr_T_Department`, `Hr_T_JobPosition` | Olay anındaki birim (Pivot kırılımı) | +| `Hr_T_DocumentType` | Belge türü (ortak İK tanımı) | + +Bildirim, onay akışı, rapor şablonu ya da bordro bağlantısı yoktur. + +--- + +### 8. Akış örneği + +1. Vardiya amiri **Disiplin Dosyaları**'nda yeni dosya açar: personel seçilir (departman/pozisyon + dolar), olay tarihi/saati/yeri, konu, tutanak metni ve tanıklar girilir → `DSP-2026-00001`, durum Açık. +2. İK **Savunmalar** sekmesine savunma talebi ekler; son tarih 2 gün sonrası önerilir; dosya panoda + **Savunma Bekleniyor**'a çekilir. +3. Personel savunmasını verince talep **Savunma Verildi** yapılır, metin ve tarih girilir; verilmezse **Savunma Verilmedi**. +4. Kurul kararı **Kararlar** sekmesine girilir: ceza türü Yazılı Uyarı, yürürlük ve tebliğ tarihi, durum **Kesinleşti**; dosya **Karara Bağlandı**. +5. İmzalı tutanak, savunma ve tebliğ belgesi **Belgeler** sekmesine yüklenir; dosya **Kapandı** yapılır. + +--- + +### 9. Sık sorulanlar + +**Savunma/karar girdim, dosya durumu değişmedi.** Durum elle yönetilir; panoda sürükleyin ya da formdan seçin. + +**Son savunma tarihi neden 2 gün sonrası?** Formdaki varsayılan öneridir; değiştirilebilir, yalnızca talep tarihinden önce olamaz. + +**Ücret kesintisi bordroya yansıyor mu?** Hayır; karar kaydında bilgi olarak durur. + +**Tutanak metni listede görünmüyor.** HTML alan listede gizlidir; detayda ve Todo kartında görünür. + +**Bir yöneticinin yalnız kendi tuttuğu dosyaları görmesi mümkün mü?** Şu an değil (satır süzmesi yok). Gerekirse ayrı bir persona ekranı `DefaultFilter` (`"ReportedById" = '@USERID'`) ile açılır (Performans modülündeki kalıp). + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_Disciplinary{PenaltyType,Case,Defense,Decision,File}.sql` | Tablolar | +| `configs/seeds/wizard/Disciplinary{PenaltyType,Case,Defense,Decision,File}.json` | 5 wizard | +| `configs/seeds/data/App.Hr.DisciplinaryPenaltyType.json` | Ceza türleri | +| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | + +Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar (`DisciplinaryDefense`, `DisciplinaryDecision`, +`DisciplinaryFile`) önce, sonra `DisciplinaryCase` ve `DisciplinaryPenaltyType` silinir; tablolar +yalnızca onayda seçilirse düşer. + + +## Araçlar (`App.Hr.Vehicles`) + +Şirket araç filosu yönetimi: araç ve şoför kayıtları, araç/şoför belgeleri (ruhsat, sigorta, +muayene, ehliyet, psikoteknik), trafik cezaları ve kazalar, fatura bazlı araç masrafları ve +güvenlik kulübesinden araç giriş–çıkış takibi (km, süre, gidilen yer). Tamamı konfigürasyondur +(Wizard + SQL); entity, migration ya da React kodu yoktur. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Filo / idari işler sorumlusu | Araç, şoför, belge ve masraf tanımlarını yönetir; araç belgelerini ve masraf faturalarını girer | Araç Belgeleri · Araçlar · Gidilecek Yerler · Şoför Tanımlama · Masraf Tanımlama · Masraf Girişleri | +| Güvenlik personeli | Aracın çıkışını ve dönüşünü (km, saat, kullanan personel) kaydeder | Araç Giriş-Çıkış Takip | +| Yönetim | Dışarıdaki araç sayısı, toplam km ve masrafı izler | Widget'lar, Pivot, Chart | + +Kapsam: kiracı (`IsTenant`). Araç bir şubeye (tesis) bağlıdır; satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, +> SQL, seed, commit'ler `7be0b4ed` "Human Resources -> Araçlar" ve `021a8a34` "Araçlar düzenlemesi") +> okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Wizard ekranları; aracın altında Belgeler, şoförün altında Belgeler / Cezalar / Kazalar, masraf girişinin altında Kalemler (menüsüz alt formlar) | +| Belge tanımı | Tek tanım tablosu (`Hr_T_VehicleDocument`) iki eksenle ayrılır: **grup** (Vehicle / Driver) ve **tip** (Insurance, Document, Tax, Toll, Inspection, Maintenance, Penalty, Accident). Her alt form kendi kümesini süzer | +| Araç durumu | `Arrived` (Geldi — şirkette) / `Left` (Gitti — dışarıda); giriş–çıkış kaydından güncellenir | +| Araç km'si | `CurrentKm` giriş–çıkış kaydının giriş km'sinden güncellenir; yeni çıkışta önerilen çıkış km'si budur | +| Zimmet | Şoföre en fazla **5 araç** zimmetlenir (`Vehicle1Id`…`Vehicle5Id` sabit kolonlar) | +| Şoför km'si | Şoförün `TotalKm`'si, kullandığı tüm hareketlerin yapılan km toplamıdır (SQL) | +| Masraf | Fatura başlığı + kalemler; `Net Tutar = Miktar × Tutar × (1 − İskonto% / 100)` formda hesaplanır | +| Muayene/sigorta tarihleri | Araç kaydında başlangıç–bitiş tarihleri olarak tutulur; **hatırlatma/bildirim yoktur** | +| Hareket numarası | `MovementNo` kiracı bazında `MAX + 1` (insert sonrası SQL) | + +--- + +### 3. Menü ve ekranlar + +`İnsan Kaynakları › Araçlar` (`App.Hr.Vehicles`, ikon `FcAutomotive`) + +| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Widget'lar | +| --- | --- | --- | --- | --- | +| 1 | Araç Belgeleri / Vehicle Documents | `App.Hr.VehicleDocument` | — | Toplam · Aktif · Pasif | +| 2 | Masraf Tanımlama / Expense Definitions | `App.Hr.VehicleExpenseDefinition` | — | Toplam · Aktif · Pasif | +| 3 | Gidilecek Yerler / Destinations | `App.Hr.VehicleDestination` | — | Toplam · Aktif · Pasif | +| 4 | Araçlar / Vehicles | `App.Hr.Vehicle` | `VehicleFile` (`Id → VehicleId`) | Toplam · Geldi · Gitti · Pasif | +| 5 | Şoför Tanımlama / Drivers | `App.Hr.Driver` | `DriverDocument`, `DriverPenalty`, `DriverAccident` (`Id → DriverId`) | Toplam · Zimmetli Araçlı · Toplam Km | +| 6 | Araç Giriş-Çıkış Takip / Vehicle Gate Log | `App.Hr.VehicleMovement` | — | Toplam · Gitti · Bugün | +| 7 | Masraf Girişleri / Vehicle Expenses | `App.Hr.VehicleExpense` | `VehicleExpenseLine` (`Id → VehicleExpenseId`) | Toplam · Bugün · Toplam Tutar (net kalemler) | + +Tüm ekranlar Grid, Card, Pivot, Chart görünümleriyle gelir; özel görünüm (Todo, Scheduler) yoktur. + +Seed verisi: +- 17 belge tanımı (`data/App.Hr.VehicleDocument.json`). Örnekler: trafik sigortası, ruhsat, K2, MTV, OGS/HGS, egzoz/genel muayene, takograf (araç); sürücü belgesi, psikoteknik, SRC 4, kırmızı ışık ve hız cezası (şoför). +- 9 masraf tanımı (`data/App.Hr.VehicleExpenseDefinition.json`): sigorta, vergi, bakım, muayene ×2, geçiş ×2, ceza, yakıt. + +--- + +### 4. Veri modeli + +``` +Sas_T_Branch ──< Hr_T_Vehicle ──< Hr_T_VehicleFile >── Hr_T_VehicleDocument (grup Vehicle) + │ ▲ + │ └── Hr_T_Driver.Vehicle1..5Id ── AbpUsers (UserId) + │ ├──< Hr_T_DriverDocument >── VehicleDocument (grup Driver, ceza/kaza hariç) + │ ├──< Hr_T_DriverPenalty >── VehicleDocument (tip Penalty) + │ └──< Hr_T_DriverAccident >── VehicleDocument (tip Accident) + ├──< Hr_T_VehicleExpense ──< Hr_T_VehicleExpenseLine >── Hr_T_VehicleExpenseDefinition + │ └── Hr_T_VehicleDestination (firma) + └──< Hr_T_VehicleMovement >── AbpUsers (gönderen, güvenlik, kullanan), Hr_T_VehicleDestination +``` + +| Tablo | Önemli kolonlar | +| --- | --- | +| `Hr_T_VehicleDocument` | `DocumentGroup` (Vehicle/Driver), `DocumentType` (8 tip), `Name`, `IsActive` | +| `Hr_T_Vehicle` | `BranchId` (tesis), `Name`, `Brand`, `Model`, `BodyType`, `UsagePlace`, `RegistrationDate`, `PlateNumber`, `Status` (Arrived/Left), `CurrentKm`, muayene / sigorta / egzoz / takograf başlangıç–bitiş tarihleri, `IsActive` | +| `Hr_T_VehicleFile` | `VehicleId`, `VehicleDocumentId`, `FileName`, `FileContent` | +| `Hr_T_VehicleDestination` | `Name`, `Distance` (km), `IsActive` | +| `Hr_T_Driver` | `UserId`, `Vehicle1Id`…`Vehicle5Id`, `TotalKm` | +| `Hr_T_DriverDocument` | `DriverId`, `VehicleDocumentId`, `FileName`, `FileContent` | +| `Hr_T_DriverPenalty` | `DriverId`, `PenaltyDate`, `Amount`, `Description`, `VehicleDocumentId`, dosya | +| `Hr_T_DriverAccident` | `DriverId`, `AccidentDate`, `VehicleDocumentId`, `Description`, dosya | +| `Hr_T_VehicleExpenseDefinition` | `ExpenseType`, `Name`, `IsActive` | +| `Hr_T_VehicleExpense` | `VehicleId`, `InvoiceNo`, `InvoiceDate`, `DestinationId` (firma), `VehicleDocumentId`, dosya | +| `Hr_T_VehicleExpenseLine` | `VehicleExpenseId`, `ExpenseDefinitionId`, `DetailName`, `Quantity`, `Amount`, `DiscountRate`, `NetAmount`, `Description` | +| `Hr_T_VehicleMovement` | `MovementNo`, `ExitDate`, `ExitTime` (SS:dd metin), `BranchId`, `ExitKm`, `SenderUserId`, `SecurityUserId`, `DriverUserId`, `VehicleId`, `DestinationId`, `Reason`, `Location`, `EntrySecurityUserId`, `EntryDate`, `EntryBranchId`, `EntryTime`, `EntryKm`, `TravelledKm`, `Status`, `DurationMinutes`, `ExpectedKm` | + +Tablo düzeyinde CHECK ya da tekil indeks yoktur (plaka tekilliği zorlanmaz); kurallar form ve SQL'dedir. + +--- + +### 5. İş kuralları ve hesaplar + +#### 5.1 Giriş–çıkış (`App.Hr.VehicleMovement`) + +Form script'leri: + +| Olay | Kural | +| --- | --- | +| Form açılışı | Çıkış tarihi bugün, çıkış saati şimdi, durum `Left` | +| Araç seçimi | `ExpectedKm` = aracın `CurrentKm`'si; çıkış km boşsa aynı değer yazılır | +| Çıkış km | `ExpectedKm`'den küçükse uyarı + `ExpectedKm` yazılır; giriş km varsa yapılan km yeniden hesaplanır | +| Giriş km | Çıkış km'den küçükse uyarı + geri alınır. Doluysa durum `Arrived`, `TravelledKm = EntryKm − ExitKm`, giriş tarihi/saati boşsa şimdi. Boşsa durum `Left`, yapılan km boş | +| Tarih/saat değişimi | `DurationMinutes` = giriş − çıkış (dakika; saat `SS:dd` biçiminde olmalı) | + +Sunucu komutları: + +| Komut | Etki | +| --- | --- | +| Insert sonrası | `MovementNo` atanır; aracın `Status`'u ve (giriş km varsa) `CurrentKm`'si hareketten yazılır; kullanan personelin şoför kaydındaki `TotalKm` yeniden toplanır | +| Delete sonrası | Şoför `TotalKm` yeniden toplanır; aracın `CurrentKm`'si son girişin km'sine, `Status`'u son hareketin durumuna döner (hareket yoksa `Arrived`) | +| Update sonrası | **Yok** — bkz. §9 | + +#### 5.2 Masraf + +`NetAmount = round(Quantity × Amount × (1 − DiscountRate / 100), 2)`; miktar, tutar ya da iskonto +değişince formda hesaplanır. Fatura tarihi yeni kayıtta bugündür. "Toplam Tutar" widget'ı +silinmemiş tüm kalemlerin toplamıdır. + +#### 5.3 Belge süzmesi + +| Ekran | Listelenen belge tanımları | +| --- | --- | +| Araç › Belgeler, Masraf Girişi | `DocumentGroup = 'Vehicle'` | +| Şoför › Belgeler | `DocumentGroup = 'Driver'` ve tip `Penalty`/`Accident` dışı | +| Şoför › Cezalar | `DocumentType = 'Penalty'` | +| Şoför › Kazalar | `DocumentType = 'Accident'` | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Vehicles` ara yetkisinin +altında yedi ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; alt formlar (`VehicleFile`, +`DriverDocument`, `DriverPenalty`, `DriverAccident`, `VehicleExpenseLine`) ana ekranlarının altındadır. +Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. + +| Rol | Yetkiler | +| --- | --- | +| Filo sorumlusu | `App.Hr.Vehicles` dalının tamamı | +| Güvenlik | `App.Hr.VehicleMovement` (+ `.Create/.Update`) | +| Muhasebe (masraf) | `App.Hr.VehicleExpense`, `App.Hr.VehicleExpenseLine` | + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `Sas_T_Branch` | Aracın tesisi; hareketin çıkış/giriş şubesi | +| `AbpUsers` | Şoför, gönderen personel, güvenlik personeli, kullanan personel | + +Bildirim, zamanlanmış iş ya da rapor şablonu yoktur. + +--- + +### 8. Akış örneği + +1. Filo sorumlusu **Araçlar**'a "34 ABC 123"ü girer (şube Merkez, km 45.000, muayene/sigorta bitiş + tarihleri); **Belgeler** sekmesine ruhsat ve trafik sigortasını yükler. +2. **Şoför Tanımlama**'da personeli şoför yapar, aracı zimmet 1'e bağlar; sürücü belgesini yükler. +3. Güvenlik **Araç Giriş-Çıkış Takip**'te yeni kayıt açar: tarih/saat dolar, araç seçilince çıkış + km 45.000 olur; kullanan personel ve gidilen yer seçilir → araç **Dışarıda**. +4. Dönüşte giriş km'si (45.180) girilir → durum Şirkette, yapılan km 180, süre dakika olarak hesaplanır. +5. Yakıt faturası **Masraf Girişleri**'ne başlık + kalem (yakıt, 40 lt × 45 ₺) olarak girilir. +6. Gelen hız cezası şoförün **Cezalar** sekmesine tutar ve belgeyle eklenir. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Plakası aynı iki araç girilebiliyor mu?** Evet; tabloda tekil kısıt yoktur. + +**Muayene/sigorta bitişi yaklaşınca uyarı geliyor mu?** Hayır; tarihler yalnızca kayıttadır. +Hatırlatma için zamanlanmış iş + bildirim tipi eklenmelidir (yok). + +**Bir şoföre 5'ten fazla araç zimmetlenebilir mi?** Hayır; kolonlar sabittir. + +**Masraf girişindeki "Firma Adı" neden Gidilecek Yerler'den geliyor?** Masraf firması ayrı bir +tanım olarak açılmamış, gidilecek yer tanımı kullanılmıştır. + +**Kontrol edilmeli — dönüş güncellemeyle girildiğinde araç/şoför güncellenmiyor.** Giriş–çıkış +ekranında yalnızca insert ve delete sonrası komut vardır. Çıkış kaydı açılıp dönüş **aynı kaydı +düzenleyerek** girildiğinde aracın `Status`/`CurrentKm`'si ve şoförün `TotalKm`'si güncellenmez +(bir sonraki ekleme ya da silmeye kadar). + +**Kontrol edilmeli — yalnız çıkış girilen kayıtta aracın km'si.** Formda `EntryKm` varsayılanı +`0`'dır. Insert sonrası komut `@EntryKm` boş değilse aracın `CurrentKm`'sini ona eşitler. Giriş km +temizlenmeden kaydedilen bir çıkış kaydı aracın km'sini 0'a çekebilir. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_{VehicleDocument,Vehicle,VehicleFile,VehicleDestination,Driver,DriverDocument,DriverPenalty,DriverAccident,VehicleExpenseDefinition,VehicleExpense,VehicleExpenseLine,VehicleMovement}.sql` | Tablolar | +| `configs/seeds/wizard/{VehicleDocument,Vehicle,VehicleFile,VehicleDestination,Driver,DriverDocument,DriverPenalty,DriverAccident,VehicleExpenseDefinition,VehicleExpense,VehicleExpenseLine,VehicleMovement}.json` | 12 wizard | +| `configs/seeds/data/App.Hr.{VehicleDocument,VehicleExpenseDefinition}.json` | Tanım verisi | +| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | + +Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar önce, ana ekranlar sonra silinir; +tablolar yalnızca onayda seçilirse düşer. + + +## Ziyaretçiler (`App.Hr.Visitor`) + +Güvenlik/resepsiyon için ziyaretçi giriş–çıkış defteri: kim, hangi firmadan, kimi ziyarete, ne +zaman geldi, hangi kartı aldı, ne zaman çıktı. Tamamı konfigürasyondur (tek Wizard ekranı). + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Güvenlik / resepsiyon | Ziyaretçiyi girişte kaydeder, kart verir, çıkışta çıkış saatini işler | Ziyaretçiler | +| İK / idari işler | Günlük ziyaretçi sayısını, içeride kalanları ve geçmişi izler | Ziyaretçiler (widget, Pivot) | + +Kapsam: kiracı (`IsTenant`). Her kayıt bir şubeye bağlıdır; satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar wizard ve SQL'den okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Tek Wizard liste ekranı | +| Ziyaretçi kimliği | Ziyaretçi ayrı bir kişi kartı değildir; her ziyaret satırında ad soyad serbest metindir (tekrar gelen ziyaretçi yeniden yazılır) | +| Firma | Serbest metin + **otomatik tamamlama** (daha önce girilen firma adlarından) | +| Ziyaretçi tipi | Sabit liste: Ziyaretçi, Müşteri, Tedarikçi, Taşeron, Kurye (değerler Türkçe anahtardır) | +| İçeride mi? | `ExitTime` boşsa ziyaretçi içeride sayılır | +| Bildirim | Ziyaret edilen personele bildirim **gönderilmez** | + +--- + +### 3. Menü ve ekran + +| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar (bugün) | +| --- | --- | --- | --- | --- | +| Ziyaretçiler / Visitors | `App.Hr.Visitor` | `İnsan Kaynakları` (sıra 12, `FcBusinessman`) | Grid, Card, Pivot, Chart | Bugün Gelen · İçeride · Çıkış Yapan | + +Widget'lar yalnız **bugünün** (`VisitDate = bugün`) kayıtlarını sayar. + +--- + +### 4. Veri modeli + +`Hr_T_Visitor` (`sql/object/Hr_T_Visitor.sql`, entity yok): + +| Kolon | Açıklama | +| --- | --- | +| `BranchId` | Şube (zorunlu) | +| `VisitorType` | Ziyaretçi tipi (varsayılan "Ziyaretçi") | +| `VisitDate` | Ziyaret tarihi | +| `EntryTime` / `ExitTime` | Giriş / çıkış zamanı (`datetime`) | +| `CardNo` | Verilen ziyaretçi kartı | +| `VisitorFullName` | Ziyaretçi adı soyadı (zorunlu) | +| `VisitedUserId` | Ziyaret edilen personel (`AbpUsers`, zorunlu) | +| `CompanyName` | Firma | +| `VisitReason` | Ziyaret sebebi | + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Yeni kayıt | Ziyaret tarihi bugün, giriş saati şimdi, tip "Ziyaretçi" | +| Çıkış | Kayıt düzenlenip çıkış saati girilir; otomatik çıkış yoktur | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`; `App.Hr.Visitor` + `.Create/.Update/.Delete/.Export/.Import/.Note`. +Güvenliğe kök + `.Create/.Update` yeter. Hiçbir yetki role otomatik atanmaz. Ziyaretçi adı kişisel +veridir; saklama süresi için periyodik temizlik yoktur. + +--- + +### 7. Entegrasyonlar + +`Sas_T_Branch` (şube), `AbpUsers` (ziyaret edilen personel). Bildirim, rapor ya da zamanlanmış iş yoktur. + +--- + +### 8. Akış örneği + +1. Tedarikçi temsilcisi gelir; güvenlik yeni kayıt açar (tarih/saat dolu), tip Tedarikçi, ad soyad, + firma (otomatik tamamlamadan), ziyaret edilen satın alma uzmanı, kart no 12. +2. "İçeride" kartı 1 artar. +3. Çıkışta kayıt açılıp çıkış saati girilir; "Çıkış Yapan" kartı artar. + +--- + +### 9. Sık sorulanlar + +**Tekrar gelen ziyaretçinin bilgileri neden dolmuyor?** Ziyaretçi kartı yoktur; yalnız firma adı otomatik tamamlanır. + +**Gün sonunda içeride kalanlar nasıl görülür?** Bugünün "İçeride" kartı ya da `ExitTime` boş filtresi. + +**Ziyaret edilen kişiye haber gidiyor mu?** Hayır. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_Visitor.sql` | Tablo | +| `configs/seeds/wizard/Visitor.json` | Wizard | + +Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer. + + +## Olay Günlüğü (`App.Hr.EventLog`) + +Vardiya amiri, güvenlik odası ve gözlem odasının tuttuğu vardiya defteri: tarih–saat, kaynak, +olayı yaşayan/kaydeden personel, vardiya, önem derecesi (1–5) ve açıklama. Tamamı konfigürasyondur +(tek Wizard ekranı). + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Vardiya amiri / güvenlik / gözlem odası | Vardiyada yaşanan önemli olayları kaydeder | Olay Günlüğü | +| Yönetim / İK | Günün olaylarını ve önemli/kritik kayıtları izler; gerekirse disiplin dosyası açar | Olay Günlüğü (widget, Pivot) | + +Kapsam: kiracı (`IsTenant`). Şube isteğe bağlıdır; satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar wizard ve SQL'den okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Tek Wizard liste ekranı | +| Kaynak | Sabit liste: Vardiya Amiri (`ShiftSupervisor`), Güvenlik Odası (`SecurityRoom`), Gözlem Odası (`ObservationRoom`) | +| Önem | 1–5 yıldız: Rutin, Düşük, Önemli, Çok Önemli, Kritik; **4 ve üstü** "önemli" kartında sayılır | +| Saat | `EventTime` `SS:dd` metin; yeni kayıtta şimdiki saat | +| Vardiya | Vardiya tanımından seçilir (`Hr_T_Shift`) | +| Disiplin bağı | Olaydan disiplin dosyasına otomatik geçiş **yoktur**; dosya elle açılır | + +--- + +### 3. Menü ve ekran + +| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | +| --- | --- | --- | --- | --- | +| Olay Günlüğü / Event Log | `App.Hr.EventLog` | `İnsan Kaynakları` (sıra 13, `FcViewDetails`) | Grid, Card, Pivot, Chart | Toplam · Bugün · Önemli (önem ≥ 4) | + +--- + +### 4. Veri modeli + +`Hr_T_EventLog` (`sql/object/Hr_T_EventLog.sql`, entity yok): + +| Kolon | Açıklama | +| --- | --- | +| `LogSource` | Kayıt kaynağı (zorunlu) | +| `BranchId` | Şube | +| `UserId` | Vardiya amiri / olayı yaşayan personel (zorunlu) | +| `EventDate`, `EventTime` | Olay tarihi ve saati (zorunlu) | +| `Importance` | 1–5 (varsayılan 1) | +| `ShiftId` | Vardiya | +| `Description` | Açıklama | + +--- + +### 5. İş kuralları + +| Yer | Kural | +| --- | --- | +| Yeni kayıt | Olay saati boşsa şimdiki saat yazılır | +| Önem kartı | `Importance >= 4` | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`; `App.Hr.EventLog` + `.Create/.Update/.Delete/.Export/.Import/.Note`. +Kayıt tutanlara kök + `.Create` (ve gerekiyorsa `.Update`) yeter; silme yalnız yöneticide kalmalıdır. +Hiçbir yetki role otomatik atanmaz. + +--- + +### 7. Entegrasyonlar + +`Sas_T_Branch`, `AbpUsers`, `Hr_T_Shift` (bkz. Çalışma Takvimi ve Vardiyalar bölümü). Kritik olay için bildirim yoktur. + +--- + +### 8. Akış örneği + +1. Gece vardiyasında güvenlik odası "B kapısı alarmı" olayını kaynak Güvenlik Odası, önem 3, vardiya Gece ile kaydeder. +2. Vardiya amiri bir iş kazasını önem 5 ile girer → "Önemli" kartı artar. +3. Sabah İK önemli kayıtları süzer; gerekiyorsa Disiplin Dosyaları'nda elle dosya açar. + +--- + +### 9. Sık sorulanlar + +**Kritik olayda yöneticiye bildirim gidiyor mu?** Hayır; widget ve filtre ile izlenir. + +**Olay disiplin dosyasına bağlanabiliyor mu?** Hayır; iki kayıt arasında bağ yoktur. + +--- + +### 10. Dosyalar ve geri alma + +| Dosya | İçerik | +| --- | --- | +| `configs/seeds/sql/object/Hr_T_EventLog.sql` | Tablo | +| `configs/seeds/wizard/EventLog.json` | Wizard | + +Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer. + + +## Intranet (`App.Hr.Intranet`) + +Kurum içi iletişim: ana sayfa panosu (bugün doğanlar, dokümanlar, aktif anketler, sosyal duvar, +duyurular, yaklaşan etkinlikler), bunların yönetim ekranları (duyuru, anket, sosyal paylaşım, +etkinlik), doküman kütüphanesi ve kullanıcılar arası mesajlaşma. Bu modül **entity + C# seeder + +özel React sayfalarıyla** kuruludur (wizard değil); pano kutuları Developer Kit › Intranet Widgets +kaydıyla yönetilir. + +> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te +> buraya yansır (`lowcode.instructions.md` §0.13). + +--- + +### 1. Amaç ve kapsam + +| Persona | Ne yapar | Ekran | +| --- | --- | --- | +| Tüm çalışanlar | Panoyu görür; duyuru okur/beğenir/yorumlar, anket doldurur, paylaşım yapar, beğenir, yorumlar, ankete oy verir, etkinliği beğenir/yorumlar, doküman indirir, mesajlaşır | `/admin/dashboard` · mesajlaşma penceresi | +| İK / iç iletişim | Duyuru, anket (soru/seçenek), etkinlik ve tanımlarını yönetir; yanıtları ve etkileşimleri izler | İK › Intranet › Duyurular · Anketler · Sosyal Paylaşımlar · Etkinlik Türleri/Kategorileri · Etkinlikler | +| İK / doküman sorumlusu | Doküman yükler, yayına alır/kaldırır | İK › Intranet › Dokümanlar (`/admin/intranet-documents`) | +| Sistem yöneticisi | Pano kutularını (hazır ya da custom component) tanımlar, sırasını ve yetkisini belirler | Developer Kit › Intranet Widgets | + +Kapsam: kiracı. Bütün tablolar `IMultiTenant`; satır süzmesi yoktur. + +--- + +### 2. Analiz ve kararlar + +> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan +> (`ListFormSeeder_Hr.cs`, `Entities/Tenant/Hr/Intranet`, `IntranetAppService`, `views/intranet`) okunmuştur. + +| Konu | Karar | +| --- | --- | +| Yol | Yönetim ekranları entity + seeder ListForm'u; pano ve etkileşimler özel React + `IntranetAppService` | +| Modül yeri | Intranet İK'dadır: menü `App.Hr.Intranet`, yetkiler `App.Hr.Intranet.*`, tablolar `Hr_T_*`; pano kutusu kaydı (`Sas_T_IntranetWidget`) Saas › Developer Kit'te kalır | +| Pano kutuları | Veritabanı kaydıdır (kod, kolon, sıra, yetki, aktiflik). **Builtin** kutu koda kayıtlı React bileşenidir (`id` = kayıt `Code`); **Custom** kutu Developer Kit custom component'idir (Props JSON ile) | +| Kullanıcı yerleşimi | Pano tasarım modunda sürükle-bırak, gizle/göster, kolon oranı hazır ayarları; tercih **tarayıcıda (localStorage)** saklanır, sunucuya yazılmaz | +| Doğum günleri | Her pano isteğinde kullanıcıların `BirthDate` genişletme alanından canlı hesaplanır (gün + ay) | +| Duyuru panoda | Kutu yalnız **sabitlenmiş** (`IsPinned`) duyuruları, en fazla 3 tane gösterir | +| Anket | `Status = active` anketler; kullanıcı yanıtını sonradan **güncelleyebilir**; anonim ankette yanıt `UserId` taşımaz | +| Sosyal medya | Bir paylaşımda tek medya kaydı (resim(ler), video ya da anket); yüklenen dosya **base64 data URL** olarak `SocialMedia.Urls`'e yazılır | +| Doküman yayını | Fiziksel CDN klasörleri: `intranet` (yayında) ve `intranet/_passive` (yayında değil); yayına alma = klasörler arası taşıma | +| Mesajlaşma | Yalnız tablo öneki ile İK'dadır (`Hr_T_Messenger*`); menüsü/yetkisi yoktur, kabuk düzenine gömülü pencere + SignalR | +| Bildirim / zamanlanmış iş | Yok | + +--- + +### 3. Menü ve ekranlar + +`İnsan Kaynakları › Intranet` (`App.Hr.Intranet`, sıra 14) + +| Sıra | Menü | `ListFormCode` / rota | Alt formlar | Widget'lar | +| --- | --- | --- | --- | --- | +| 1 | Etkinlik Türleri | `App.Hr.Intranet.Events.EventType` | — | — | +| 2 | Etkinlik Kategorisi | `App.Hr.Intranet.Events.EventCategory` | — | — | +| 3 | Duyurular | `App.Hr.Intranet.Announcement` | `…Announcement.AnnouncementLike`, `…Announcement.AnnouncementComment` (`Id → AnnouncementId`) | Aktif · Sabitlenmiş · Süresi dolan · Toplam görüntülenme | +| 4 | Anketler | `App.Hr.Intranet.Survey` | `SurveyQuestion` (→ `SurveyQuestionOption`), `SurveyResponse` (→ `SurveyAnswer`) — iki seviyeli | Aktif · Pasif · Toplam yanıt | +| 5 | Sosyal Paylaşımlar | `App.Hr.Intranet.SocialPost` | `SocialComment`, `SocialMedia` (→ `SocialPollOption`), `SocialLike` (`Id → SocialPostId`) | Toplam · Bugün · Toplam beğeni | +| 6 | Etkinlikler | `App.Hr.Intranet.Events.Event` | `EventLike`, `EventComment` (`Id → EventId`) | Yaklaşan · Yayında · Taslak · İptal | +| 7 | Dokümanlar | `/admin/intranet-documents` (özel sayfa) | — | — | + +Diğer giriş noktaları: + +| Ne | Nerede | +| --- | --- | +| Pano | `/admin/dashboard` (`views/Dashboard.tsx` → `views/intranet/Dashboard.tsx`); rota yetkisizdir, menüde ayrı kaydı yoktur | +| Pano kutusu tanımı | Developer Kit › Intranet Widgets (`App.DeveloperKit.IntranetWidgets`, `Sas_T_IntranetWidget`); veri `data/App.DeveloperKit.IntranetWidgets.json`'a aynalanır | +| Mesajlaşma | Uygulama kabuğundaki `MessengerWidget` | + +Pano kutuları (seed): + +| Kod | Kolon / sıra | Yetki | Ne gösterir | +| --- | --- | --- | --- | +| `today-birthdays` | Sol / 10 | `AbpIdentity.Users.Widget` | Bugün doğanlar: avatar, ad, yaş, departman | +| `documents` | Sol / 20 | `App.Files.Widget` | Yayındaki ilk 3 doküman (tür, boyut, tarih, indir) | +| `active-surveys` | Sol / 30 | `App.Hr.Intranet.Survey.Widget` | Aktif anketler (kalan gün, soru/yanıt sayısı, doldurdum/doldur) | +| `my-leave` | Sol / 35 | `App.Hr.MyLeaveRequest` | Custom `MyLeaveWidget`: izin bakiyesi, süren talepler → İzin Talebi Oluştur · Taleplerim · Bakiyem | +| `team-leave` | Sol / 36 | `App.Hr.TeamLeaveRequest` | Custom `TeamLeaveWidget`: müdürün onayını bekleyen izin talepleri, bugün izinde olanlar → Onay Bekleyenler | +| `my-timesheet` | Sol / 37 | `App.Hr.MyTimesheet` | Custom `MyTimesheetWidget`: seçilen ayın puantajı (net saat, geç/erken dk, fazla mesai, devamsız/izinli/raporlu) ve yıl toplamı, 270 saatlik fazla mesai çubuğu → Puantajım | +| `social-wall` | Orta / 40 | `App.Hr.Intranet.SocialPost.Widget` | Sosyal duvar (Tümü / Paylaşımlarım, sonsuz kaydırma 10'arlı) | +| `announcements` | Sağ / 50 | `App.Hr.Intranet.Announcement.Widget` | Sabitlenmiş duyurular (en fazla 3) | +| `upcoming-events` | Sağ / 60 | `App.Hr.Intranet.Events.Event.Widget` | Bugünden sonraki yayınlanmış ilk 3 etkinlik | +| `my-performance` | Sağ / 70 | `App.Hr.MyPerformanceReview` | Custom `MyPerformanceWidget`: aktif performans değerlendirmesi, puanlar, gelişim aksiyonları → Değerlendirmelerim | +| `team-performance` | Sağ / 80 | `App.Hr.TeamPerformanceReview` | Custom `TeamPerformanceWidget`: yöneticinin ekip değerlendirmeleri → Ekibimin Değerlendirmeleri | +| `my-360-feedback` | Sağ / 90 | `App.Hr.My360Feedback` | Custom `My360FeedbackWidget`: kullanıcıya atanan 360 talepleri → 360 Taleplerim | + +İlk altı kutu Builtin'dir (koddaki `Code`). `my-leave` / `team-leave` İzin Yönetimi'nin (İzin Yönetimi bölümü §3.3), `my-timesheet` Puantaj ve Devam Takibi'nin (Puantaj ve Devam Takibi bölümü §3.3), son üçü Performans Yönetimi'nin çalışana ait özetleridir: +İK menüsü İK departmanınındır, çalışan kendi değerlendirmesini buradan takip eder; listeler menüsüzdür ve +kutudaki bağlantıyla açılır. Ayrıntı: Performans Yönetimi bölümü §3.3. + +--- + +### 4. Veri modeli + +Entity'ler `Entities/Tenant/Hr/Intranet` (`FullAuditedEntity, IMultiTenant`); tablolar migration'lıdır. + +| Tablo | Önemli kolonlar | Kural | +| --- | --- | --- | +| `Hr_T_Announcement` | `Title`, `Excerpt`, `Content` (HTML), `ImageUrl`, `Category` (general/event/urgent/announcement), `UserId`, `PublishDate`, `ExpiryDate`, `IsPinned`, `ViewCount`, `Likes`, `Attachments` | Başlık kiracıda tekil | +| `Hr_T_AnnouncementComment` / `Hr_T_AnnouncementLike` | `AnnouncementId`, `UserId`, (`Content`) | Beğeni kullanıcı başına tekil | +| `Hr_T_Survey` | `Title`, `Description`, `Deadline`, `Responses`, `Status`, `IsAnonymous` | Başlık kiracıda tekil | +| `Hr_T_SurveyQuestion` | `SurveyId`, `QuestionText`, `Type` (rating/multiple-choice/text/textarea/yes-no), `Order`, `IsRequired` | — | +| `Hr_T_SurveyQuestionOption` | `QuestionId`, `Text`, `Order` | — | +| `Hr_T_SurveyResponse` / `Hr_T_SurveyAnswer` | `SurveyId`, `UserId`, `SubmissionTime` / `ResponseId`, `QuestionId`, `QuestionType`, `Value` | — | +| `Hr_T_SocialPost` | `UserId`, `Content`, `LikeCount`, `IsLiked`, `IsOwnPost` | — | +| `Hr_T_SocialMedia` | `SocialPostId` (1:1), `Type` (image/video/poll), `Urls`, `PollQuestion`, `PollTotalVotes`, `PollEndsAt`, `PollUserVoteId` | — | +| `Hr_T_SocialPollOption` | `SocialMediaId`, `Text`, `Votes` | — | +| `Hr_T_SocialComment` / `Hr_T_SocialLike` | `SocialPostId`, `UserId`, (`Content`) | Beğeni kullanıcı başına tekil | +| `Hr_T_SocialLocation` | Konum bilgisi | Kullanan ekran/servis yok | +| `Hr_T_EventType` / `Hr_T_EventCategory` | `Name` | Kiracıda tekil | +| `Hr_T_Event` | `CategoryId`, `TypeId`, `Date`, `Name`, `Description`, `Place`, `Status` (published/draft/cancelled), `UserId`, `ParticipantsCount`, `Likes`, `isPublished`, `Photos` | `(CategoryId, TypeId, Name)` tekil | +| `Hr_T_EventComment` / `Hr_T_EventLike` | `EventId`, `UserId`, (`Content`) | Beğeni tekil | +| `Sas_T_IntranetWidget` | `Code`, `Name`, `LabelKey`, `SourceType` (0 Builtin / 1 Custom), `ComponentName`, `PermissionName`, `Column` (0 sol / 1 orta / 2 sağ), `Order`, `Props`, `IsActive` | Kod kiracıda tekil | +| `Hr_T_MessengerConversation` / `Hr_T_MessengerConversationMessage` | Konuşma (katılımcılar, son mesaj) / mesaj (gönderen, alıcılar, metin, ekler, zaman) | — | + +--- + +### 5. İş kuralları (`IntranetAppService`) + +| İşlem | Kural | +| --- | --- | +| Pano verisi | Doğum günleri (bugün), `intranet` klasöründeki dosyalar (`_passive` hariç), son 50 duyuru, `active` anketler + kullanıcının yanıtı, `isPublished` son 50 etkinlik, aktif ve yetkisi verilmiş pano kutuları. Duyuru için tarih/sabitleme süzmesi, anket için son tarih süzmesi **sunucuda yoktur** | +| Duyuru aç | Her açılışta `ViewCount + 1` | +| Beğeni (duyuru, paylaşım, etkinlik) | Aç/kapa: beğeni satırı eklenir/silinir, sayaç ±1 | +| Yorum | Satır eklenir; listelenirken yazar bilgisi doldurulur | +| Anket yanıtı | Kullanıcının önceki yanıtı varsa cevaplar güncellenir; yoksa yeni yanıt + `Responses + 1`; anonimde `UserId` boş | +| Paylaşım | İsteğe bağlı tek medya ya da 2–6 seçenekli anket; yalnız sahibi silebilir | +| Ankete oy | Seçenek ve toplam oy +1, `PollUserVoteId` = seçenek; tekrar oy UI'da engellenir | +| Doküman | Yüklemede görünen ad zorunlu (uzantı korunur); yayına al/kaldır = klasör taşıma; silme toplu | +| Mesaj | Aynı kiracıdaki aktif kullanıcılara (en fazla 100 kişi listelenir); en fazla 10 ek; çevrimiçi durumu SignalR (`/messengerhub`) | + +--- + +### 6. Yetki ve görünürlük + +İzin grubu `App.Hr`, modül `Sas|Hr`. Kök `App.Hr.Intranet`; her yönetim ekranının kökü + standart alt +yetkiler (`.Create/.Update/.Delete/.Export/.Import`, ana ekranlarda `.Note`). Duyuru, Anket, Sosyal +Paylaşım ve Etkinlik ayrıca **`.Widget`** taşır — pano kutusunu görme yetkisidir. Dokümanlar: +`App.Hr.Intranet.Document` + `.Create` (yükle) / `.Update` (yayına al/kaldır) / `.Delete`. +Intranet Widgets: `App.DeveloperKit.IntranetWidgets` (+ CRUD). Hiçbir yetki role otomatik atanmaz. + +Önerilen dağıtım: + +| Rol | Yetkiler | +| --- | --- | +| Tüm çalışanlar | `AbpIdentity.Users.Widget`, `App.Files.Widget`, dört `.Widget` yetkisi, `App.Hr.Intranet.Document` (okuma); performans kutuları için Performans Yönetimi bölümü §6 | +| İç iletişim | `App.Hr.Intranet` dalının tamamı | +| Sistem yöneticisi | `App.DeveloperKit.IntranetWidgets` | + +**Kontrol edilmeli — güvenlik:** `IntranetAppService`, `MessengerAppService` ve dosya yöneticisi servisi +yalnız oturum ister (`[Authorize]`); `App.Hr.Intranet.*` yetkilerini sunucuda denetlemez. Pano +kutularının yetkisi (`PermissionName`) sunucuda süzülür, doküman yetkileri ise **yalnız arayüzde** +uygulanır. + +--- + +### 7. Entegrasyonlar + +| Kaynak | Kullanım | +| --- | --- | +| `AbpUsers` (+ departman, pozisyon) | Doğum günleri, yazar/kullanıcı kartları, mesajlaşma rehberi | +| Dosya yöneticisi / CDN (`intranet`, `intranet/_passive`) | Doküman kütüphanesi ve pano doküman kutusu | +| Developer Kit › Custom Components | Custom pano kutuları | +| SignalR (`/messengerhub`) | Mesajlaşma ve çevrimiçi durumu | +| Organizasyon Şeması | Kullanıcı satırlarında sosyal duvarın `UserProfileCard` bileşenini kullanır | + +--- + +### 8. Akış örneği + +1. İç iletişim **Duyurular**'a "Yeni ofis açılışı"nı görsel ve HTML içerikle ekler, **sabitler** → panonun sağ kolonunda görünür. +2. **Anketler**'de "Çalışan Memnuniyet Anketi"ni anonim ve aktif açar; **Sorular** sekmesine puanlama, çoktan seçmeli (seçenekleriyle) ve metin soruları ekler. +3. Çalışan panoda anketi doldurur, sonradan yanıtını günceller; İK **Yanıtlar** sekmesinden sonuçları görür (anonimde kişi boş). +4. **Etkinlikler**'de "Jazz Akşamı" tarih, yer ve fotoğraflarla yayınlanır → "Yaklaşan Etkinlikler" kutusunda çıkar; çalışanlar beğenir/yorumlar. +5. Çalışan sosyal duvarda iki seçenekli bir anket paylaşır; diğerleri oy verir. +6. Doküman sorumlusu "İzin Prosedürü.pdf"i yükler ve yayına alır → pano doküman kutusunda indirilebilir olur. +7. Sistem yöneticisi Intranet Widgets'a bir custom component'i (ör. kurum KPI kartı) orta kolona ekler. + +--- + +### 9. Sık sorulanlar ve bilinen sınırlar + +**Duyuru panoda görünmüyor.** Kutu yalnız sabitlenmiş duyuruları (en fazla 3) gösterir; listelenmek için **Sabitle** işaretli olmalı. + +**Süresi dolmuş duyuru/anket hâlâ görünüyor.** Sunucuda son tarih süzmesi yoktur; duyuru sabitlemesi kaldırılmalı, anket `passive` yapılmalıdır. + +**Pano yerleşimim başka bilgisayarda yok.** Yerleşim tarayıcıda saklanır. + +**Pano kutusu görünmüyor.** Kayıt aktif olmalı ve kullanıcıda `PermissionName` yetkisi bulunmalı; Custom kutuda bileşen aktif olmalı. + +**Yanıtlarımı değiştirebilir miyim?** Evet; anketi tekrar açıp kaydetmek önceki yanıtı günceller. + +Kontrol edilmeli (koddan tespit edilenler): +- Ankete oy sunucuda kullanıcı bazında tutulmaz (`PollUserVoteId` tek kolon); aynı kullanıcı API'yi doğrudan çağırarak tekrar oy verebilir. +- `SocialPost.IsLiked` beğenen son kullanıcıya göre veritabanına yazılır; listelerken sunucu kullanıcıya göre yeniden hesaplar. +- Duyuru modalındaki ekler bölümü dizi bekler, `Attachments` metindir; ekler görünmeyebilir. +- Anket entity açıklaması `draft|active|closed` der, ekran `active|passive` sunar. +- Sosyal paylaşımda yüklenen medya base64 olarak veritabanına yazılır; büyük dosyalar tabloyu büyütür. +- `Hr_T_EventPhoto` tablosu ve `sql/object/Hr_T_EventPhoto.sql` yoktur (referans dokümanda geçer); etkinlik fotoğrafları `Hr_T_Event.Photos` kolonundadır. + +--- + +### 10. Dosyalar + +| Dosya | İçerik | +| --- | --- | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Hr.cs` | Yönetim ekranları | +| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs` | Intranet Widgets ekranı | +| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Hr/Intranet/*.cs`, `Entities/Tenant/Administration/IntranetWidget.cs`, `Entities/Tenant/Messenger*.cs` | Entity'ler | +| `api/src/Sozsoft.Platform.Application/Intranet/IntranetAppService.cs`, `Messenger/MessengerAppService.cs` | Servisler | +| `ui/src/views/intranet/Dashboard.tsx`, `widgets/*`, `SocialWall/*`, `documents/IntranetDocuments.tsx` | Pano, kutular, sosyal duvar, doküman sayfası | +| `ui/src/components/template/MessengerWidget.tsx` | Mesajlaşma penceresi | +| `configs/seeds/data/App.Hr.Intranet.*.json`, `App.DeveloperKit.IntranetWidgets.json` | Örnek veri ve pano kutuları | + +Örnek veri: +- 5 duyuru (3'ü sabitlenmiş). +- 3 anket, 10 soru ve 13 seçenek. +- 6 paylaşım: 4 medya (2 resim, 1 video, 1 anket), 8 yorum. +- 50 etkinlik türü, 5 kategori, 3 etkinlik ve 9 yorum. + + +## Ek — Ekran envanteri (otomatik) + +> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. + +### Tanımlamalar (`App.Hr.Definitions`) + +#### Yeterlilik Belgeleri — `App.Hr.Certificate` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Certificate.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.Certificate` (sıra 4) | +| Yetki | `App.Hr.Certificate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yeterlilik Belgeleri — personelin sahip olabileceği mesleki yeterlilik ve mezuniyet belgeleri. | +| Geliştirme talebi | Human Resources -> Definitions | +| Kaynak | `Hr_T_Certificate` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.Certificate.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Evrak Türleri — `App.Hr.DocumentType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DocumentType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.DocumentType` (sıra 5) | +| Yetki | `App.Hr.DocumentType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Evrak Türleri — personel ve süreç belgelerinin türleri (CV, dilekçe, ibraname, sağlık raporu…), gruplarıyla. | +| Geliştirme talebi | Human Resources -> Definitions | +| Kaynak | `Hr_T_DocumentType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive`, `App.Listform.ListformField.IsRequired` | +| Veri aynası | `data/App.Hr.DocumentType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `GroupName` | Dosya Grubu | dxSelectBox | ✓ | ✓ | liste: Genel, Özlük Evrakları, Sağlık | +| `Name` | Dosya Türü | dxTextBox | ✓ | ✓ | | +| `IsRequired` | Zorunlu | dxCheckBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Masraf Türleri — `App.Hr.ExpenseType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/ExpenseType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.ExpenseType` (sıra 9) | +| Yetki | `App.Hr.ExpenseType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Masraf Türleri — personel masraf kalemleri (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) ve vergi/SGK özellikleri. | +| Kaynak | `Hr_T_ExpenseType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | CurrencyId=TRY, IsTaxable=false, IsSgkSubject=false, RequiresReceipt=true, IsActive=true | +| Veri aynası | `data/App.Hr.ExpenseType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Code` | Kod | dxTextBox | ✓ | ✓ | | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `DefaultAmount` | Varsayılan Tutar | dxNumberBox | | ✓ | | +| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | +| `IsTaxable` | Gelir Vergisine Tabi | dxCheckBox | ✓ | ✓ | | +| `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | | +| `RequiresReceipt` | Fiş / Belge Gerekir | dxCheckBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Yan Hak Türleri — `App.Hr.BenefitType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/BenefitType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.BenefitType` (sıra 10) | +| Yetki | `App.Hr.BenefitType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yan Hak Türleri — çalışanlara sağlanan yan haklar (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk ve yakacak yardımı…). | +| Kaynak | `Hr_T_BenefitType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | CurrencyId=TRY, IsTaxable=false, IsSgkSubject=false, IsActive=true | +| Veri aynası | `data/App.Hr.BenefitType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Code` | Kod | dxTextBox | ✓ | ✓ | | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `DefaultAmount` | Varsayılan Tutar | dxNumberBox | | ✓ | | +| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | +| `IsTaxable` | Gelir Vergisine Tabi | dxCheckBox | ✓ | ✓ | | +| `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### İzin Türleri — `App.Hr.LeaveType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/LeaveType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.LeaveType` (sıra 12) | +| Yetki | `App.Hr.LeaveType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İzin Türleri — izin çeşitleri ve kuralları (yıllık, mazeret, ücretsiz, hastalık, doğum, babalık, evlilik, ölüm, süt izni). | +| Kaynak | `Hr_T_LeaveType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Paid`, `App.Widget.Unpaid` | +| Form varsayılanları | IsPaid=true, DeductsFromAnnualLeave=false, RequiresDocument=false, AllowHalfDay=false, Gender=All, IsActive=true, BalanceExceedAction=Block | +| Veri aynası | `data/App.Hr.LeaveType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Code` | Kod | dxTextBox | ✓ | ✓ | | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `Gender` | Cinsiyet | dxSelectBox | ✓ | ✓ | liste: All, Male, Female | +| `MaxDaysPerYear` | Yıllık En Fazla Gün | dxNumberBox | | ✓ | | +| `IsPaid` | Ücretli | dxCheckBox | ✓ | ✓ | | +| `DeductsFromAnnualLeave` | Yıllık İzinden Düşer | dxCheckBox | ✓ | ✓ | | +| `RequiresDocument` | Belge Gerekir | dxCheckBox | ✓ | ✓ | | +| `AllowHalfDay` | Yarım Gün Kullanılabilir | dxCheckBox | ✓ | ✓ | | +| `BalanceExceedAction` | Bakiye Aşılırsa | dxRadioGroup | ✓ | ✓ | liste: Block, Warn | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Kurum Doktorları — `App.Hr.Doctor` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Doctor.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.Doctor` (sıra 13) | +| Yetki | `App.Hr.Doctor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Kurum Doktorları — işyeri hekimleri ve belge bilgileri. | +| Geliştirme talebi | Human Resources -> Definitions | +| Kaynak | `Hr_T_Doctor` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.Doctor.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `FullName` | Doktor Adı Soyadı | dxTextBox | ✓ | ✓ | | +| `DiplomaNo` | Diploma No | dxTextBox | | ✓ | | +| `DiplomaDate` | Diploma Tarihi | dxDateBox | | ✓ | | +| `OhsCertificateNo` | İşyeri Hekimi Belge No | dxTextBox | | ✓ | | +| `OhsCertificateDate` | İşyeri Hekimi Belge Tarihi | dxDateBox | | ✓ | | +| `IdentityNo` | T.C. Kimlik No | dxTextBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Hastaneler — `App.Hr.Hospital` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Hospital.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.Hospital` (sıra 14) | +| Yetki | `App.Hr.Hospital` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Hastaneler — hastane ve sağlık kurumu tanımları. | +| Geliştirme talebi | Human Resources -> Definitions | +| Kaynak | `Hr_T_Hospital` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.Hospital.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Kurum Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Hastane Bölümleri — `App.Hr.HospitalDepartment` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HospitalDepartment.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.HospitalDepartment` (sıra 15) | +| Yetki | `App.Hr.HospitalDepartment` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Hastane Bölümleri — hastane klinik/bölüm tanımları (acil, dahiliye, kardiyoloji…). | +| Geliştirme talebi | Human Resources -> Definitions | +| Kaynak | `Hr_T_HospitalDepartment` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.HospitalDepartment.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Bölüm Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +### İşe Alım (`App.Hr.Recruitment`) + +#### Kadro Talepleri — `App.Hr.StaffRequest` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/StaffRequest.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.StaffRequest` (sıra 1) | +| Yetki | `App.Hr.StaffRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Kadro Talepleri — bir departmanın yeni ya da boşalan bir pozisyon için personel istemesi ve bu isteğin onay süreci. İşe alım sürecinin ilk adımıdır; ilan yalnızca onaylanmış talepten açılır. | +| Kaynak | `Hr_T_StaffRequest` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Pending`, `App.Hr.StaffRequest.Widget.Approved`, `App.Hr.StaffRequest.Widget.Headcount` | +| Komutlar | InsertAfter: SQL | +| Form varsayılanları | IsActive=true, RequestDate=@DATE, RequestedById=@USERID, Headcount=1, EmploymentType=FullTime, Reason=NewPosition, CurrencyId=TRY | +| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Onay Bekliyor' → Inform 'Onay Bilgisi' → Inform 'Ret Bilgisi' → End 'Onaylandı' → End 'Reddedildi' | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `RequestNo` | Talep No | dxTextBox | | ✓ | | +| `RequestDate` | Talep Tarihi | dxDateBox | ✓ | ✓ | | +| `RequestedById` | Talep Eden | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | +| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | +| `Headcount` | Kadro Adedi | dxNumberBox | ✓ | ✓ | | +| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | +| `ExpectedStartDate` | Beklenen Başlangıç | dxDateBox | | ✓ | | +| `Reason` | Talep Nedeni | dxRadioGroup | ✓ | ✓ | liste: NewPosition, Replacement · script | +| `ReplacedUserId` | Ayrılan Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `MinSalary` | Asgari Ücret | dxNumberBox | | ✓ | | +| `MaxSalary` | Azami Ücret | dxNumberBox | | ✓ | | +| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | +| `Qualifications` | Aranan Nitelikler | dxHtmlEditor | | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | +| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | +| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | +| `ApprovalDescription` | Onay Açıklaması | dxTextArea | | ✓ | | + +#### İlanlar — `App.Hr.JobPosting` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/JobPosting.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.JobPosting` (sıra 2) | +| Yetki | `App.Hr.JobPosting` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İlanlar — onaylanmış kadro taleplerinden açılan iş ilanları ve ilana gelen başvurular. | +| Kaynak | `Hr_T_JobPosting` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.JobApplication` (Id → JobPostingId) | +| Widget'lar | `App.Widget.Total`, `App.Widget.Published`, `App.Widget.Draft`, `App.Hr.JobPosting.Widget.Closed` | +| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | +| Form varsayılanları | IsActive=true, Status=Draft, Headcount=1, EmploymentType=FullTime, WorkModel=Office, PublishDate=@DATE | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PostingNo` | İlan No | dxTextBox | | ✓ | | +| `StaffRequestId` | Kadro Talebi | dxSelectBox | | ✓ | sorgu: Hr_T_StaffRequest · script | +| `Title` | İlan Başlığı | dxTextBox | ✓ | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Published, Closed, Cancelled | +| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | +| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | +| `Headcount` | Kadro Adedi | dxNumberBox | ✓ | ✓ | | +| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | +| `WorkModel` | Çalışma Modeli | dxSelectBox | ✓ | ✓ | liste: Office, Hybrid, Remote | +| `Location` | Lokasyon | dxTextBox | | ✓ | | +| `PublishDate` | Yayın Tarihi | dxDateBox | | ✓ | | +| `ClosingDate` | Son Başvuru Tarihi | dxDateBox | | ✓ | | +| `SourceIds` | Yayın Kanalları | dxTagBox | | ✓ | sorgu: Hr_T_CandidateSource | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `Description` | Açıklama | dxHtmlEditor | | ✓ | | +| `Requirements` | Aranan Nitelikler | dxHtmlEditor | | ✓ | | + +#### Adaylar — `App.Hr.Candidate` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Candidate.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.Candidate` (sıra 3) | +| Yetki | `App.Hr.Candidate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Adaylar — CV ve KVKK açık rızası ile tutulan aday havuzu. Bir aday birden fazla ilana başvurabilir. | +| Kaynak | `Hr_T_Candidate` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.JobApplication` (Id → CandidateId) | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive`, `App.Hr.Candidate.Widget.Converted` | +| Komutlar | UpdateAfter: SQL | +| Form varsayılanları | Country=Türkiye, IsActive=true, KvkkConsentDate=@NOW, KvkkConsentMethod=Written, CurrencyId=TRY | +| Butonlar | `App.Hr.Candidate.KvkkConsentForm` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Photo` | Fotoğraf | dxImageUpload | | ✓ | | +| `FirstName` | Adı | dxTextBox | ✓ | ✓ | | +| `LastName` | Soyadı | dxTextBox | ✓ | ✓ | | +| `Email` | E-posta | dxTextBox | ✓ | ✓ | | +| `PhoneNumber` | Telefon | dxTextBox | | ✓ | | +| `Gender` | Cinsiyet | dxSelectBox | | ✓ | liste: Male, Female | +| `BirthDate` | Doğum Tarihi | dxDateBox | | ✓ | | +| `Country` | Ülke | dxSelectBox | | ✓ | sorgu: Sas_H_Country | +| `City` | Şehir | dxSelectBox | | ✓ | sorgu: Sas_H_City (← Country) | +| `Address` | Adres | dxTextBox | | ✓ | | +| `EducationLevel` | Eğitim Düzeyi | dxSelectBox | | ✓ | liste: Primary, HighSchool, Associate, Bachelor, Master, Doctorate | +| `School` | Okul | dxTextBox | | ✓ | | +| `Major` | Bölüm | dxTextBox | | ✓ | | +| `GraduationYear` | Mezuniyet Yılı | dxNumberBox | | ✓ | | +| `ExperienceYears` | Deneyim (Yıl) | dxNumberBox | | ✓ | | +| `CurrentCompany` | Mevcut Firma | dxTextBox | | ✓ | | +| `CurrentTitle` | Mevcut Ünvan | dxTextBox | | ✓ | | +| `ExpectedSalary` | Ücret Beklentisi | dxNumberBox | | ✓ | | +| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | +| `SourceId` | Kaynak | dxSelectBox | | ✓ | sorgu: Hr_T_CandidateSource | +| `LinkedInUrl` | LinkedIn | dxTextBox | | ✓ | | +| `UserId` | Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `SkillIds` | Yetkinlikler | dxTagBox | | ✓ | sorgu: Hr_T_Skill | +| `CvDocument` | CV | dxImageUpload | | ✓ | | +| `Notes` | Notlar | dxTextBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `KvkkConsent` | Adayın KVKK kapsamında açık rızası alındı | dxCheckBox | ✓ | ✓ | | +| `KvkkConsentDate` | Rıza Tarihi | dxDateBox | ✓ | ✓ | | +| `KvkkConsentMethod` | Rıza Alma Yöntemi | dxSelectBox | ✓ | ✓ | liste: Written, Electronic, Email | +| `KvkkConsentDocument` | İmzalı Rıza Belgesi | dxImageUpload | | ✓ | | + +#### Başvurular — `App.Hr.JobApplication` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/JobApplication.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.JobApplication` (sıra 4) | +| Yetki | `App.Hr.JobApplication` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Başvurular — bir adayın bir ilana başvurusu ve başvurunun aşama takibi (kanban panosu). | +| Kaynak | `Hr_T_JobApplication` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.Interview` (Id → ApplicationId), `App.Hr.JobOffer` (Id → ApplicationId) | +| Todo | başlık `CandidateName`, durum `Stage` (Applied,Screening,Interview,Offer,Hired,Rejected) | +| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | +| Form varsayılanları | IsActive=true, ApplicationDate=@DATE, Stage=Applied, OwnerUserId=@USERID | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `CandidateId` | Aday | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Candidate · script | +| `JobPostingId` | İlan | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosting | +| `CandidateName` | Aday | dxTextBox | | | | +| `PostingTitle` | İlan | dxTextBox | | | | +| `ApplicationDate` | Başvuru Tarihi | dxDateBox | ✓ | ✓ | | +| `SourceId` | Kaynak | dxSelectBox | | ✓ | sorgu: Hr_T_CandidateSource | +| `OwnerUserId` | Sorumlu | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `AverageScore` | Ortalama Puan | dxNumberBox | | ✓ | | +| `Stage` | Aşama | dxSelectBox | ✓ | ✓ | liste: Applied, Screening, Interview, Offer, Hired, Rejected · script | +| `RejectionReasonId` | Ret Sebebi | dxSelectBox | | ✓ | sorgu: Hr_T_RejectionReason | +| `RejectionNote` | Ret Açıklaması | dxTextArea | | ✓ | | +| `SortOrder` | Sıralama | dxNumberBox | | | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `Notes` | Notlar | dxTextArea | | ✓ | | + +#### Mülakatlar — `App.Hr.Interview` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Interview.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.Interview` (sıra 5) | +| Yetki | `App.Hr.Interview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Mülakatlar — başvuru için mülakat planlama, mülakatçı ataması ve kriter bazlı puanlama. | +| Kaynak | `Hr_T_Interview` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Scheduler (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.InterviewScore` (Id → InterviewId) | +| Komutlar | InsertAfter: SQL · UpdateAfter: SQL · DeleteAfter: SQL | +| Form varsayılanları | IsActive=true, InterviewType=FaceToFace, Status=Planned, InterviewerUserId=@USERID | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ApplicationId` | Başvuru | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobApplication | +| `Title` | Başlık | dxTextBox | | | | +| `InterviewType` | Mülakat Türü | dxSelectBox | ✓ | ✓ | liste: Phone, Video, FaceToFace, Technical, Hr | +| `InterviewerUserId` | Mülakatçı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `StartDate` | Başlangıç | dxDateBox | ✓ | ✓ | script | +| `EndDate` | Bitiş | dxDateBox | ✓ | ✓ | | +| `Location` | Yer | dxTextBox | | ✓ | | +| `MeetingUrl` | Toplantı Bağlantısı | dxTextBox | | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, Completed, Cancelled, NoShow | +| `Recommendation` | Öneri | dxSelectBox | | ✓ | liste: Hire, Hold, Reject | +| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `Notes` | Notlar | dxTextArea | | ✓ | | + +#### Aday Kaynakları — `App.Hr.CandidateSource` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/CandidateSource.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.CandidateSource` (sıra 6) | +| Yetki | `App.Hr.CandidateSource` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Aday Kaynakları — adayların ve ilanların hangi kanaldan geldiğini/yayınlandığını tanımlayan liste (LinkedIn, Kariyer.net, referans, kariyer fuarı…). | +| Kaynak | `Hr_T_CandidateSource` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true | +| Veri aynası | `data/App.Hr.CandidateSource.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Teklifler — `App.Hr.JobOffer` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/JobOffer.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Recruitment` › `App.Hr.JobOffer` (sıra 6) | +| Yetki | `App.Hr.JobOffer` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Teklifler — işe alınması düşünülen adaya yapılan ücret ve şart teklifi, iç onayı ve teklif mektubu. | +| Kaynak | `Hr_T_JobOffer` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | +| Form varsayılanları | IsActive=true, OfferDate=@DATE, Status=Draft, CurrencyId=TRY, EmploymentType=FullTime, WorkModel=Office | +| Butonlar | `App.Hr.JobOffer.OfferLetter` | +| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Onay Bekliyor' → Inform 'Onay Bilgisi' → Inform 'Ret Bilgisi' → End 'Onaylandı' → End 'Reddedildi' | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `OfferNo` | Teklif No | dxTextBox | | ✓ | | +| `ApplicationId` | Başvuru | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobApplication · script | +| `CandidateName` | Aday | dxTextBox | | | | +| `OfferDate` | Teklif Tarihi | dxDateBox | ✓ | ✓ | | +| `ValidUntil` | Geçerlilik Tarihi | dxDateBox | | ✓ | | +| `StartDate` | İşe Başlama Tarihi | dxDateBox | | ✓ | | +| `GrossSalary` | Brüt Maaş | dxNumberBox | ✓ | ✓ | | +| `CurrencyId` | Para Birimi | dxSelectBox | ✓ | ✓ | sorgu: Sas_H_Currency | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Sent, Accepted, Declined, Expired · script | +| `ResponseDate` | Yanıt Tarihi | dxDateBox | | ✓ | | +| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | +| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | +| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | +| `WorkModel` | Çalışma Modeli | dxSelectBox | ✓ | ✓ | liste: Office, Hybrid, Remote | +| `BenefitCodes` | Yan Haklar | dxTagBox | | ✓ | sorgu: Hr_T_BenefitType | +| `Notes` | Notlar | dxTextBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | +| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | +| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | +| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | + +#### Ret Sebepleri — `App.Hr.RejectionReason` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/RejectionReason.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.RejectionReason` (sıra 7) | +| Yetki | `App.Hr.RejectionReason` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ret Sebepleri — bir başvurunun şirket ya da aday tarafından neden kapatıldığını sınıflandıran liste. | +| Kaynak | `Hr_T_RejectionReason` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true, RejectedBy=Company | +| Veri aynası | `data/App.Hr.RejectionReason.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `RejectedBy` | Reddeden | dxRadioGroup | ✓ | ✓ | liste: Company, Candidate | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Değerlendirme Kriterleri — `App.Hr.EvaluationCriterion` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/EvaluationCriterion.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.EvaluationCriterion` (sıra 8) | +| Yetki | `App.Hr.EvaluationCriterion` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Değerlendirme Kriterleri — mülakatlarda puanlanan kriterler ve ağırlıkları (iletişim, teknik yetkinlik, problem çözme…). | +| Kaynak | `Hr_T_EvaluationCriterion` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true, Weight=1 | +| Veri aynası | `data/App.Hr.EvaluationCriterion.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `Weight` | Ağırlık | dxNumberBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Mülakat Puanları — `App.Hr.InterviewScore` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/InterviewScore.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.InterviewScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Mülakat Puanları — mülakatta her değerlendirme kriterine verilen 1–5 puan. | +| Kaynak | `Hr_T_InterviewScore` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: SQL · UpdateAfter: SQL · DeleteAfter: SQL | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `InterviewId` | Mülakat | dxTextBox | | | | +| `CriterionId` | Kriter | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_EvaluationCriterion | +| `Score` | Puan | dxSelectBox | ✓ | ✓ | liste: 1, 2, 3, 4, 5 | +| `Comment` | Yorum | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +### Çalışma Takvimi ve Vardiyalar (`App.Hr.WorkCalendar`, `App.Hr.Shift`) + +#### Çalışma Takvimi — `App.Hr.WorkCalendar` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/WorkCalendar.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr` › `App.Hr.WorkCalendar` (sıra 4) | +| Yetki | `App.Hr.WorkCalendar` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Çalışma Takvimi — resmi tatiller, arife (yarım gün) ve çalışılmayan günler. | +| Kaynak | `Hr_T_WorkCalendar` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Scheduler (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Hr.WorkCalendar.DayType.Holiday`, `App.Hr.WorkCalendar.DayType.HalfDay` | +| Komutlar | InsertAfter: `Hr_S_WorkCalendarAfterSave` · UpdateAfter: `Hr_S_WorkCalendarAfterSave` · DeleteAfter: `Hr_S_WorkCalendarAfterSave` | +| Form varsayılanları | DayType=Holiday, RecurrenceRule=FREQ=YEARLY, AllDay=true, IsActive=true | +| Veri aynası | `data/App.Hr.WorkCalendar.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | | +| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | | +| `DayType` | Gün Türü | dxSelectBox | ✓ | ✓ | liste: Holiday, HalfDay | +| `RecurrenceRule` | Tekrarlama Kuralı | dxSelectBox | | ✓ | liste: FREQ=YEARLY | +| `AllDay` | Tüm Gün | dxCheckBox | | | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Vardiyalar — `App.Hr.Shift` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Shift.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.Shift` (sıra 11) | +| Yetki | `App.Hr.Shift` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Vardiyalar — çalışma vardiyalarının tanımı (sabah, akşam, gece…). | +| Geliştirme talebi | Human Resources -> Olay Günlüğü | +| Kaynak | `Hr_T_Shift` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsNightShift=false, IsActive=true | +| Veri aynası | `data/App.Hr.Shift.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Vardiya Adı | dxTextBox | ✓ | ✓ | | +| `StartTime` | Başlangıç Saati | dxTextBox | | ✓ | | +| `EndTime` | Bitiş Saati | dxTextBox | | ✓ | | +| `BreakMinutes` | Mola (dk) | dxNumberBox | | ✓ | | +| `LateToleranceMinutes` | Geç Kalma Toleransı (dk) | dxNumberBox | | ✓ | | +| `EarlyLeaveToleranceMinutes` | Erken Çıkış Toleransı (dk) | dxNumberBox | | ✓ | | +| `WorkingHours` | Çalışma Süresi (Saat) | dxNumberBox | | ✓ | | +| `IsNightShift` | Gece Vardiyası | dxCheckBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +### İzin Yönetimi (`App.Hr.Leave`) + +#### İzin Talepleri — `App.Hr.LeaveRequest` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/LeaveRequest.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Leave` › `App.Hr.LeaveRequest` (sıra 1) | +| Yetki | `App.Hr.LeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İzin Talepleri — kurumdaki bütün izin talepleri ve onay durumları. Yalnız İnsan Kaynakları kullanır. | +| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Leave.Widget.ManagerApproval`, `App.Hr.Leave.Widget.HrApproval`, `App.Hr.Leave.Widget.Approved`, `App.Hr.Leave.Widget.Rejected` | +| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: `Hr_S_LeaveRequestAfterSave` | +| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE | +| Onay akışı | Start 'Onaya Gönderildi' → Compare 'Müdür Onayı Gerekli mi?' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `RequestNo` | Talep No | dxTextBox | | ✓ | | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType | +| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | +| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | +| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script | +| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | +| `Days` | Gün | dxNumberBox | | ✓ | | +| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | +| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | | +| `RequiresManagerApproval` | Müdür Onayı Gerekli | dxNumberBox | | | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | +| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | +| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | +| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | +| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | +| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | + +#### İzin Bakiyeleri — `App.Hr.LeaveBalance` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/LeaveBalance.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Leave` › `App.Hr.LeaveBalance` (sıra 2) | +| Yetki | `App.Hr.LeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İzin Bakiyeleri — her çalışanın yıllık izin bakiyesi. | +| Kaynak | `Hr_V_LeaveSummary` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.LeaveBalanceAdjustment` (Id → EmployeeId), `App.Hr.LeaveBalanceYear` (Id → EmployeeId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Leave.Widget.RemainingDays`, `App.Hr.Leave.Widget.NegativeBalance`, `App.Hr.Leave.Widget.PendingDays` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeName` | Çalışan Adı | dxTextBox | | ✓ | | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `SeniorityStartDate` | Kıdem Başlangıcı | dxDateBox | | ✓ | | +| `ServiceYears` | Kıdem Yılı | dxNumberBox | | ✓ | | +| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | +| `AdjustmentDays` | Düzeltme Günü | dxNumberBox | | ✓ | | +| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | +| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | +| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | +| `AvailableDays` | Kullanılabilir Gün | dxNumberBox | | ✓ | | +| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | +| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Bakiye Düzeltmeleri — `App.Hr.LeaveBalanceAdjustment` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/LeaveBalanceAdjustment.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.LeaveBalanceAdjustment` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Bakiye Düzeltmeleri — çalışanın yıllık izin bakiyesine elle yapılan ekleme ve düşümler. | +| Kaynak | `Hr_T_LeaveBalanceAdjustment` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | IsActive=true, AdjustmentDate=@DATE | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `AdjustmentDate` | Düzeltme Tarihi | dxDateBox | ✓ | ✓ | | +| `Days` | Gün | dxNumberBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `Reason` | Neden | dxTextArea | ✓ | ✓ | | + +#### İzin Defteri — `App.Hr.LeaveBalanceYear` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/LeaveBalanceYear.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.LeaveBalanceYear` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İzin Defteri — çalışanın yıllık izninin yıl yıl dökümü. | +| Kaynak | `Hr_V_LeaveBalanceYear` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | | +| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | | +| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | | +| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | +| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | +| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | +| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | +| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | | +| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | +| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | + +#### İzin Taleplerim — `App.Hr.MyLeaveRequest` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyLeaveRequest.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İzin Taleplerim — oturum açan çalışanın kendi izin talepleri ve onay durumları. | +| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: `Hr_S_LeaveRequestAfterSave` | +| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `RequestNo` | Talep No | dxTextBox | | ✓ | | +| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType | +| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | +| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | +| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script | +| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | +| `Days` | Gün | dxNumberBox | | ✓ | | +| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | +| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | +| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | +| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | +| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | +| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | + +#### Ekibimin İzin Talepleri — `App.Hr.TeamLeaveRequest` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TeamLeaveRequest.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TeamLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ekibimin İzin Talepleri — müdürü olduğunuz departmandaki çalışanların izin talepleri. | +| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND '\|' + "ManagerIds" + '\|' LIKE '%\|@USERID\|%'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | +| Komutlar | UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` | +| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `RequestNo` | Talep No | dxTextBox | | ✓ | | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `LeaveTypeId` | İzin Türü | dxSelectBox | | ✓ | sorgu: Hr_T_LeaveType | +| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | +| `EndDate` | Bitiş Tarihi | dxDateBox | | ✓ | | +| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | | +| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | +| `Days` | Gün | dxNumberBox | | ✓ | | +| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | +| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | +| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | +| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | +| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | +| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | +| `ApprovalDescription` | Onay Açıklaması | dxTextArea | | ✓ | | + +#### Bakiyem — `App.Hr.MyLeaveBalance` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyLeaveBalance.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyLeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Bakiyem — yıllık izin hakkınızın ve kullanımınızın yıl yıl dökümü. | +| Kaynak | `Hr_V_LeaveBalanceYear` · filtre `"EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | | +| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | | +| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | | +| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | +| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | +| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | +| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | +| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | | +| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | +| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | + +### Puantaj ve Devam Takibi (`App.Hr.Attendance`) + +#### Günlük Hareketler — `App.Hr.AttendanceLog` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/AttendanceLog.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Attendance` › `App.Hr.AttendanceLog` (sıra 1) | +| Yetki | `App.Hr.AttendanceLog` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Günlük Hareketler — PDKS'den (kart okuyucu), Excel aktarımından gelen ya da elle girilen ham giriş/çıkış okutmaları. | +| Kaynak | `Hr_T_AttendanceLog` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Attendance.Widget.Today`, `App.Hr.Attendance.Widget.Pdks`, `App.Hr.Attendance.Widget.Manual`, `App.Hr.Attendance.Widget.Error` | +| Komutlar | InsertAfter: `Hr_S_AttendanceProcess` · UpdateAfter: `Hr_S_AttendanceProcess` · DeleteAfter: `Hr_S_AttendanceProcess` | +| Form varsayılanları | Direction=Auto, Source=Manual | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `CardNo` | Kart No | dxTextBox | | ✓ | | +| `EventTime` | Zaman | dxDateBox | ✓ | ✓ | | +| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: In, Out, Auto | +| `Source` | Kaynak | dxSelectBox | | ✓ | liste: Manual, Pdks, Import | +| `DeviceCode` | Cihaz | dxTextBox | | ✓ | | +| `WorkDate` | İş Günü | dxDateBox | | | | +| `ProcessError` | Hata | dxSelectBox | | | liste: UnknownCard, ClosedPeriod | +| `Note` | Not | dxTextArea | | ✓ | | + +#### Günlük Puantaj — `App.Hr.Timesheet` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Timesheet.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Attendance` › `App.Hr.Timesheet` (sıra 2) | +| Yetki | `App.Hr.Timesheet` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Günlük Puantaj — çalışan × gün satırı: ilk giriş, son çıkış, net çalışma süresi, mola düşümü, geç kalma (dk), erken çıkış (dk), fazla mesai (saat) ve gün tipi (çalışma, hafta tatili, resmî tatil, izinli, raporlu, eğitimde, devamsız). | +| Kaynak | `Hr_T_Timesheet` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Attendance.Widget.Absent`, `App.Hr.Attendance.Widget.Late`, `App.Hr.Attendance.Widget.Overtime`, `App.Hr.Attendance.Widget.Incomplete` | +| Komutlar | UpdateBefore: SQL · UpdateAfter: `Hr_S_TimesheetCalculate` · DeleteBefore: SQL · DeleteAfter: `Hr_S_TimesheetCalculate` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `WorkDate` | İş Günü | dxDateBox | | ✓ | | +| `DayType` | Gün Tipi | dxSelectBox | ✓ | ✓ | liste: Work, WeeklyOff, Holiday, Training, Leave, Sick, Absent | +| `LeaveTypeId` | İzin Türü | dxSelectBox | | ✓ | sorgu: Hr_T_LeaveType | +| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | +| `ShiftId` | Vardiya | dxSelectBox | | | sorgu: Hr_T_Shift | +| `FirstIn` | İlk Giriş | dxDateBox | | ✓ | | +| `LastOut` | Son Çıkış | dxDateBox | | ✓ | | +| `NetHours` | Net Çalışma (saat) | dxNumberBox | | | | +| `BreakMinutes` | Mola Düşümü (dk) | dxNumberBox | | ✓ | | +| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | | | +| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | | | +| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | | | +| `IsAssumed` | Varsayılan | dxCheckBox | | | | +| `IsManual` | Elle | dxCheckBox | | | | +| `IsIncomplete` | Eksik Okutma | dxCheckBox | | | | +| `Note` | Not | dxTextArea | | ✓ | | +| `PeriodYear` | Yıl | dxNumberBox | | | | +| `PeriodMonth` | Ay | dxNumberBox | | | | +| `PeriodKey` | Dönem Anahtarı | dxTextBox | | | | + +#### Aylık Puantaj — `App.Hr.TimesheetMonthly` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TimesheetMonthly.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Attendance` › `App.Hr.TimesheetMonthly` (sıra 3) | +| Yetki | `App.Hr.TimesheetMonthly` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Aylık Puantaj — Günlük Puantaj'ın personel bazlı aylık toplamı (salt okunur). | +| Kaynak | `Hr_V_TimesheetMonthly` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.Timesheet` (Id → PeriodKey) | +| Widget'lar | `App.Hr.Attendance.Widget.Employees`, `App.Hr.Attendance.Widget.Overtime`, `App.Hr.Attendance.Widget.Absent`, `App.Hr.Attendance.Widget.OverLimit` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `PeriodYear` | Yıl | dxNumberBox | | ✓ | | +| `PeriodMonth` | Ay | dxNumberBox | | ✓ | | +| `PeriodStatus` | Dönem Durumu | dxSelectBox | | ✓ | liste: Open, Closed | +| `WorkDays` | Çalışma Günü | dxNumberBox | | ✓ | | +| `NetHours` | Net Çalışma (saat) | dxNumberBox | | ✓ | | +| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | ✓ | | +| `LateDays` | Geç Kalınan Gün | dxNumberBox | | ✓ | | +| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | ✓ | | +| `EarlyLeaveDays` | Erken Çıkılan Gün | dxNumberBox | | ✓ | | +| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `OvertimePaidHours` | Zamlı Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `WeeklyOffDays` | Hafta Tatili | dxNumberBox | | ✓ | | +| `HolidayDays` | Resmî Tatil | dxNumberBox | | ✓ | | +| `LeaveDays` | İzinli Gün | dxNumberBox | | ✓ | | +| `UnpaidLeaveDays` | Ücretsiz İzinli Gün | dxNumberBox | | ✓ | | +| `TrainingDays` | Eğitim Günü | dxNumberBox | | ✓ | | +| `SickDays` | Raporlu Gün | dxNumberBox | | ✓ | | +| `AbsentDays` | Devamsız Gün | dxNumberBox | | ✓ | | +| `IncompleteDays` | Eksik Okutmalı Gün | dxNumberBox | | ✓ | | +| `AssumedDays` | Varsayılan Gün | dxNumberBox | | ✓ | | +| `YearOvertimeHours` | Yıllık Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `AnnualOvertimeLimit` | Yıllık Fazla Mesai Sınırı | dxNumberBox | | ✓ | | +| `IsOverAnnualLimit` | Yıllık Sınır Aşıldı | dxNumberBox | | | | + +#### Puantaj Dönemleri — `App.Hr.TimesheetPeriod` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TimesheetPeriod.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Attendance` › `App.Hr.TimesheetPeriod` (sıra 4) | +| Yetki | `App.Hr.TimesheetPeriod` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Puantaj Dönemleri — aylık puantaj dönemleri: yeniden hesaplama ve kapanış. | +| Kaynak | `Hr_T_TimesheetPeriod` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Attendance.Widget.Open`, `App.Hr.Attendance.Widget.Closed`, `App.Widget.Total` | +| Komutlar | InsertAfter: `Hr_S_TimesheetPeriodAfterSave` · UpdateAfter: `Hr_S_TimesheetPeriodAfterSave` · DeleteBefore: SQL | +| Form varsayılanları | PeriodYear=@YEAR, PeriodMonth=@MONTH, Status=Open | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodYear` | Yıl | dxNumberBox | ✓ | ✓ | | +| `PeriodMonth` | Ay | dxNumberBox | ✓ | ✓ | | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, Closed | +| `CalculatedAt` | Hesaplanma | dxDateBox | | | | +| `ClosedAt` | Kapanış | dxDateBox | | | | +| `ClosedById` | Kapatan | dxSelectBox | | | sorgu: AbpUsers | +| `NightlyAt` | Gece İşi | dxDateBox | | | | +| `Note` | Not | dxTextArea | | ✓ | | + +#### Puantajım — `App.Hr.MyTimesheet` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyTimesheet.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyTimesheet` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Puantajım — kendi aylık puantajınız: ay ay çalışma günü, net saat, geç kalma, erken çıkış, fazla mesai ve izinli/raporlu/devamsız günler. | +| Kaynak | `Hr_V_TimesheetMonthly` · filtre `"EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.MyTimesheetDay` (Id → PeriodKey) | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `PeriodYear` | Yıl | dxNumberBox | | ✓ | | +| `PeriodMonth` | Ay | dxNumberBox | | ✓ | | +| `PeriodStatus` | Dönem Durumu | dxSelectBox | | ✓ | liste: Open, Closed | +| `WorkDays` | Çalışma Günü | dxNumberBox | | ✓ | | +| `NetHours` | Net Çalışma (saat) | dxNumberBox | | ✓ | | +| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | ✓ | | +| `LateDays` | Geç Kalınan Gün | dxNumberBox | | ✓ | | +| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | ✓ | | +| `EarlyLeaveDays` | Erken Çıkılan Gün | dxNumberBox | | ✓ | | +| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `OvertimePaidHours` | Zamlı Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `WeeklyOffDays` | Hafta Tatili | dxNumberBox | | ✓ | | +| `HolidayDays` | Resmî Tatil | dxNumberBox | | ✓ | | +| `LeaveDays` | İzinli Gün | dxNumberBox | | ✓ | | +| `UnpaidLeaveDays` | Ücretsiz İzinli Gün | dxNumberBox | | ✓ | | +| `TrainingDays` | Eğitim Günü | dxNumberBox | | ✓ | | +| `SickDays` | Raporlu Gün | dxNumberBox | | ✓ | | +| `AbsentDays` | Devamsız Gün | dxNumberBox | | ✓ | | +| `IncompleteDays` | Eksik Okutmalı Gün | dxNumberBox | | ✓ | | +| `AssumedDays` | Varsayılan Gün | dxNumberBox | | ✓ | | +| `YearOvertimeHours` | Yıllık Fazla Mesai (saat) | dxNumberBox | | ✓ | | +| `AnnualOvertimeLimit` | Yıllık Fazla Mesai Sınırı | dxNumberBox | | ✓ | | +| `IsOverAnnualLimit` | Yıllık Sınır Aşıldı | dxNumberBox | | | | + +#### Puantaj Günlerim — `App.Hr.MyTimesheetDay` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyTimesheetDay.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyTimesheetDay` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Puantaj Günlerim — puantajınızın günleri: ilk giriş, son çıkış, net çalışma, mola, geç kalma, erken çıkış, fazla mesai ve gün tipi. | +| Kaynak | `Hr_T_Timesheet` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `WorkDate` | İş Günü | dxDateBox | | | | +| `DayType` | Gün Tipi | dxSelectBox | | | liste: Work, WeeklyOff, Holiday, Training, Leave, Sick, Absent | +| `LeaveTypeId` | İzin Türü | dxSelectBox | | | sorgu: Hr_T_LeaveType | +| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | +| `FirstIn` | İlk Giriş | dxDateBox | | | | +| `LastOut` | Son Çıkış | dxDateBox | | | | +| `NetHours` | Net Çalışma (saat) | dxNumberBox | | | | +| `BreakMinutes` | Mola Düşümü (dk) | dxNumberBox | | | | +| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | | | +| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | | | +| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | | | +| `IsAssumed` | Varsayılan | dxCheckBox | | | | +| `IsManual` | Elle | dxCheckBox | | | | +| `IsIncomplete` | Eksik Okutma | dxCheckBox | | | | +| `Note` | Not | dxTextBox | | | | +| `PeriodKey` | Dönem Anahtarı | dxTextBox | | | | + +### Sağlık Kartları (`App.Hr.HealthCard`) + +#### Sağlık Kartları — `App.Hr.HealthCard` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCard.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr` › `App.Hr.HealthCard` (sıra 7) | +| Yetki | `App.Hr.HealthCard` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Sağlık Kartları — işyeri hekimliği için her çalışanın sağlık kartı. Liste kiracının bütün kullanıcılarıdır; kart bilgileri detay sekmelerinden girilir. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.HealthCardHistory` (Id → Id), `App.Hr.HealthCardLabPhysical` (Id → Id), `App.Hr.HealthCardAnamnesis` (Id → Id), `App.Hr.HealthCardResult` (Id → Id), `App.Hr.HealthCardPeriodicExamination` (Id → UserId), `App.Hr.HealthCardPatientProtocol` (Id → UserId), `App.Hr.HealthCardSickLeave` (Id → UserId) | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Ad | dxTextBox | | ✓ | | +| `Surname` | Soyad | dxTextBox | | ✓ | | +| `IdentityNumber` | T.C. Kimlik No | dxTextBox | | ✓ | | +| `BirthDate` | Doğum Tarihi | dxDateBox | | ✓ | | +| `Gender` | Cinsiyet | dxSelectBox | | ✓ | liste: Male, Female | +| `BloodType` | Kan Grubu | dxTextBox | | ✓ | | +| `Email` | E-posta | dxTextBox | | ✓ | | +| `PhoneNumber` | Telefon | dxTextBox | | ✓ | | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `HireDate` | İşe Giriş Tarihi | dxDateBox | | ✓ | | +| `SskNo` | SSK No | dxTextBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Soy / Özgeçmiş — `App.Hr.HealthCardHistory` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardHistory.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardHistory` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Soy / Özgeçmiş — çalışanın aile sağlık geçmişi, kan grubu, kronik hastalıkları ve aşıları. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `MotherHealthStatus` | Anne | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | +| `MotherHealthNote` | Anne Notu | dxTextBox | | ✓ | | +| `FatherHealthStatus` | Baba | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | +| `FatherHealthNote` | Baba Notu | dxTextBox | | ✓ | | +| `SiblingHealthStatus` | Kardeş | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | +| `SiblingHealthNote` | Kardeş Notu | dxTextBox | | ✓ | | +| `ChildHealthStatus` | Çocuk | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | +| `ChildHealthNote` | Çocuk Notu | dxTextBox | | ✓ | | +| `BloodType` | Kan Grubu | dxSelectBox | | ✓ | liste: 0 Rh+, 0 Rh-, A Rh+, A Rh-, B Rh+, B Rh-, AB Rh+, AB Rh- | +| `ChronicDisease` | Doğuştan / Kronik Hastalık | dxTextBox | | ✓ | | +| `TetanusVaccination` | Tetanoz | dxTextBox | | ✓ | | +| `HepatitisVaccination` | Hepatit | dxTextBox | | ✓ | | +| `OtherVaccination` | Diğer | dxTextBox | | ✓ | | + +#### Laboratuvar - Fizik Muayene — `App.Hr.HealthCardLabPhysical` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardLabPhysical.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardLabPhysical` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Laboratuvar – Fizik Muayene — işe giriş ya da periyodik muayenedeki tahlil ve fizik muayene bulguları. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `LabBiologicalAnalysis` | Biyolojik Analizler | dxTextBox | | ✓ | | +| `LabBlood` | Kan | dxTextBox | | ✓ | | +| `LabUrine` | İdrar | dxTextBox | | ✓ | | +| `LabRadiological` | Radyolojik Analizler | dxTextBox | | ✓ | | +| `LabRadiologicalPhysiological` | Radyolojik Fizyolojik | dxTextBox | | ✓ | | +| `LabAudiometry` | Odyometri | dxTextBox | | ✓ | | +| `LabPulmonaryFunction` | Solunum Fonksiyon Testi | dxTextBox | | ✓ | | +| `LabPsychologicalTests` | Psikolojik Testler | dxTextBox | | ✓ | | +| `LabOther` | Diğer Laboratuvar Bulguları | dxTextBox | | ✓ | | +| `ExamSensoryOrgans` | Duyu Organları | dxTextBox | | ✓ | | +| `ExamEye` | Göz | dxTextBox | | ✓ | | +| `ExamEnt` | Kulak-Burun-Boğaz | dxTextBox | | ✓ | | +| `ExamSkin` | Deri | dxTextBox | | ✓ | | +| `ExamCardiovascular` | Kalp-Damar Sistemi Muayenesi | dxTextBox | | ✓ | | +| `ExamRespiratory` | Solunum Sistemi Muayenesi | dxTextBox | | ✓ | | +| `ExamDigestive` | Sindirim Sistemi Muayenesi | dxTextBox | | ✓ | | +| `ExamUrogenital` | Ürogenital Sistem Muayenesi | dxTextBox | | ✓ | | +| `ExamMusculoskeletal` | Kas-İskelet Sistemi Muayenesi | dxTextBox | | ✓ | | +| `ExamNeurological` | Nörolojik Muayene | dxTextBox | | ✓ | | +| `ExamPsychiatric` | Psikiyatrik Muayene | dxTextBox | | ✓ | | +| `ExamOther` | Diğer Muayene Bulguları | dxTextBox | | ✓ | | +| `ExamBloodPressure` | Tansiyon | dxTextBox | | ✓ | | +| `ExamPulse` | Nabız / dk | dxTextBox | | ✓ | | +| `ExamHeight` | Boy (cm) | dxNumberBox | | ✓ | | +| `ExamWeight` | Kilo (kg) | dxNumberBox | | ✓ | | + +#### Anamnez — `App.Hr.HealthCardAnamnesis` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardAnamnesis.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardAnamnesis` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Anamnez — çalışanın sağlık geçmişine dair soru formu. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ComplaintChestPain` | Göğüs Ağrısı | dxCheckBox | | ✓ | | +| `ComplaintProductiveCough` | Balgamlı Öksürük | dxCheckBox | | ✓ | | +| `ComplaintDyspnea` | Nefes Darlığı | dxCheckBox | | ✓ | | +| `ComplaintPalpitation` | Çarpıntı | dxCheckBox | | ✓ | | +| `ComplaintJointPain` | Eklem Ağrısı | dxCheckBox | | ✓ | | +| `ComplaintBackPain` | Bel Ağrısı | dxCheckBox | | ✓ | | +| `ComplaintDiarrheaConstipation` | İshal veya Kabızlık | dxCheckBox | | ✓ | | +| `DiagnosisDiabetes` | Şeker Hastalığı | dxCheckBox | | ✓ | | +| `DiagnosisHeartDisease` | Kalp Hastalığı | dxCheckBox | | ✓ | | +| `DiagnosisKidneyDisease` | Böbrek Hastalığı | dxCheckBox | | ✓ | | +| `DiagnosisJaundice` | Sarılık | dxCheckBox | | ✓ | | +| `DiagnosisPepticUlcer` | Mide / Oniki Parmak Ülseri | dxCheckBox | | ✓ | | +| `DiagnosisHearingLoss` | İşitme Kaybı | dxCheckBox | | ✓ | | +| `DiagnosisVisionImpairment` | Görme Bozukluğu | dxCheckBox | | ✓ | | +| `DiagnosisNervousSystemDisease` | Sinir Sistemi Hastalığı | dxCheckBox | | ✓ | | +| `DiagnosisSkinDisease` | Deri Hastalığı | dxCheckBox | | ✓ | | +| `DiagnosisFoodPoisoning` | Besin Zehirlenmesi | dxCheckBox | | ✓ | | +| `Hospitalized` | 3. Hastanede yattınız mı? | dxCheckBox | | ✓ | script | +| `HospitalizedNote` | Hastanede Yatış Notu | dxTextBox | | ✓ | | +| `HadSurgery` | 4. Ameliyat oldunuz mu? | dxCheckBox | | ✓ | script | +| `HadSurgeryNote` | Ameliyat Notu | dxTextBox | | ✓ | | +| `HadWorkAccident` | 5. İş kazası geçirdiniz mi? | dxCheckBox | | ✓ | script | +| `HadWorkAccidentNote` | İş Kazası Notu | dxTextBox | | ✓ | | +| `OccupationalDiseaseExam` | 6. Meslek hastalığı şüphesiyle tetkik veya muayene oldunuz mu? | dxCheckBox | | ✓ | script | +| `OccupationalDiseaseExamNote` | Meslek Hastalığı Muayene Notu | dxTextBox | | ✓ | | +| `DisabilityPension` | 7. Malulen emeklilik aldınız mı? | dxCheckBox | | ✓ | script | +| `DisabilityPensionNote` | Malulen Emeklilik Notu | dxTextBox | | ✓ | | +| `UnderTreatment` | 8. Şu anda bir tedavi görüyor musunuz? | dxCheckBox | | ✓ | script | +| `UnderTreatmentNote` | Tedavi Notu | dxTextBox | | ✓ | | +| `Smoking` | 9. Sigara kullanıyor musunuz? | dxSelectBox | | ✓ | liste: None, Occasionally, Normal, Quit · script | +| `SmokingNote` | Sigara Notu | dxTextBox | | ✓ | | +| `Alcohol` | 10. Alkol kullanıyor musunuz? | dxSelectBox | | ✓ | liste: None, Occasionally, Normal, Quit · script | +| `AlcoholNote` | Alkol Notu | dxTextBox | | ✓ | | + +#### Sonuç — `App.Hr.HealthCardResult` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardResult.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardResult` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Sonuç — işyeri hekiminin çalışmaya elverişlilik kararı. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `FitForWorkJob` | Çalışmaya Elverişli - İş | dxTextBox | | ✓ | | +| `FitForWorkCondition` | Çalışmaya Elverişli - Koşul | dxTextBox | | ✓ | | +| `FitnessDoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | +| `ShiftWorkFit` | Vardiyalı Çalışabilir | dxCheckBox | | ✓ | | +| `NightWorkFit` | Gece Çalışabilir | dxCheckBox | | ✓ | | +| `ShiftNightDoctorId` | Vardiya / Gece Çalışması Doktoru | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | + +#### Periyodik Muayeneler — `App.Hr.HealthCardPeriodicExamination` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardPeriodicExamination.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardPeriodicExamination` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Periyodik Muayeneler — çalışanın yasal periyodik sağlık muayeneleri. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `Adm_T_UserPeriodicExamination` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | +| `ExamDate` | Tarih | dxDateBox | ✓ | ✓ | script | +| `Examination` | Muayene | dxTextBox | ✓ | ✓ | | +| `Result` | Sonuç | dxTextBox | | ✓ | | +| `DoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor · script | +| `DoctorDiplomaNo` | Diploma No | dxTextBox | | ✓ | | + +#### Hasta Protokol Defteri — `App.Hr.HealthCardPatientProtocol` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardPatientProtocol.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardPatientProtocol` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Hasta Protokol Defteri — çalışanın revir başvuruları. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `Adm_T_UserPatientProtocol` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | +| `SequenceNo` | Sıra No | dxNumberBox | | ✓ | | +| `ProtocolDate` | Tarih | dxDateBox | ✓ | ✓ | script | +| `ProtocolType` | Protokol Türü | dxSelectBox | ✓ | ✓ | liste: Disease, WorkAccident, OccupationalDisease, Control, Other | +| `ProtocolResult` | Sonuç | dxSelectBox | | ✓ | liste: TreatmentDischarged, Rest, Referral · script | +| `RestDays` | İstirahat Günü | dxNumberBox | | ✓ | | +| `ReferralPlace` | Sevk Yeri | dxTextBox | | ✓ | | +| `DoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | + +#### İstirahat Raporları — `App.Hr.HealthCardSickLeave` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/HealthCardSickLeave.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.HealthCardSickLeave` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | İstirahat Raporları — çalışanın aldığı istirahat (rapor) kayıtları. | +| Geliştirme talebi | Human Resources -> Health Card | +| Kaynak | `Adm_T_UserSickLeave` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_LeaveSickLeaveSync` · UpdateAfter: `Hr_S_LeaveSickLeaveSync` · DeleteAfter: `Hr_S_LeaveSickLeaveSync` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | +| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | +| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | +| `Days` | Gün | dxNumberBox | ✓ | ✓ | | +| `SickLeaveType` | İstirahat Türü | dxSelectBox | ✓ | ✓ | liste: Disease, WorkAccident, OccupationalDisease, Maternity | +| `Institution` | Kurum | dxTextBox | | ✓ | | +| `Clinic` | Klinik | dxTextBox | | ✓ | | +| `SickLeaveReason` | İstirahat Nedeni | dxTextBox | | ✓ | | + +### Eğitimler (`App.Hr.Trainings`) + +#### Eğitim Tipleri — `App.Hr.TrainingType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TrainingType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Trainings` › `App.Hr.TrainingType` (sıra 1) | +| Yetki | `App.Hr.TrainingType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Eğitim Tipleri — eğitimlerin türü (oryantasyon, iş başı, grup, firma dışı, akademi, rotasyon…). | +| Geliştirme talebi | Human Resources -> Eğitim | +| Kaynak | `Hr_T_TrainingType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.TrainingType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | script | + +#### Eğitim Konuları — `App.Hr.TrainingSubject` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TrainingSubject.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Trainings` › `App.Hr.TrainingSubject` (sıra 2) | +| Yetki | `App.Hr.TrainingSubject` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Eğitim Konuları — bir eğitim tipine bağlı konu başlıkları (İSG, siber güvenlik, iş başı eğitimi…). | +| Geliştirme talebi | Human Resources -> Eğitim | +| Kaynak | `Hr_T_TrainingSubject` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Veri aynası | `data/App.Hr.TrainingSubject.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `TrainingTypeId` | Eğitim Tipi | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingType | +| `Name` | Eğitim Konusu | dxTextBox | ✓ | ✓ | | +| `IsEvaluated` | Değerlendirilsin mi? | dxCheckBox | ✓ | ✓ | script | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | script | + +#### Eğitimler — `App.Hr.Training` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Training.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Trainings` › `App.Hr.Training` (sıra 3) | +| Yetki | `App.Hr.Training` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Eğitimler — düzenlenen her eğitim oturumu: tarih/saat, süre, yer, eğitmen, maliyet, kazandırdığı yetkinlikler, katılımcılar ve dosyalar. | +| Geliştirme talebi | Human Resources -> Eğitim | +| Kaynak | `Hr_T_Training` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.TrainingParticipant` (Id → TrainingId), `App.Hr.TrainingFile` (Id → TrainingId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Training.Widget.Open`, `App.Hr.Training.Widget.Closed`, `App.Hr.Training.Widget.Cost` | +| Komutlar | UpdateAfter: `Hr_S_TrainingSync` · DeleteAfter: `Hr_S_TrainingSync` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `TrainingTypeId` | Eğitim Tipi | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingType | +| `TrainingSubjectId` | Eğitim Konusu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingSubject (← TrainingTypeId) | +| `EntryDate` | Giriş Tarihi | dxDateBox | ✓ | ✓ | script | +| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | +| `StartDate` | Eğitim Baş. Tarihi | dxDateBox | ✓ | ✓ | script | +| `EndDate` | Bit. Tarihi | dxDateBox | ✓ | ✓ | script | +| `StartTime` | Eğitim Baş. Saati | dxDateBox | | ✓ | script | +| `EndTime` | Bit. Saati | dxDateBox | | ✓ | script | +| `TotalHours` | Top. Eğitim Süresi (Saat) | dxNumberBox | | ✓ | | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, Closed · script | +| `TrainerName` | Eğitim Veren Kişi | dxTextBox | | ✓ | | +| `TrainingPlace` | Eğitim Yeri | dxTextBox | | ✓ | | +| `TrainingInstitution` | Eğitim Veren Kurum | dxTextBox | | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `SkillIds` | Yetkinlikler | dxTagBox | | ✓ | sorgu: Hr_T_Skill | +| `CostPlace` | Eğitim Yeri Maliyeti | dxNumberBox | | ✓ | script | +| `CostTrainer` | Eğitmen Maliyeti | dxNumberBox | | ✓ | script | +| `CostAccommodation` | Konaklama | dxNumberBox | | ✓ | script | +| `CostTransport` | Ulaşım | dxNumberBox | | ✓ | script | +| `CostCatering` | İkram | dxNumberBox | | ✓ | script | +| `CostOther` | Diğer | dxNumberBox | | ✓ | script | +| `CostTotal` | Toplam Maliyet | dxNumberBox | | ✓ | | + +#### Katılımcılar — `App.Hr.TrainingParticipant` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TrainingParticipant.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TrainingParticipant` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Katılımcılar — eğitime katılan personel ve katılım sonucu. | +| Geliştirme talebi | Human Resources -> Eğitim | +| Kaynak | `Hr_T_TrainingParticipant` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_TrainingSync` · UpdateAfter: `Hr_S_TrainingSync` · DeleteAfter: `Hr_S_TrainingSync` | +| Butonlar | `App.Hr.TrainingParticipant.Certificate` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | +| `UserId` | Adı Soyadı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `HireDate` | İşe Giriş Tarihi | dxDateBox | | ✓ | | +| `DepartmentId` | Bölüm | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Görevi | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `AttendanceStatus` | Katılım Durumu | dxSelectBox | ✓ | ✓ | liste: Attended, NotAttended, Excused · script | +| `EvaluationScore` | Değerlendirme Puanı | dxNumberBox | | ✓ | | +| `ExamScore` | Sınav Notu | dxNumberBox | | ✓ | | +| `LeaveDate` | Ayrılma Tarihi | dxDateBox | | ✓ | | +| `Note` | Not | dxTextArea | | ✓ | | + +#### Dosyalar — `App.Hr.TrainingFile` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TrainingFile.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TrainingFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Eğitim Dosyaları — eğitime ait doküman ve dijital kaynaklar (sunum, imzalı katılım listesi, sertifika örneği…). | +| Geliştirme talebi | Human Resources -> Eğitim | +| Kaynak | `Hr_T_TrainingFile` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `TrainingId` | Eğitim | dxTextBox | | | | +| `DocumentTypeId` | Dosya Türü | dxSelectBox | | ✓ | sorgu: Hr_T_DocumentType | +| `FileDate` | Tarih | dxDateBox | ✓ | ✓ | script | +| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | +| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | + +### Performans Yönetimi (`App.Hr.Performance`) + +#### Değerlendirme Dönemleri — `App.Hr.PerformancePeriod` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformancePeriod.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Performance` › `App.Hr.PerformancePeriod` (sıra 1) | +| Yetki | `App.Hr.PerformancePeriod` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Değerlendirme Dönemleri — performans değerlendirmesinin yapıldığı dönem (ör. 2026 Yıl Sonu), puan ağırlıkları ve 360 derece ayarı. | +| Kaynak | `Hr_T_PerformancePeriod` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.PerformancePeriodSkill` (Id → PeriodId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.ActivePeriod`, `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.ClosedPeriod` | +| Komutlar | InsertAfter: `Hr_S_PerformancePeriodActivate` · UpdateAfter: `Hr_S_PerformancePeriodActivate` | +| Form varsayılanları | Status=Planned, GoalWeight=60, CompetencyWeight=40, Is360Enabled=false, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Ad | dxTextBox | ✓ | ✓ | | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Planned, Active, Calibration, Closed | +| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | | +| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | | +| `SelfReviewDueDate` | Öz Değerlendirme Son Tarihi | dxDateBox | | ✓ | | +| `ManagerReviewDueDate` | Yönetici Değerlendirmesi Son Tarihi | dxDateBox | | ✓ | | +| `GoalWeight` | Hedef Ağırlığı % | dxNumberBox | ✓ | ✓ | script | +| `CompetencyWeight` | Yetkinlik Ağırlığı % | dxNumberBox | ✓ | ✓ | script | +| `Is360Enabled` | 360 Derece Açık | dxCheckBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `Description` | Açıklama | dxTextBox | | ✓ | | + +#### Tüm Değerlendirmeler — `App.Hr.PerformanceReview` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceReview.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Performance` › `App.Hr.PerformanceReview` (sıra 2) | +| Yetki | `App.Hr.PerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir. | +| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.PerformanceGoal` (Id → ReviewId), `App.Hr.PerformanceCompetency` (Id → ReviewId), `App.Hr.PerformanceFeedback` (Id → ReviewId), `App.Hr.ReviewDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.InGoalOrSelf`, `App.Hr.Performance.Widget.ManagerReview`, `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.Completed` | +| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | +| Komutlar | InsertAfter: `Hr_S_PerformanceReviewAfterSave` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | +| Form varsayılanları | Status=GoalSetting, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `EmployeeName` | Çalışan Adı | dxTextBox | | | | +| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | +| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | +| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | +| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | +| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | +| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | +| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | +| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | +| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | +| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | + +#### Kalibrasyon — `App.Hr.PerformanceCalibration` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceCalibration.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Performance` › `App.Hr.PerformanceCalibration` (sıra 3) | +| Yetki | `App.Hr.PerformanceCalibration` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Kalibrasyon — yöneticilerin gönderdiği değerlendirmelerin İK tarafından birlikte gözden geçirilip puanların dengelenmesi. | +| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "Status" IN ('Calibration', 'Completed')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.Completed`, `App.Hr.Performance.Widget.AverageScore`, `App.Hr.Performance.Widget.AverageCalibrated` | +| Komutlar | UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | +| Form varsayılanları | Status=GoalSetting, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `EmployeeName` | Çalışan Adı | dxTextBox | | | | +| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | +| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | +| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | +| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | +| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | +| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | +| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | +| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | +| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | +| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | + +#### Gelişim Planları — `App.Hr.DevelopmentPlan` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DevelopmentPlan.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Performance` › `App.Hr.DevelopmentPlan` (sıra 4) | +| Yetki | `App.Hr.DevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Gelişim Planları — bütün çalışanların gelişim aksiyonları; yetkinlik, eğitim ve sertifikalarla bağlantılı. | +| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Scheduler, Todo (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.Open`, `App.Hr.Performance.Widget.Overdue`, `App.Hr.Performance.Widget.Completed` | +| Todo | başlık `Title`, durum `Status` (Planned,InProgress,Completed,Cancelled) | +| Komutlar | InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateAfter: `Hr_S_DevelopmentPlanSync` | +| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `ReviewId` | Değerlendirme | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceReview | +| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | +| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | +| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | +| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | +| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | +| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | +| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | +| `Progress` | İlerleme % | dxNumberBox | | ✓ | | +| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Performans Dereceleri — `App.Hr.PerformanceRating` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceRating.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.PerformanceRating` (sıra 16) | +| Yetki | `App.Hr.PerformanceRating` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Performans Dereceleri — genel performans puanının hangi dereceye karşılık geldiğini ve kalibrasyonda hedeflenen dağılımı tanımlayan ölçek. | +| Kaynak | `Hr_T_PerformanceRating` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | IsActive=true | +| Veri aynası | `data/App.Hr.PerformanceRating.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Level` | Seviye | dxNumberBox | ✓ | ✓ | | +| `Name` | Ad | dxTextBox | ✓ | ✓ | | +| `MinScore` | Alt Puan | dxNumberBox | ✓ | ✓ | | +| `MaxScore` | Üst Puan (hariç) | dxNumberBox | ✓ | ✓ | | +| `TargetDistribution` | Hedef Dağılım % | dxNumberBox | | ✓ | | +| `Color` | Renk | dxColorBox | | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Yetkinlik Seti — `App.Hr.PerformancePeriodSkill` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformancePeriodSkill.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.PerformancePeriodSkill` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yetkinlik Seti — dönemde her çalışanın değerlendirileceği yetkinlikler ve beklenen seviyeleri. | +| Kaynak | `Hr_T_PerformancePeriodSkill` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_PerformancePeriodActivate` · UpdateAfter: `Hr_S_PerformancePeriodActivate` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodId` | Dönem | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Hedefler — `App.Hr.PerformanceGoal` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceGoal.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.PerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Hedefler — değerlendirmenin ağırlıklı KPI / OKR hedefleri ve gerçekleşmeleri (İK görünümü). | +| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | +| `Title` | Hedef | dxTextBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | +| `Unit` | Birim | dxTextBox | | ✓ | | +| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | +| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | +| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | +| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Yetkinlikler — `App.Hr.PerformanceCompetency` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceCompetency.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.PerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yetkinlikler — değerlendirmede yetkinliklerin beklenen, öz ve yönetici seviyeleri (İK görünümü). | +| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `Score` | Puan | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | + +#### 360 Puanları — `App.Hr.PerformanceFeedbackScore` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceFeedbackScore.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.PerformanceFeedbackScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | 360 Puanları — 360 derece değerlendiricisinin yetkinlik bazında verdiği seviyeler (İK görünümü). | +| Kaynak | `Hr_T_PerformanceFeedbackScore` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `FeedbackId` | Geri Bildirim | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `LevelId` | Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `Comment` | Yorum | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### 360 Derece — `App.Hr.PerformanceFeedback` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/PerformanceFeedback.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.PerformanceFeedback` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | 360 Derece — değerlendirmeye atanan 360 derece değerlendiriciler (akran, ast, üst, iç müşteri). | +| Kaynak | `Hr_T_PerformanceFeedback` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.PerformanceFeedbackScore` (Id → FeedbackId) | +| Komutlar | InsertBefore: SQL · InsertAfter: `Hr_S_PerformanceFeedbackOpen`, `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | Relation=Peer, Status=Pending, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxSelectBox | | | sorgu: Hr_T_PerformanceReview | +| `ReviewerId` | Değerlendirici | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `Relation` | İlişki | dxSelectBox | ✓ | ✓ | liste: Peer, Subordinate, Superior, InternalCustomer | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Pending, Submitted | +| `Score` | Puan | dxNumberBox | | ✓ | | +| `SubmittedDate` | Gönderim Tarihi | dxDateBox | | ✓ | | +| `Comment` | Yorum | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Gelişim Planı — `App.Hr.ReviewDevelopmentPlan` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/ReviewDevelopmentPlan.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.ReviewDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Gelişim Planı — değerlendirmeden çıkan gelişim aksiyonları (İK görünümü). | +| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateAfter: `Hr_S_DevelopmentPlanSync` | +| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxTextBox | | | | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | +| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | +| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | +| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | +| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | +| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | +| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | +| `Progress` | İlerleme % | dxNumberBox | | ✓ | | +| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Hedeflerim — `App.Hr.MyPerformanceGoal` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyPerformanceGoal.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyPerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Hedeflerim — çalışanın kendi değerlendirmesindeki hedefler. | +| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "EmployeeId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | +| `Title` | Hedef | dxTextBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | +| `Unit` | Birim | dxTextBox | | ✓ | | +| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | +| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | +| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | +| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Yetkinliklerim — `App.Hr.MyPerformanceCompetency` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyPerformanceCompetency.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyPerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yetkinliklerim — çalışanın yetkinlik öz değerlendirmesi. | +| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "EmployeeId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `Score` | Puan | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | + +#### Gelişim Planım — `App.Hr.MyDevelopmentPlan` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyDevelopmentPlan.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Gelişim Planım — çalışanın kendi gelişim aksiyonları. | +| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Komutlar | UpdateBefore: SQL · UpdateAfter: `Hr_S_DevelopmentPlanSync` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxTextBox | | | | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | +| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | +| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | +| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | +| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | +| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | +| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | +| `Progress` | İlerleme % | dxNumberBox | | ✓ | | +| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Değerlendirmelerim — `App.Hr.MyPerformanceReview` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/MyPerformanceReview.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.MyPerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Değerlendirmelerim — oturum açan çalışanın kendi performans değerlendirmeleri. | +| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.MyPerformanceGoal` (Id → ReviewId), `App.Hr.MyPerformanceCompetency` (Id → ReviewId), `App.Hr.MyDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | +| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | +| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | +| Form varsayılanları | Status=GoalSetting, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `EmployeeName` | Çalışan Adı | dxTextBox | | | | +| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | +| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | +| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | +| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | +| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | +| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | +| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | +| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | +| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | +| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | + +#### Ekip Hedefleri — `App.Hr.TeamPerformanceGoal` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TeamPerformanceGoal.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TeamPerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ekip Hedefleri — yöneticinin, ekibindeki çalışanın hedefleri üzerindeki görünümü. | +| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | +| `Title` | Hedef | dxTextBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | +| `Unit` | Birim | dxTextBox | | ✓ | | +| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | +| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | +| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | +| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Ekip Yetkinlikleri — `App.Hr.TeamPerformanceCompetency` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TeamPerformanceCompetency.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TeamPerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ekip Yetkinlikleri — yöneticinin yetkinlik değerlendirmesi; yönetici seviyesi yetkinlik puanını belirler. | +| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `Score` | Puan | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | + +#### Ekip Gelişim Planı — `App.Hr.TeamDevelopmentPlan` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TeamDevelopmentPlan.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TeamDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ekip Gelişim Planı — yöneticinin ekibindeki çalışan için planladığı gelişim aksiyonları. | +| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_DevelopmentPlanSync` · DeleteBefore: `Hr_S_PerformanceGuard` | +| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `EmployeeId` | Çalışan | dxTextBox | | | | +| `ReviewId` | Değerlendirme | dxTextBox | | | | +| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | +| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | +| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | +| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | +| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | +| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | +| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | +| `Progress` | İlerleme % | dxNumberBox | | ✓ | | +| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### Ekibimin Değerlendirmeleri — `App.Hr.TeamPerformanceReview` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/TeamPerformanceReview.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.TeamPerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ekibimin Değerlendirmeleri — kullanıcının yönetici olarak atandığı çalışanların değerlendirmeleri. | +| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "ManagerId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.TeamPerformanceGoal` (Id → ReviewId), `App.Hr.TeamPerformanceCompetency` (Id → ReviewId), `App.Hr.TeamDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | +| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | +| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | +| Form varsayılanları | Status=GoalSetting, IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | +| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `EmployeeName` | Çalışan Adı | dxTextBox | | | | +| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | +| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | +| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | +| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | +| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | +| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | +| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | +| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | +| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | +| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | +| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | +| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | +| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | + +#### Yetkinlik Puanları — `App.Hr.My360FeedbackScore` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/My360FeedbackScore.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.My360FeedbackScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Yetkinlik Puanları — 360 değerlendiricisinin kendi talebinde her yetkinliğe verdiği seviye. | +| Kaynak | `Hr_T_PerformanceFeedbackScore` · filtre `"IsDeleted" = 'false' AND "FeedbackId" IN (SELECT "Id" FROM "Hr_T_PerformanceFeedback" WHERE "ReviewerId" = '@USERID')` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `FeedbackId` | Geri Bildirim | dxTextBox | | | | +| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | +| `LevelId` | Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | +| `Comment` | Yorum | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +#### 360 Taleplerim — `App.Hr.My360Feedback` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/My360Feedback.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.My360Feedback` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | 360 Taleplerim — kullanıcıya değerlendirici olarak atanan 360 derece değerlendirme talepleri. | +| Kaynak | `Hr_T_PerformanceFeedback` · filtre `"IsDeleted" = 'false' AND "ReviewerId" = '@USERID'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.My360FeedbackScore` (Id → FeedbackId) | +| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ReviewId` | Değerlendirme | dxSelectBox | | | sorgu: Hr_T_PerformanceReview | +| `ReviewerId` | Değerlendirici | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `Relation` | İlişki | dxSelectBox | ✓ | ✓ | liste: Peer, Subordinate, Superior, InternalCustomer | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Pending, Submitted | +| `Score` | Puan | dxNumberBox | | ✓ | | +| `SubmittedDate` | Gönderim Tarihi | dxDateBox | | ✓ | | +| `Comment` | Yorum | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | | ✓ | | + +### Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) + +#### Disiplin Dosyaları — `App.Hr.DisciplinaryCase` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DisciplinaryCase.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr` › `App.Hr.DisciplinaryCase` (sıra 10) | +| Yetki | `App.Hr.DisciplinaryCase` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Disiplin Dosyaları — bir personel hakkındaki olay tutanağı ile başlayan disiplin süreci: savunma, karar ve belgeler tek dosyada. | +| Kaynak | `Hr_T_DisciplinaryCase` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.DisciplinaryDefense` (Id → CaseId), `App.Hr.DisciplinaryDecision` (Id → CaseId), `App.Hr.DisciplinaryFile` (Id → CaseId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.DisciplinaryCase.Widget.Open`, `App.Hr.DisciplinaryCase.Widget.AwaitingDefense`, `App.Hr.DisciplinaryCase.Widget.Closed` | +| Todo | başlık `Subject`, durum `Status` (Open,AwaitingDefense,Decided,Closed) | +| Komutlar | InsertAfter: SQL | +| Form varsayılanları | IncidentDate=@DATE, ReportedById=@USERID, Status=Open | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `CaseNo` | Dosya No | dxTextBox | | | | +| `UserId` | Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | +| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | +| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | +| `IncidentDate` | Olay Tarihi | dxDateBox | ✓ | ✓ | | +| `IncidentTime` | Olay Saati | dxDateBox | | ✓ | | +| `IncidentPlace` | Olay Yeri | dxTextBox | | ✓ | | +| `ReportedById` | Tutanağı Tutan | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, AwaitingDefense, Decided, Closed | +| `Subject` | Konu | dxTextBox | ✓ | ✓ | | +| `IncidentDescription` | Olay Tutanağı | dxHtmlEditor | ✓ | ✓ | | +| `WitnessUserIds` | Tanıklar | dxTagBox | | ✓ | sorgu: AbpUsers | + +#### Ceza Türleri — `App.Hr.DisciplinaryPenaltyType` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DisciplinaryPenaltyType.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Definitions` › `App.Hr.DisciplinaryPenaltyType` (sıra 17) | +| Yetki | `App.Hr.DisciplinaryPenaltyType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ceza Türleri — disiplin kararlarında verilebilecek cezalar ve ağırlıkları (sözlü uyarı, yazılı uyarı, ihtar, kınama, ücret kesintisi, fesih). | +| Kaynak | `Hr_T_DisciplinaryPenaltyType` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | Severity=1, IsActive=true | +| Veri aynası | `data/App.Hr.DisciplinaryPenaltyType.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Ad | dxTextBox | ✓ | ✓ | | +| `Severity` | Ağırlık | dxNumberBox | ✓ | ✓ | | +| `Description` | Açıklama | dxTextArea | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Savunmalar — `App.Hr.DisciplinaryDefense` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DisciplinaryDefense.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DisciplinaryDefense` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Savunmalar — disiplin dosyası için personelden istenen savunma ve verilen cevap. | +| Kaynak | `Hr_T_DisciplinaryDefense` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | RequestDate=@DATE, Status=Requested | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `CaseId` | Disiplin Dosyası | dxTextBox | | | | +| `RequestDate` | Talep Tarihi | dxDateBox | ✓ | ✓ | script | +| `DueDate` | Son Savunma Tarihi | dxDateBox | ✓ | ✓ | script | +| `ResponseDate` | Savunma Tarihi | dxDateBox | | ✓ | | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Requested, Submitted, NotSubmitted | +| `DefenseText` | Savunma Metni | dxHtmlEditor | | ✓ | | + +#### Kararlar — `App.Hr.DisciplinaryDecision` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DisciplinaryDecision.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DisciplinaryDecision` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Kararlar — disiplin dosyası için verilen karar ve ceza. | +| Kaynak | `Hr_T_DisciplinaryDecision` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | DecisionDate=@DATE, Status=Draft | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `CaseId` | Disiplin Dosyası | dxTextBox | | | | +| `DecisionDate` | Karar Tarihi | dxDateBox | ✓ | ✓ | | +| `PenaltyTypeId` | Ceza Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_DisciplinaryPenaltyType | +| `EffectiveDate` | Yürürlük Tarihi | dxDateBox | | ✓ | | +| `NotificationDate` | Tebliğ Tarihi | dxDateBox | | ✓ | | +| `DeductionAmount` | Kesinti Tutarı | dxNumberBox | | ✓ | | +| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Draft, Final | +| `DecisionText` | Karar Metni | dxHtmlEditor | | ✓ | | + +#### Belgeler — `App.Hr.DisciplinaryFile` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DisciplinaryFile.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DisciplinaryFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Disiplin Belgeleri — dosyaya ait imzalı tutanak, savunma, tebliğ gibi belgeler. | +| Kaynak | `Hr_T_DisciplinaryFile` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Form varsayılanları | FileDate=@DATE | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `CaseId` | Disiplin Dosyası | dxTextBox | | | | +| `DocumentTypeId` | Dosya Türü | dxSelectBox | | ✓ | sorgu: Hr_T_DocumentType | +| `FileDate` | Tarih | dxDateBox | ✓ | ✓ | | +| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | +| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | + +### Araçlar (`App.Hr.Vehicles`) + +#### Araç Belgeleri — `App.Hr.VehicleDocument` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleDocument.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleDocument` (sıra 1) | +| Yetki | `App.Hr.VehicleDocument` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Araç Belgeleri — araç ve şoför kayıtlarında kullanılan belge tanımları (ruhsat, sigorta, muayene, MTV, OGS/HGS, ehliyet, psikoteknik, ceza ve kaza belgeleri). | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleDocument` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true | +| Veri aynası | `data/App.Hr.VehicleDocument.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `DocumentGroup` | Belge Grubu | dxSelectBox | ✓ | ✓ | liste: Vehicle, Driver | +| `DocumentType` | Belge Tipi | dxSelectBox | ✓ | ✓ | liste: Insurance, Document, Tax, Toll, Inspection, Maintenance, Penalty, Accident | +| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Masraf Tanımlama — `App.Hr.VehicleExpenseDefinition` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleExpenseDefinition.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleExpenseDefinition` (sıra 2) | +| Yetki | `App.Hr.VehicleExpenseDefinition` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Masraf Tanımlama — araç masraf kalemleri (sigorta, vergi, bakım, muayene, geçiş, ceza, yakıt…). | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleExpenseDefinition` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true | +| Veri aynası | `data/App.Hr.VehicleExpenseDefinition.json` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `ExpenseType` | Masraf Tipi | dxTextBox | ✓ | ✓ | | +| `Name` | Masraf Adı | dxTextBox | ✓ | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Gidilecek Yerler — `App.Hr.VehicleDestination` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleDestination.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleDestination` (sıra 3) | +| Yetki | `App.Hr.VehicleDestination` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Gidilecek Yerler — araçlarla gidilen tanımlı yerler ve uzaklıkları. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleDestination` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `Name` | Gidilecek Yerin Adı | dxTextBox | ✓ | ✓ | | +| `Distance` | Uzaklığı (km) | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | + +#### Araçlar — `App.Hr.Vehicle` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Vehicle.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.Vehicle` (sıra 4) | +| Yetki | `App.Hr.Vehicle` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Araçlar — şubeye ait şirket araçları, anlık durumu (şirkette/dışarıda), güncel km'si ve muayene/sigorta tarihleri. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_Vehicle` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.VehicleFile` (Id → VehicleId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Vehicle.Widget.Arrived`, `App.Hr.Vehicle.Widget.Left`, `App.Widget.Passive` | +| Form varsayılanları | IsActive=true | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `BranchId` | Tesis Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | +| `Name` | Araç Adı | dxTextBox | ✓ | ✓ | | +| `Brand` | Markası | dxTextBox | | ✓ | | +| `Model` | Modeli | dxTextBox | | ✓ | | +| `BodyType` | Cinsi | dxTextBox | | ✓ | | +| `UsagePlace` | Kullanıldığı Yer | dxTextBox | | ✓ | | +| `RegistrationDate` | Tescil Tarihi | dxDateBox | | ✓ | | +| `PlateNumber` | Plakası | dxTextBox | ✓ | ✓ | | +| `Status` | Durumu | dxSelectBox | | ✓ | liste: Arrived, Left | +| `CurrentKm` | Araç Km'si | dxNumberBox | | ✓ | | +| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | +| `InspectionStart` | Muayene Başlangıç | dxDateBox | | ✓ | | +| `InspectionEnd` | Muayene Bitiş | dxDateBox | | ✓ | | +| `InsuranceStart` | Sigorta Başlangıç | dxDateBox | | ✓ | | +| `InsuranceEnd` | Sigorta Bitiş | dxDateBox | | ✓ | | +| `EmissionStart` | Egzoz Muayene Başlangıç | dxDateBox | | ✓ | | +| `EmissionEnd` | Egzoz Muayene Bitiş | dxDateBox | | ✓ | | +| `TachographStart` | Takograf Kalib. Başlangıç | dxDateBox | | ✓ | | +| `TachographEnd` | Takograf Kalib. Bitiş | dxDateBox | | ✓ | | + +#### Şoför Tanımlama — `App.Hr.Driver` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Driver.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.Driver` (sıra 5) | +| Yetki | `App.Hr.Driver` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Şoför Tanımlama — şirket araçlarını kullanan personel, zimmetli araçları ve sürüş geçmişi. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_Driver` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.DriverDocument` (Id → DriverId), `App.Hr.DriverPenalty` (Id → DriverId), `App.Hr.DriverAccident` (Id → DriverId) | +| Widget'lar | `App.Widget.Total`, `App.Hr.Driver.Widget.WithVehicle`, `App.Hr.Driver.Widget.TotalKm` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `UserId` | Sicil No / Adı Soyadı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `Vehicle1Id` | Zimmetli Araç 1 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | +| `Vehicle2Id` | Zimmetli Araç 2 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | +| `Vehicle3Id` | Zimmetli Araç 3 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | +| `Vehicle4Id` | Zimmetli Araç 4 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | +| `Vehicle5Id` | Zimmetli Araç 5 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | +| `TotalKm` | Yapılan KM | dxNumberBox | | ✓ | | + +#### Araç Giriş-Çıkış Takip — `App.Hr.VehicleMovement` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleMovement.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleMovement` (sıra 6) | +| Yetki | `App.Hr.VehicleMovement` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Araç Giriş-Çıkış Takip — güvenliğin tuttuğu araç hareket defteri: araç şirketten ne zaman, kimle, hangi km ile çıktı, ne zaman döndü. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleMovement` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Hr.Vehicle.Widget.Left`, `App.Widget.Today` | +| Komutlar | InsertAfter: SQL · DeleteAfter: SQL | +| Form varsayılanları | EntryKm=0 | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `MovementNo` | Hareket No | dxNumberBox | | | | +| `ExitDate` | Çıkış Tarihi | dxDateBox | ✓ | ✓ | script | +| `BranchId` | Çıkış Şube | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | +| `ExitTime` | Çıkış Saati | dxTextBox | ✓ | ✓ | script | +| `ExitKm` | Çıkış Km | dxNumberBox | ✓ | ✓ | script | +| `SenderUserId` | Gönderen Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `SecurityUserId` | Güvenlik Personeli | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `DriverUserId` | Kullanan Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `VehicleId` | Araç Adı / Plaka | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Vehicle · script | +| `DestinationId` | Gidilen Yer | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDestination | +| `Reason` | Gidiş Sebebi | dxTextBox | | ✓ | | +| `Location` | Konum | dxTextBox | | ✓ | | +| `EntrySecurityUserId` | Giriş Yapan Güvenlik Per. | dxSelectBox | | ✓ | sorgu: AbpUsers | +| `EntryDate` | Giriş Tarihi | dxDateBox | | ✓ | script | +| `EntryBranchId` | Giriş Şube | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | +| `EntryTime` | Giriş Saati | dxTextBox | | ✓ | script | +| `EntryKm` | Giriş Km | dxNumberBox | | ✓ | script | +| `TravelledKm` | Yapılan Km | dxNumberBox | | ✓ | | +| `Status` | Durum | dxSelectBox | | ✓ | liste: Arrived, Left | +| `DurationMinutes` | Gezinti Süresi / Dk | dxNumberBox | | ✓ | | +| `ExpectedKm` | Olması Gereken Km | dxNumberBox | | ✓ | | + +#### Masraf Girişleri — `App.Hr.VehicleExpense` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleExpense.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleExpense` (sıra 7) | +| Yetki | `App.Hr.VehicleExpense` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Masraf Girişleri — araç için gelen her fatura/fiş: başlık bilgileri ve kalemleri. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleExpense` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Alt formlar | `App.Hr.VehicleExpenseLine` (Id → VehicleExpenseId) | +| Widget'lar | `App.Widget.Total`, `App.Widget.Today`, `App.Widget.TotalRevenue` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `VehicleId` | Araç Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Vehicle | +| `InvoiceNo` | Fatura No | dxTextBox | ✓ | ✓ | | +| `InvoiceDate` | Fatura Tarihi | dxDateBox | ✓ | ✓ | script | +| `DestinationId` | Firma Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDestination | +| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | +| `FileName` | Dosya Adı | dxTextBox | | ✓ | | +| `FileContent` | Dosya | dxImageUpload | | ✓ | | + +#### Araç Belgeleri — `App.Hr.VehicleFile` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleFile.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.VehicleFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Araç Dosyaları — araca yüklenen belgeler (ruhsat, poliçe, muayene raporu…). | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleFile` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `VehicleId` | Araç | dxSelectBox | | | sorgu: Hr_T_Vehicle | +| `VehicleDocumentId` | Belge Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleDocument | +| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | +| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | + +#### Şoför Belgeleri — `App.Hr.DriverDocument` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DriverDocument.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DriverDocument` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Şoför Belgeleri — şoföre ait belgeler (sürücü belgesi, psikoteknik, SRC…). | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_DriverDocument` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | +| `VehicleDocumentId` | Belge Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleDocument | +| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | +| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | + +#### Ceza Belgeleri — `App.Hr.DriverPenalty` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DriverPenalty.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DriverPenalty` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Şoför Cezaları — şoföre kesilen trafik cezaları. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_DriverPenalty` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | +| `PenaltyDate` | Ceza Tarihi | dxDateBox | ✓ | ✓ | | +| `Amount` | Tutarı | dxNumberBox | | ✓ | | +| `Description` | Ceza Açıklama | dxTextBox | | ✓ | | +| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | +| `FileName` | Dosya Adı | dxTextBox | | ✓ | | +| `FileContent` | Dosya | dxImageUpload | | ✓ | | + +#### Kaza Belgeleri — `App.Hr.DriverAccident` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/DriverAccident.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.DriverAccident` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Şoför Kazaları — şoförün karıştığı trafik kazaları ve belgeleri. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_DriverAccident` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | +| `AccidentDate` | Kaza Tarihi | dxDateBox | ✓ | ✓ | | +| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | +| `Description` | Kaza Açıklama | dxTextBox | | ✓ | | +| `FileName` | Dosya Adı | dxTextBox | | ✓ | | +| `FileContent` | Dosya | dxImageUpload | | ✓ | | + +#### Masraf Kalemleri — `App.Hr.VehicleExpenseLine` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/VehicleExpenseLine.json` | +| Yol | Liste (Wizard) | +| Menü | Menüsüz (alt form) | +| Yetki | `App.Hr.VehicleExpenseLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Masraf Kalemleri — bir masraf faturasının satırları. | +| Geliştirme talebi | Human Resources -> Araçlar | +| Kaynak | `Hr_T_VehicleExpenseLine` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `VehicleExpenseId` | Masraf Girişi | dxTextBox | | | | +| `ExpenseDefinitionId` | Masraf Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleExpenseDefinition | +| `DetailName` | Masraf Detay Adı | dxTextBox | | ✓ | | +| `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | script | +| `Amount` | Tutarı | dxNumberBox | ✓ | ✓ | script | +| `DiscountRate` | İskonto Oranı (%) | dxNumberBox | ✓ | ✓ | script | +| `NetAmount` | Net Tutar | dxNumberBox | ✓ | ✓ | | +| `Description` | Masraf Açıklama | dxTextBox | | ✓ | | + +### Ziyaretçiler (`App.Hr.Visitor`) + +#### Ziyaretçiler — `App.Hr.Visitor` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/Visitor.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr` › `App.Hr.Visitor` (sıra 12) | +| Yetki | `App.Hr.Visitor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Ziyaretçiler — güvenlik/resepsiyonun tuttuğu ziyaretçi giriş-çıkış defteri. | +| Geliştirme talebi | Human Resources -> Ziyaretçi Takip Listesi | +| Kaynak | `Hr_T_Visitor` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Hr.Visitor.Widget.Today`, `App.Hr.Visitor.Widget.Inside`, `App.Hr.Visitor.Widget.Exited` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `VisitDate` | Ziyaret Tarihi | dxDateBox | ✓ | ✓ | script | +| `VisitorType` | Ziyaretçi Tipi | dxSelectBox | ✓ | ✓ | liste: Ziyaretçi, Müşteri, Tedarikçi, Taşeron, Kurye · script | +| `EntryTime` | Giriş Saati | dxDateBox | ✓ | ✓ | script | +| `ExitTime` | Çıkış Saati | dxDateBox | | ✓ | | +| `CardNo` | Kart No | dxTextBox | | ✓ | | +| `VisitedUserId` | Ziyaret Edilen Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `VisitorFullName` | Ziyaretçi Adı Soyadı | dxTextBox | ✓ | ✓ | | +| `CompanyName` | Firma Adı | dxAutocomplete | | ✓ | sorgu: Hr_T_Visitor | +| `VisitReason` | Ziyaret Sebebi | dxTextArea | | ✓ | | +| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | + +### Olay Günlüğü (`App.Hr.EventLog`) + +#### Olay Günlüğü — `App.Hr.EventLog` + +| Özellik | Değer | +| --- | --- | +| Wizard | `wizard/EventLog.json` | +| Yol | Liste (Wizard) | +| Menü | `App.Hr` › `App.Hr.EventLog` (sıra 13) | +| Yetki | `App.Hr.EventLog` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | +| Açıklama | Olay Günlüğü — vardiya amiri, güvenlik odası ve gözlem odasının vardiya sırasında kaydettiği önemli olaylar. | +| Geliştirme talebi | Human Resources -> Olay Günlüğü | +| Kaynak | `Hr_T_EventLog` · filtre `"IsDeleted" = 'false'` | +| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | +| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | +| Kapsam | Kiracı | +| Widget'lar | `App.Widget.Total`, `App.Widget.Today`, `App.Hr.EventLog.Widget.Important` | + +| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | +| --- | --- | --- | --- | --- | --- | +| `LogSource` | Kaynak | dxSelectBox | ✓ | ✓ | liste: ShiftSupervisor, SecurityRoom, ObservationRoom | +| `BranchId` | Şube Adı | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | +| `UserId` | Vardiya Amiri / Olayı Yaşayan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | +| `EventDate` | Olay Tarihi | dxDateBox | ✓ | ✓ | script | +| `EventTime` | Olay Saati | dxTextBox | ✓ | ✓ | | +| `Importance` | Önem Durumu | dxSelectBox | ✓ | ✓ | liste: 1, 2, 3, 4, 5 | +| `ShiftId` | Vardiya | dxSelectBox | | ✓ | sorgu: Hr_T_Shift | +| `Description` | Açıklama | dxTextArea | | ✓ | | + + diff --git a/configs/seeds/docs/modules/PrcDefinitions.md b/configs/seeds/docs/modules/App.Prc.md similarity index 85% rename from configs/seeds/docs/modules/PrcDefinitions.md rename to configs/seeds/docs/modules/App.Prc.md index b4e06683..d913bc58 100644 --- a/configs/seeds/docs/modules/PrcDefinitions.md +++ b/configs/seeds/docs/modules/App.Prc.md @@ -1,19 +1,22 @@ -# Tanımlamalar (`App.Prc.Definitions`) +# Satınalma (`App.Prc`) -> Bu dosya ilk deploy'da otomatik açıldı. "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. +> Menünün altındaki her dal bu dosyada bir bölümdür (`module-doc:section`); dosya ve bölümler ilk deploy'da otomatik açılır. `module-doc:todo` işaretli alt bölümleri modülü üreten kişi ya da AI doldurur (`lowcode.instructions.md` §0.13); MCP ile üretimde talep bu bölümler doldurulmadan Testing'e alınamaz. "Ek — Ekran envanteri" bölümü wizard dosyalarından üretilir, elle düzenlenmez. -## 1. Amaç ve kapsam + +## Tanımlamalar (`App.Prc.Definitions`) + +### 1. Amaç ve kapsam Satınalma belgelerinde kullanılacak ödeme koşulu, ödeme yöntemi, teslimat koşulu (Incoterm) ve teslim yöntemi tanımları. Kullanıcılar satınalma ve muhasebe personelidir. Satınalma talebi, teklif, sipariş ve fatura belgeleri bu modülün kapsamında değildir; bu ekranlar onların lookup kaynağıdır. -Tedarikçi kartı (eski `App.Prc.Supplier`) satış ve satınalmanın ortak kartı olarak **Kontaklar** adıyla Yönetim › Tanımlamalar'a taşındı; ayrıntı [AdministrationDefinitions.md](AdministrationDefinitions.md). Kontak kartının Satış ve Satınalma sekmeleri bu modülün tanımlarını lookup olarak kullanır. +Tedarikçi kartı (eski `App.Prc.Supplier`) satış ve satınalmanın ortak kartı olarak **Kontaklar** adıyla Yönetim › Tanımlamalar'a taşındı; ayrıntı [Administration › Tanımlamalar](). Kontak kartının Satış ve Satınalma sekmeleri bu modülün tanımlarını lookup olarak kullanır. -## 2. Analiz ve kararlar +### 2. Analiz ve kararlar - Modül kodu `Prc`, tablo öneki `Prc_T_`; ekranlar Satınalma › Tanımlamalar altında. - Kart, etiket, ilgili kişi ve banka hesabı ekranları Satış tarafı da kullanacağı için `Adm` modülüne (`Adm_T_Contact*`, `App.Definitions.Contact*`) taşındı; bu modülde yalnızca satınalma koşulu tanımları kaldı. -## 3. Menü ve ekranlar +### 3. Menü ve ekranlar Satınalma (`App.Prc`) › Tanımlamalar (`App.Prc.Definitions`): @@ -24,7 +27,7 @@ Satınalma (`App.Prc`) › Tanımlamalar (`App.Prc.Definitions`): | Teslimat Koşulları | `App.Prc.Incoterm` | tanım, demo veri | | Teslim Yöntemleri | `App.Prc.DeliveryMethod` | tanım, demo veri | -## 4. Veri modeli +### 4. Veri modeli Tüm tablolar kiracı (`TenantId`) + tam audit + soft delete taşır. @@ -33,30 +36,30 @@ Tüm tablolar kiracı (`TenantId`) + tam audit + soft delete taşır. - `Prc_T_Incoterm` (Code, Name, IsActive) - `Prc_T_DeliveryMethod` (Name, IsActive) -## 5. İş kuralları ve hesaplar +### 5. İş kuralları ve hesaplar - Tanım lookup'ları yalnızca `IsActive = 1` ve silinmemiş kayıtları listeler; kullanılan tanım silinmek yerine pasife alınır. - Ödeme koşulu `DueDays` vade gününü tutar; ay sonu kuralları açıklamada yazılıdır, otomatik vade hesabı yoktur. -## 6. Yetki ve görünürlük +### 6. Yetki ve görünürlük Yetki ağacı: `App.Prc` › `App.Prc.Definitions` › her ekran (+ Create/Update/Delete/Export/Import/Note). Tüm ekranlar kiracı kapsamlıdır, şube filtresi yoktur. Widget'lar: her ekranda Toplam · Aktif · Pasif. -## 7. Entegrasyonlar +### 7. Entegrasyonlar Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalma sekmelerinde (`App.Definitions.ContactSales`, `App.Definitions.ContactPurchasing`) seçilir. -## 8. Akış örneği +### 8. Akış örneği 1. Satınalma › Tanımlamalar › Ödeme Koşulları'nda "30 Gün" aktif durur. 2. Yönetim › Tanımlamalar › Kontaklar'da "Acme Corporation" açılır; Satınalma sekmesinde Düzenle ile Ödeme Koşulu = 30 Gün seçilip kaydedilir. -## 9. Sık sorulanlar +### 9. Sık sorulanlar - **Tedarikçiler ekranı nerede?** Yönetim › Tanımlamalar › Kontaklar; müşteri ve tedarikçi aynı karttadır. - **Pasife alınan tanım kartta görünüyor mu?** Var olan kayıtta değer durur, yeni seçimde listelenmez. -## 10. Dosyalar ve geri alma +### 10. Dosyalar ve geri alma - Tablolar: `sql/object/Prc_T_PaymentTerm.sql`, `Prc_T_PaymentMethod.sql`, `Prc_T_Incoterm.sql`, `Prc_T_DeliveryMethod.sql`. - Wizard'lar: `PaymentTerm.json`, `PaymentMethod.json`, `Incoterm.json`, `DeliveryMethod.json`. @@ -68,7 +71,9 @@ Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalm > Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. -### Ödeme Koşulları — `App.Prc.PaymentTerm` +### Tanımlamalar (`App.Prc.Definitions`) + +#### Ödeme Koşulları — `App.Prc.PaymentTerm` | Özellik | Değer | | --- | --- | @@ -92,7 +97,7 @@ Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalm | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | | `Description` | Açıklama | dxTextArea | | ✓ | | -### Ödeme Yöntemleri — `App.Prc.PaymentMethod` +#### Ödeme Yöntemleri — `App.Prc.PaymentMethod` | Özellik | Değer | | --- | --- | @@ -115,7 +120,7 @@ Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalm | `Journal` | Yevmiye | dxTextBox | | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -### Teslimat Koşulları — `App.Prc.Incoterm` +#### Teslimat Koşulları — `App.Prc.Incoterm` | Özellik | Değer | | --- | --- | @@ -138,7 +143,7 @@ Yok. Tanımlar Yönetim › Tanımlamalar › Kontaklar'ın Satış ve Satınalm | `Name` | Ad | dxTextBox | ✓ | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -### Teslim Yöntemleri — `App.Prc.DeliveryMethod` +#### Teslim Yöntemleri — `App.Prc.DeliveryMethod` | Özellik | Değer | | --- | --- | diff --git a/configs/seeds/docs/modules/HrAttendance.md b/configs/seeds/docs/modules/HrAttendance.md deleted file mode 100644 index 488153e4..00000000 --- a/configs/seeds/docs/modules/HrAttendance.md +++ /dev/null @@ -1,552 +0,0 @@ -# İK › Puantaj ve Devam Takibi (`App.Hr.Attendance`) - -Günlük giriş/çıkış hareketlerinden (PDKS, Excel aktarımı, elle giriş) çalışan × gün puantajı; -personel bazlı aylık puantaj, dönem kapanışı ve PDKS'nin hareket gönderdiği uç. Kişi eşlemesi kullanıcı -kartındaki PDKS Kart No / Sicil No alanlarıyladır. -İzin Yönetimi (onaylı izin → İzinli), Sağlık Kartı (istirahat → Raporlu), Çalışma Takvimi (resmî -tatil / arife) ve Vardiyalar (saat, mola, tolerans) puantajın girdisidir. Çalışan kendi puantajını -**Intranet › Dashboard**'daki **Puantajım** widget'ından izler; İK menüsü İK içindir. Wizard ekranları, -SQL nesneleri, custom component widget'ı, Custom Endpoint ve zamanlanmış işle kuruludur. Çerçeve dışında -tek ek vardır (kullanıcı onayıyla): kullanıcı detayındaki **Puantaj** sekmesi. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Çalışan | Seçtiği ayın net saatini, geç kalma/erken çıkış dakikasını, fazla mesaisini, devamsız/izinli/raporlu günlerini ve yıllık toplamı (270 saatlik fazla mesai sınırıyla) görür | Intranet panosu: **Puantajım** widget'ı → Puantajım (aylar) → ayın günleri · Profil › Puantajım (aylık puantaj salt okunur) | -| İK | Hareketleri izler/düzeltir, elle takip edilen çalışanın gelmediği günü işaretler, aylık puantajı izler, ayı yeniden hesaplar ve kapatır, çalışanın PDKS Kart No'sunu kullanıcı kartına (İş sekmesi) girer, toleransı ve fazla mesai kurallarını ayarlar | İK › Puantaj ve Devam Takibi · Ayarlar › İnsan Kaynakları › Puantaj · Kullanıcı detayı › Puantaj | -| PDKS (servis kullanıcısı) | Kart okutmalarını toplu gönderir | `POST /api/app/custom-endpoint/hr/attendance/` | - -Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur. - ---- - -## 2. Analiz ve kararlar - -### 2.1 Talep - -> Human Resources → Puantaj ve Devam Takibi modülü: günlük hareketler, personel bazlı aylık puantaj. -> Intranet › Dashboard'da aylık puantajıma ulaşabileceğim, ilgili ayın durumunu ve yıllık toplamı gösteren -> widget (sol kolon, anket tarafı). Kolonlar: ilk giriş, son çıkış, net çalışma süresi, mola düşümü, geç -> kalma (dk), erken çıkış (dk), fazla mesai (saat), gün tipi (çalışma, hafta tatili, resmî tatil, izinli, -> raporlu, devamsız). Tolerans vardiya bazında (ör. 10 dk), ayarlardan dinamik. Haftalık 45 saati aşan -> çalışma fazla mesaidir, ücreti %50 zamlıdır (4857 md. 41), yıllık üst sınır 270 saat; ayarlardan -> yönetilir. Veri elle yazılabilir ya da PDKS'den akabilir. Kullanıcı detayında İzinler gibi bir Puantaj -> sekmesi. Diğer modüllerle core koda dokunmadan entegre olmalı. - -### 2.2 Depodan okunanlar (sorulmadı) - -- Vardiya `Hr_T_Shift` (`StartTime`/`EndTime` `SS:dd` metin, `BreakMinutes`, `WorkingHours`, gece vardiyası); çalışanın vardiyası `AbpUsers.ShiftId`. -- Tatiller `Hr_T_WorkCalendar` (`Holiday` / `HalfDay`, `FREQ=YEARLY`); hafta tatili İzin Yönetimi'nin `App.HrSettings.Leave.Work{Gün}` ayarları. -- Onaylı izin `Hr_T_LeaveRequest.ApprovalStatus = 'Onaylandı'`; rapor `Adm_T_UserSickLeave`. -- İstihdam `AbpUsers.HireDate` / `TerminationDate`; departman/pozisyon `DepartmentId` / `JobPositionId`. -- Kullanıcı kartında (İş sekmesi) PDKS Kart No (`AbpUsers.PdksCardNo`) ve Sicil No (`RegistrationNo`) alanları var; ayrı kart tablosu açılmadı. -- Zamanlanmış işin saklı yordamı parametresiz çağrılır (`PlatformBackgroundWorker`); Custom Endpoint gövdesindeki dizi ham JSON metni olarak bağlanır. - -### 2.3 Keşif turu cevapları - -| # | Soru | Seçilen | -| --- | --- | --- | -| 1 | Veri modeli | Ham hareket (`Hr_T_AttendanceLog`) + hesaplanan gün (`Hr_T_Timesheet`); İK günü elle düzeltebilir, düzeltilen gün yeniden hesapta ezilmez | -| 2 | Tolerans yeri | Vardiyada (`LateToleranceMinutes`, `EarlyLeaveToleranceMinutes`), boşsa Ayarlar › Puantaj (10 dk) | -| 3 | Geç kalma dakikası | Tolerans aşılırsa dakikanın tamamı yazılır, aşılmazsa 0 | -| 4 | Fazla mesai | Haftalık (Pzt–Paz) birikim 45 saati aştığı günden itibaren aşan kısım o günlere; hafta tatili ve resmî tatildeki çalışmanın tamamı; yıllık 270 saati aşan satır işaretlenir (engellemez) | -| 5 | PDKS | Excel import + API ucu (Custom Endpoint); kişi eşlemesi kullanıcı kartındaki PDKS Kart No, Sicil No ya da kullanıcı adıyla | -| 6 | Mola | `MAX(vardiya molası, gün içi okutulan çıkış→giriş aralıkları)` | -| 7 | Hesap zamanı | Hareket kaydında (o hafta) + gece işi (okutmasız günler) + dönem kaydı (ay) | -| 8 | Kapanış | İK ayı kilitler, onay akışı yok; müdür ekranı/widget'ı yok | -| 9 | Kullanıcı detayı sekmesi | Core istisnası onaylandı (`Details.tsx` + `TimesheetTab.tsx`, İzinler sekmesi emsali) | -| 10 | Elle takip (üretim sırasında) | Elle takipte yalnız gelinmeyen gün yazılır; yazılmayan iş günü "geldi" kabul edilir | - -### 2.4 Üretimde verilen kararlar - -| Konu | Karar | Neden | -| --- | --- | --- | -| Takip türü | Çalışan bazında otomatik: kullanıcı kartında PDKS Kart No'su olan çalışan **ilk PDKS/aktarım okutmasının gününden itibaren** okutmayla takip edilir (okutmasız iş günü Devamsız); diğerleri elle takip edilir (kayıtsız iş günü vardiya saatleriyle `IsAssumed`). Elle girilen hareket takip türünü değiştirmez | Ayrı bir ayar gerektirmez; kartın sonradan verilmesi geçmiş günleri devamsıza çevirmez | -| Gün sınırı | Hareketin iş günü vardiya bitişi ile bir sonraki başlangıç arasındaki boşluğun ortasından ayrılır (`Hr_V_AttendanceShift.DayOffset`) | Gece vardiyasının 23:50 okutması vardiyanın başladığı ertesi güne yazılır | -| Okutma yönü | `In` / `Out` / `Auto`; `Auto` sıraya göre giriş/çıkış sayılır | PDKS'lerin çoğu yön göndermez | -| Elle düzeltme | Günlük Puantaj'da kaydedilen gün `IsManual = 1` olur; otomatiğe dönmek için satır silinir (yeniden hesap aynı günü kurar) | Ekrandan "elle mi" bilgisini ayrıca istemeden yeniden hesabın düzeltmeyi ezmesini önler | -| Kapalı dönem | Hesap kapalı ayın günlerini yazmaz, yalnız haftalık birikime alır; ekrandan gelen hareket/gün değişikliği `THROW` ile geri alınır; PDKS/gece işi okutmayı `ClosedPeriod` hatasıyla işaretler | PDKS gönderimi tek bir eski okutma yüzünden durmasın | -| Kurulum sırası | Vardiya çözümü view'dadır (`Hr_V_AttendanceShift`) | SQL nesneleri dosya adına göre kurulur; `Hr_F_*` fonksiyonları `Hr_T_*` tablolarından önce oluşur | -| Gece işi kapsamı | `Scope = Host ve Kiracılar`; prosedür veritabanındaki bütün kiracıları işler ve aynı gün işlenen kiracıyı dönemin `NightlyAt` değeriyle atlar | Saklı yordam kiracı parametresi almaz | -| İzin entegrasyonu | `Hr_S_LeaveRequestAfterSave` ve `Hr_S_LeaveSickLeaveSync` sonunda talebin/raporun günleri yeniden hesaplanır | Onaylı izin ve rapor anında puantaja düşer; çekirdek koda dokunulmaz | -| Aylık özet anahtarı | `PeriodKey = {EmployeeId}-{YYYYMM}` hem view'ın `Id`'si hem günlük satırın kolonudur | Alt form ilişkisi tek alanla kurulur | -| Widget sınıfları | Bileşen sınıfları `className` literalleriyle yazılır, koşullu kısım dizge birleştirmeyle eklenir | Safelist üreteci şablon dizgisindeki ifadeyi sınıf sanır | - -### 2.5 Varsayılan kalanlar - -- Varsayılan vardiya 08:00–18:00, mola 60 dk (vardiyası olmayan çalışan için, ayarlarda değişir). -- İzinli/raporlu gün haftalık 45 saat birikimine 0 katkı verir; o gün okutma varsa net süre birikime girer. -- Yarım gün izinli günde geç/erken yazılmaz; arifede (`HalfDay`) vardiya süresinin yarısında biter. -- Yalnız giriş okutması olan gün `IsIncomplete` (Eksik Okutma) işaretlenir, net süre 0'dır. - ---- - -## 3. Menü ve ekranlar - -### 3.1 İK menüsü - -`İnsan Kaynakları › Puantaj ve Devam Takibi` (`App.Hr.Attendance`, sıra 15, `FcAlarmClock`) — yalnız İK. - -| Sıra | Menü (TR / EN) | `ListFormCode` | Kaynak | Alt formlar | Widget'lar | -| --- | --- | --- | --- | --- | --- | -| 1 | Günlük Hareketler / Attendance Events | `App.Hr.AttendanceLog` | `Hr_T_AttendanceLog` | — | Bugün · PDKS (bu ay) · Manuel (bu ay) · Hatalı | -| 2 | Günlük Puantaj / Daily Timesheet | `App.Hr.Timesheet` | `Hr_T_Timesheet` | — | Devamsız gün · Geç kalınan gün · Fazla mesai saati · Eksik okutma (bu ay) | -| 3 | Aylık Puantaj / Monthly Timesheet | `App.Hr.TimesheetMonthly` | `Hr_V_TimesheetMonthly` (salt okunur) | `App.Hr.Timesheet` (`Id → PeriodKey`) | Çalışan · Fazla mesai · Devamsız gün (bu ay) · Yıllık sınırı aşan | -| 4 | Puantaj Dönemleri / Timesheet Periods | `App.Hr.TimesheetPeriod` | `Hr_T_TimesheetPeriod` | — | Açık · Kapalı · Toplam | - -Görünümler: hepsi Grid, Card, Pivot, Chart. Günlük Puantaj'da ekleme yoktur (günleri hesap kurar). -Koşullu biçim: gün tipi (Devamsız kırmızı, Raporlu mor, İzinli mavi, tatiller gri), geç/erken/fazla -mesai > 0, hareket hatası, aylık satırda yıllık sınırın aşılması (satır). - -### 3.2 Çalışana ait ekranlar (menüsüz) - -| Ekran | `ListFormCode` | Satır süzmesi | Yapılabilen | -| --- | --- | --- | --- | -| Puantajım | `App.Hr.MyTimesheet` | `EmployeeId = @USERID` (`Hr_V_TimesheetMonthly`) | Ayları görür; detayda ayın günleri | -| Puantaj Günlerim | `App.Hr.MyTimesheetDay` | `EmployeeId = @USERID` (`Hr_T_Timesheet`) | Puantajım'ın sekmesi (`Id → PeriodKey`), salt okunur | - -### 3.3 Intranet › Dashboard widget'ı - -Sol kolon (`Column: 0`), İzinlerim'in (35/36) altında; kayıt `data/App.DeveloperKit.IntranetWidgets.json`. - -| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Buton | -| --- | --- | --- | --- | --- | -| `my-timesheet` · 37 | `MyTimesheetWidget` | `App.Hr.MyTimesheet` | Ay seçici (varsayılan içinde bulunulan ay); net saat, çalışılan gün, fazla mesai, geç kalma dk, erken çıkış dk, devamsız gün; izinli/raporlu/tatil günü; yıl toplamı (net saat, geç kalma, devamsız) ve fazla mesai / yıllık sınır çubuğu | Puantajım | - -Bileşen code modunda, rotasızdır; veriyi Puantajım ekranının sorgusundan okur (`GET /api/app/list-form-select/select`). - -### 3.4 Kullanıcı detayı › Puantaj - -`ui/src/views/admin/user-management/TimesheetTab.tsx`: içinde bulunulan yılın sekiz kartı (çalışma günü, -net saat, fazla mesai — yıllık sınırı aşınca kırmızı —, geç kalma, erken çıkış, devamsız, izinli, raporlu), -altında kullanıcıya süzülmüş **Aylık Puantaj**, **Günlük Puantaj** ve **Günlük Hareketler** listeleri. Her -parça kendi ekran yetkisiyle görünür; yeni hareket satırının `EmployeeId`'si süzgeçten dolar. - -### 3.5 Ayarlar - -Ayarlar › İnsan Kaynakları › Puantaj (`App.HrSettings` › `App.HrSettings.Attendance`, sağlayıcılar `T|G|D`): - -| Kod | Varsayılan | Kullanım | -| --- | --- | --- | -| `App.HrSettings.Attendance.LateToleranceMinutes` | 10 | Vardiyada tolerans yoksa | -| `App.HrSettings.Attendance.EarlyLeaveToleranceMinutes` | 10 | Vardiyada tolerans yoksa | -| `App.HrSettings.Attendance.WeeklyLimitHours` | 45 | Haftalık fazla mesai sınırı | -| `App.HrSettings.Attendance.OvertimeRate` | 1.5 | Zamlı fazla mesai saati çarpanı (Aylık Puantaj) | -| `App.HrSettings.Attendance.AnnualOvertimeLimitHours` | 270 | Yıllık sınır (işaret, widget çubuğu) | -| `App.HrSettings.Attendance.DefaultShiftStart` / `DefaultShiftEnd` | 08:00 / 18:00 | Vardiyası olmayan çalışan | -| `App.HrSettings.Attendance.DefaultBreakMinutes` | 60 | Vardiyası (ya da vardiya molası) olmayan çalışan | - -Hafta tatili İzin Yönetimi'nin çalışma günü ayarlarından (`App.HrSettings.Leave.Work{Gün}`) okunur. - ---- - -## 4. Veri modeli - -| Tablo / nesne | Kolonlar | Not | -| --- | --- | --- | -| `AbpUsers` (mevcut) | `PdksCardNo`, `RegistrationNo`, `ShiftId`, `HireDate`, `TerminationDate` | Kişi eşlemesi, vardiya, istihdam aralığı | -| `Hr_T_AttendanceLog` | `EmployeeId` (boş olabilir), `CardNo`, `EventTime` (yerel saat), `Direction` (In/Out/Auto), `Source` (Manual/Pdks/Import), `DeviceCode`, `Note`, `WorkDate` (hesaplanır), `IsProcessed`, `ProcessError` (UnknownCard/ClosedPeriod) | `IsProcessed = 0` satırları işlenmeyi bekler | -| `Hr_T_Timesheet` | `EmployeeId`, `WorkDate`, `PeriodYear`, `PeriodMonth`, `PeriodKey`, `ShiftId`, `DayType` (Work/WeeklyOff/Holiday/Leave/Sick/Training/Absent), `LeaveTypeId` (izinli/raporlu günün türü), `TrainingId` (eğitim günü), `FirstIn`, `LastOut`, `BreakMinutes`, `NetMinutes`, `NetHours`, `LateMinutes`, `EarlyLeaveMinutes`, `OvertimeHours`, `IsManual`, `IsIncomplete`, `IsAssumed`, `Note`, `CalculatedAt` | Çalışan × gün tek etkin satır | -| `Hr_T_TimesheetPeriod` | `PeriodYear`, `PeriodMonth`, `Status` (Open/Closed), `CalculatedAt`, `ClosedAt`, `ClosedById`, `NightlyAt`, `Note` | Kiracıda yıl+ay tekil (prosedür denetler) | -| `Hr_T_Shift` (+) | `LateToleranceMinutes`, `EarlyLeaveToleranceMinutes` | Vardiyalar ekranında düzenlenir | -| `Hr_V_AttendanceShift` | Çalışanın dakika cinsinden vardiyası, mola, toleranslar, `DayOffset` | Varsayılanlar ayardan | -| `Hr_V_TimesheetMonthly` | Çalışan × ay toplamları, `UnpaidLeaveDays` (ücretsiz türdeki izinli gün — bordroda eksik gün), `TrainingDays`, `OvertimePaidHours`, `YearOvertimeHours`, `AnnualOvertimeLimit`, `IsOverAnnualLimit`, `PeriodStatus` | `Id = PeriodKey` | - -Entity yoktur (wizard tabloları); `sql/object/`. - ---- - -## 5. İş kuralları ve hesaplar - -### 5.1 Prosedürler - -| Nesne | Ne yapar | Çağıran | -| --- | --- | --- | -| `Hr_S_TimesheetCalculate @TenantId, @EmployeeId, @From, @To, @ActorId` | Aralığı tam haftalara genişletip (bugünle sınırlı) çalışan × gün satırlarını kurar/günceller; kapalı ayı yazmaz | Aşağıdakilerin hepsi, izin ve rapor prosedürleri | -| `Hr_S_AttendanceProcess @FailOnClosed` | İşlenmemiş hareketlerde kart → çalışan, iş günü, hata; etkilenen günleri (eski + yeni) yeniden hesaplar | Günlük Hareketler kayıt/silme, PDKS ucu, gece işi | -| `Hr_S_AttendanceImport @TenantId, @UserId, @Items` | PDKS gönderimini (`CardNo`, `RegistrationNo` ya da `UserName`; `EventTime`, `Direction`, `DeviceCode`) yazar, tekrarı atlar; `Received/Inserted/Skipped/Errors` döner | Custom Endpoint | -| `Hr_S_TimesheetPeriodAfterSave @PeriodId, @ActorId` | Yıl/ay doğrulama ve tekillik; açık dönemde ayı yeniden hesaplar; kapatmada son hesap + kilit | Puantaj Dönemleri kayıt | -| `Hr_S_TimesheetNightly` | Kart numarası sonradan girilen "Kart tanımsız" okutmaları yeniden kuyruğa alır ve işler; her kiracı için ayın dönemini açar, dünün ayını ve kapanmamışsa önceki ayı hesaplar | Zamanlanmış iş `Timesheet Nightly` (02:00) | -| `Hr_F_WorkCalendarDayType @TenantId, @Day` | Güne düşen `Holiday` / `HalfDay` | Hesap | -| `Hr_F_TimesheetPeriodClosed @TenantId, @From, @To` | Aralığın değdiği aylardan biri kapalı dönem mi | İzin, rapor ve izin guard prosedürleri | -| `Hr_S_TrainingSync @TrainingId, @UserId, @ActorId` | Katılımcının (boşsa bütün katılımcıların) eğitim günlerini yeniden hesaplar, bağlı gelişim aksiyonunu tamamlar | Eğitimler ve Katılımcılar kayıt/silme | -| `Hr_S_WorkCalendarAfterSave @CalendarId, @ActorId` | Takvim satırına denk gelen izinlerin gün sayısını ve puantajı yeniden hesaplar | Çalışma Takvimi kayıt/silme | - -### 5.2 Günün hesabı - -1. **Gün tipi** (öncelik sırasıyla): - 1. rapor (Sağlık Kartı istirahati; takvim günü, hafta sonu dahil) → `Sick`; - 2. onaylı **ücretsiz** izin (`LeaveType.IsPaid = 0`: ücretsiz izin, doğum izni; takvim günü) → `Leave`; - 3. takvim tatili → `Holiday`; ayarda çalışma günü değil → `WeeklyOff`; - 4. onaylı **ücretli** izin → `Leave` (ücretli izne denk gelen tatil izin günü değildir, 4857 md. 56 — izin gün sayısıyla aynı kural); yarım gün izinde okutma varsa `Work`; - 5. okutma var → `Work`; - 6. eğitime "Katıldı" işaretli katılımcı → `Training` (vardiya saatleriyle, `IsAssumed`); - 7. elle takip edilen çalışan → `Work` (`IsAssumed`, vardiya saatleri); geçmiş gün → `Absent`; kartlı çalışanın okutmasız bugünü yazılmaz. - - İzinli/raporlu günde `LeaveTypeId`, eğitim gününde `TrainingId` yazılır. İstihdam dışındaki okutmasız gün yazılmaz. -2. **İlk giriş / son çıkış**: ilk `In` (yoksa ilk okutma) / son `Out` (ilk girişten sonraysa). -3. **Mola** = `MAX(vardiya molası, ilk giriş–son çıkış arasındaki çıkış→giriş aralıkları)`, brüt süreyi aşamaz; elle düzeltilen günde girilen mola. -4. **Net** = son çıkış − ilk giriş − mola. -5. **Geç kalma** = ilk giriş − vardiya başlangıcı, tolerans aşılırsa tamamı; **erken çıkış** = vardiya bitişi (arifede yarı süre) − son çıkış, tolerans aşılırsa tamamı. Yalnız `Work` gününde; eğitim günü haftalık birikime çalışma gibi girer. -6. **Fazla mesai** = `WeeklyOff`/`Holiday` gününde net sürenin tamamı; diğer günlerde haftanın kümülatif netinin sınırı aştığı kısım (`max(0, kümülatif − sınır) − max(0, önceki kümülatif − sınır)`). -7. Kaynağı kalkan gün: tek çalışanlık hesap, artık hiçbir izin/rapor/katılımla örtüşmeyen `Leave`/`Sick`/`Training` günlerini (talebin tarihi değişti, rapor ya da katılım silindi) aralığa katar; eski günler aynı işlemde düzelir. -8. Aylık view: `OvertimePaidHours = OvertimeHours × OvertimeRate`; `YearOvertimeHours` ocaktan o aya birikim; `IsOverAnnualLimit` sınır aşımı. - -### 5.3 Ekran komutları - -| Ekran | Komut | -| --- | --- | -| Günlük Hareketler | Ekle/düzenle/sil sonrası satır işlenmemiş işaretlenir → `Hr_S_AttendanceProcess 1` (kapalı dönemde kayıt geri alınır) | -| Günlük Puantaj | Düzenle/sil öncesi kapalı dönem kontrolü; düzenleme sonrası `IsManual = 1, IsAssumed = 0` ve günün haftası yeniden hesaplanır; silme sonrası gün otomatik yeniden kurulur | -| Puantaj Dönemleri | Kayıt sonrası `Hr_S_TimesheetPeriodAfterSave`; kapalı dönem silinemez; ayda onay bekleyen izin varsa kapatılamaz | - -Hata kodları: 51200 (kapalı döneme hareket), 51201 (kapalı dönemin günü), 51210 (PDKS gövdesi), 51220–51223 -(dönem; 51223 onay bekleyen izin), 51118 (kapalı döneme izin), 51120 (kapalı döneme rapor). - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Kök `App.Hr.Attendance` (sıra 9); dört ekran altında, her biri -`.Create/.Update/.Delete/.Export/.Import/.Note` ile. `App.Hr.MyTimesheet` (sıra 10) kökte, -`App.Hr.MyTimesheetDay` onun altında. Ayar yetkisi `App.HrSettings.Attendance` (`App.Administration` -grubu, `App.HrSettings` altında). Hiçbir yetki role otomatik atanmaz. - -| Rol | Yetkiler | -| --- | --- | -| Tüm çalışanlar | `App.Hr.MyTimesheet`, `App.Hr.MyTimesheetDay` (widget ve Puantajım) | -| İK | `App.Hr.Attendance` dalının tamamı, `App.HrSettings.Attendance` | -| PDKS servis kullanıcısı | `PDKS` rolü + `App.DeveloperKit.CustomEndpoints.Post` | - ---- - -## 7. Entegrasyonlar - -| Modül | Yön | Nasıl | -| --- | --- | --- | -| Kimlik › Kullanıcılar | → puantaj | PDKS Kart No / Sicil No kişi eşlemesi, vardiya, işe giriş/çıkış; kart numarası değişikliği gece işinde yansır | -| İzin Yönetimi | → puantaj | `Hr_S_LeaveRequestAfterSave` (kayıt, karar, silme) sonunda talebin günleri — tarihi değiştiyse eski günleri de — yeniden hesaplanır; onaylı izin `Leave` | -| Sağlık Kartı › İstirahatler | ↔ izin, → puantaj | `Hr_S_LeaveSickLeaveSync` (kayıt, silme) raporu onaylı Rapor talebine eşler, rapora denk gelen izin günlerini bakiyeye döndürür (`Hr_S_LeaveDaysRefresh`), günleri yeniden hesaplar; rapor `Sick` | -| Eğitimler | → puantaj | Katıldı işaretli katılımcının eğitim günleri `Training`; eğitim/katılımcı kaydı `Hr_S_TrainingSync` ile hemen yansır | -| Çalışma Takvimi | → izin, → puantaj | Tatil `Holiday`, arife `HalfDay` (yarım vardiya); takvim kaydı denk gelen izinlerin gün sayısını ve puantajı hemen yeniler (`Hr_S_WorkCalendarAfterSave`) | -| Vardiyalar / kullanıcı vardiyası | → puantaj | Saat, mola, tolerans; değişiklik gece işinde ya da dönem kaydında yansır | -| İzin ayarları | → puantaj | Hafta tatili günleri | -| PDKS | → hareket | Custom Endpoint `POST /api/app/custom-endpoint/hr/attendance/` (`data/App.DeveloperKit.CustomEndpoints.json`, `PermissionsJson`: rol `PDKS`) | -| Excel | → hareket | Günlük Hareketler import'u aynı kayıt yolundan (`InsertAfterCommand`) geçer; `Source` boş gelir ve `Import` yazılır | -| Intranet | ← puantaj | `my-timesheet` widget'ı | -| Kullanıcı detayı | ← puantaj | Puantaj sekmesi | - -### 7.1 Çakışma kuralları (modüller birbirine zıt sonuç vermez) - -| Durum | Kural | Nerede | -| --- | --- | --- | -| Raporlu gün | Devamsız yazılmaz; `Sick` her şeyin önündedir (okutma olsa da) | `Hr_S_TimesheetCalculate` | -| Yıllık izin sırasında rapor | Rapora denk gelen izin günü izinden sayılmaz, bakiyeye döner; puantajda `Sick` | `Hr_F_LeaveNetDays`, `Hr_S_LeaveDaysRefresh` | -| Rapor talebi onay beklerken | Sağlık kartına ve puantaja düşmez; onayla istirahat kaydı oluşur, redde kalkar | `Hr_S_LeaveRequestAfterSave` | -| Ücretli izne denk gelen tatil | Puantajda `Holiday`/`WeeklyOff`; izin gün sayısına girmez (4857 md. 56) | hesap + `Hr_F_LeaveWorkDays` | -| Ücretsiz izin / doğum izni | Hafta tatili ve genel tatil dahil `Leave` (ücret doğmaz); aylıkta `UnpaidLeaveDays` | hesap + aylık view | -| Eğitime katılan | Okutması yoksa devamsız değil `Training`; okutması varsa `Work` | hesap | -| Kapalı puantaj ayı | İzin talebi ve rapor eklenemez/değiştirilemez/silinemez (51118, 51120); onay bekleyen izni olan ay kapatılamaz (51223) | guard + kayıt prosedürleri + dönem kaydı | -| İstihdam dışı | İzin tarihleri işe giriş – işten çıkış arasında olmalı (51119); puantaj istihdam dışında gün yazmaz | `Hr_S_LeaveRequestAfterSave`, hesap | -| Takvime sonradan girilen bayram | Denk gelen izinlerin gün sayısı ve puantaj hemen yenilenir | `Hr_S_WorkCalendarAfterSave` | - -PDKS gövdesi: - -```json -{ "Items": [ { "CardNo": "000123", "EventTime": "2026-10-05T08:02:00", "Direction": "In", "DeviceCode": "GATE-1" } ] } -``` - -`Items` dizi ya da JSON metni olabilir; `CardNo` yerine `UserName` gönderilebilir. Endpoint kaydı -kiracıya aittir (`CustomEndpoint` `IMultiTenant`): seed satırı host'a kurulur, kiracıda Developer Kit › -Custom Endpoints'ten aynı SQL ve parametrelerle eklenir. - ---- - -## 8. Akış örneği - -1. İK üretim çalışanlarının kullanıcı kartına (İş sekmesi) PDKS Kart No girer; ofis çalışanlarında alan boştur (elle takip). -2. PDKS her 5 dakikada okutmaları uca gönderir; **Günlük Hareketler**'e düşer, Günlük Puantaj o hafta için güncellenir. Tanımsız kart "Kart tanımsız" görünür; numara kullanıcı kartına girilince gece işi okutmayı işler. -3. Gece 02:00'de iş dünü kurar: kartlı çalışanın okutmasız iş günü Devamsız, elle takip edilen çalışanın günü vardiya saatleriyle Varsayılan çalışma. -4. Ofis çalışanı bir gün gelmez; İK **Günlük Puantaj**'da o günü Devamsız yapar (gün Elle olur). -5. Ay sonunda İK **Aylık Puantaj**'ı kontrol eder, yıllık sınırı aşanları görür; **Puantaj Dönemleri**'nde ayı Kapalı yapar. -6. Çalışan panodaki **Puantajım**'da ayını ve yıl toplamını görür, butonla aylarına ve günlerine iner. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Okutması olmayan çalışan neden hep "geldi" görünüyor?** Kullanıcı kartında PDKS Kart No yoksa (ya da henüz PDKS okutması gelmediyse) elle takip edilir; gelinmeyen gün Günlük Puantaj'da işaretlenir. İlk PDKS okutmasından itibaren okutmayla takip edilir. - -**Düzelttiğim gün neden yeniden hesapta değişmiyor?** Elle düzeltilen gün korunur. Otomatiğe döndürmek için satırı silin. - -**Vardiya/takvim/ayar değişti, puantaj eski.** Gece işi dünün ve önceki ayın günlerini yeniler; hemen yansıtmak için Puantaj Dönemleri'nde ilgili ayı kaydedin. - -**Kapalı aya PDKS okutması geldi.** Okutma `Kapalı dönem` hatasıyla kalır; dönem açılıp kaydedilirse hareket ekranından düzenlenerek işlenir. - -**Fazla mesai hafta tatilinde neden tamamı?** Talepte istenen kural (hafta tatili ve resmî tatilde çalışma fazla mesaidir); haftalık 45 saat birikimine bu günler katılmaz. - -**İzin talebinin tarihi değişti, eski günler ne olur?** Aynı kayıtta düzelir: tek çalışanlık hesap kaynağı kalmayan izinli/raporlu/eğitim günlerini aralığa katar. - -**Hasta raporu alan çalışan devamsız mı yazılır?** Hayır. Rapor günleri (hafta sonu dahil) `Raporlu`dur; aynı güne izin ya da okutma düşse bile rapor önce gelir. Yıllık izindeyken rapor alındıysa o günler izinden düşmez, bakiyeye döner. - -**Eğitimdeki çalışan devamsız görünüyor.** Katılımcı satırında durum "Katıldı" olmalıdır; "Katılmadı/Mazeretli" günler normal hesaplanır. - -**Çalışma Takvimi kaydı sonrası hangi günler yenilenir?** Satırın tarihleri (yıllık tekrarlıda bu yıl ve gelecek yıl). Tarihi değiştirilen satırın eski günleri gece işinde ya da dönem kaydında düzelir. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{AttendanceLog,Timesheet,TimesheetPeriod}.sql` | Tablolar | -| `configs/seeds/sql/object/Hr_T_Shift.sql` | Vardiya toleransı kolonları | -| `configs/seeds/sql/object/Hr_V_{AttendanceShift,TimesheetMonthly}.sql` | View'lar | -| `configs/seeds/sql/object/Hr_F_{WorkCalendarDayType,TimesheetPeriodClosed,LeaveNetDays}.sql` | Takvim günü türü, kapalı dönem, rapordan arınmış izin günü | -| `configs/seeds/sql/object/Hr_S_{TimesheetCalculate,AttendanceProcess,AttendanceImport,TimesheetPeriodAfterSave,TimesheetNightly}.sql` | Hesap ve tetikler | -| `configs/seeds/sql/object/Hr_S_{LeaveRequestAfterSave,LeaveRequestGuard,LeaveSickLeaveSync,LeaveDaysRefresh}.sql` | İzin/rapor → puantaj tetiği, kapalı dönem guard'ı, rapor → izin günü | -| `configs/seeds/sql/object/Hr_S_{TrainingSync,WorkCalendarAfterSave}.sql` | Eğitim ve takvim → puantaj tetiği | -| `configs/seeds/wizard/{LeaveRequest,MyLeaveRequest,HealthCardSickLeave,Training,TrainingParticipant,WorkCalendar}.json` | Tetik komutları (silme dahil) | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` (`UserSickLeave`) | Kullanıcı detayındaki istirahat listesinin silme tetiği | -| `configs/seeds/wizard/{AttendanceLog,Timesheet,TimesheetMonthly,TimesheetPeriod,MyTimesheet,MyTimesheetDay}.json` | 6 wizard | -| `configs/seeds/wizard/Shift.json` | Tolerans alanları | -| `configs/seeds/data/App.DeveloperKit.CustomComponents/1bca19aa-e144-5e4c-b23b-9eddd4dafd19.json` | `MyTimesheetWidget` | -| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json` | `my-timesheet` | -| `configs/seeds/data/App.DeveloperKit.CustomEndpoints.json` | PDKS ucu | -| `configs/seeds/data/App.BackgroundWorkers.RecurringJobs.json` | `Timesheet Nightly` | -| `configs/seeds/data/App.SettingDefinitions.json` | `App.HrSettings.Attendance.*` | -| `configs/seeds/data/{App.Menus.Menu,Abp.Identity.Permissions,App.Languages.LanguageText}.json` | Menü, yetki, dil | -| `ui/src/views/admin/user-management/{TimesheetTab,Details}.tsx` | Kullanıcı detayı › Puantaj | - -Geri alma: Wizard Manager'dan altı ekran silinir; widget, endpoint, iş ve ayar satırları kendi -ekranlarından kaldırılır. İzin/rapor prosedürlerindeki `Hr_S_TimesheetCalculate` çağrısı kaldırılmadan -prosedür silinmemelidir. Tablolar düşürülmez. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Günlük Hareketler — `App.Hr.AttendanceLog` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/AttendanceLog.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Attendance` › `App.Hr.AttendanceLog` (sıra 1) | -| Yetki | `App.Hr.AttendanceLog` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Günlük Hareketler — PDKS'den (kart okuyucu), Excel aktarımından gelen ya da elle girilen ham giriş/çıkış okutmaları. | -| Kaynak | `Hr_T_AttendanceLog` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Attendance.Widget.Today`, `App.Hr.Attendance.Widget.Pdks`, `App.Hr.Attendance.Widget.Manual`, `App.Hr.Attendance.Widget.Error` | -| Komutlar | InsertAfter: `Hr_S_AttendanceProcess` · UpdateAfter: `Hr_S_AttendanceProcess` · DeleteAfter: `Hr_S_AttendanceProcess` | -| Form varsayılanları | Direction=Auto, Source=Manual | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `CardNo` | Kart No | dxTextBox | | ✓ | | -| `EventTime` | Zaman | dxDateBox | ✓ | ✓ | | -| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: In, Out, Auto | -| `Source` | Kaynak | dxSelectBox | | ✓ | liste: Manual, Pdks, Import | -| `DeviceCode` | Cihaz | dxTextBox | | ✓ | | -| `WorkDate` | İş Günü | dxDateBox | | | | -| `ProcessError` | Hata | dxSelectBox | | | liste: UnknownCard, ClosedPeriod | -| `Note` | Not | dxTextArea | | ✓ | | - -### Günlük Puantaj — `App.Hr.Timesheet` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Timesheet.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Attendance` › `App.Hr.Timesheet` (sıra 2) | -| Yetki | `App.Hr.Timesheet` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Günlük Puantaj — çalışan × gün satırı: ilk giriş, son çıkış, net çalışma süresi, mola düşümü, geç kalma (dk), erken çıkış (dk), fazla mesai (saat) ve gün tipi (çalışma, hafta tatili, resmî tatil, izinli, raporlu, eğitimde, devamsız). | -| Kaynak | `Hr_T_Timesheet` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Attendance.Widget.Absent`, `App.Hr.Attendance.Widget.Late`, `App.Hr.Attendance.Widget.Overtime`, `App.Hr.Attendance.Widget.Incomplete` | -| Komutlar | UpdateBefore: SQL · UpdateAfter: `Hr_S_TimesheetCalculate` · DeleteBefore: SQL · DeleteAfter: `Hr_S_TimesheetCalculate` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `WorkDate` | İş Günü | dxDateBox | | ✓ | | -| `DayType` | Gün Tipi | dxSelectBox | ✓ | ✓ | liste: Work, WeeklyOff, Holiday, Training, Leave, Sick, Absent | -| `LeaveTypeId` | İzin Türü | dxSelectBox | | ✓ | sorgu: Hr_T_LeaveType | -| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | -| `ShiftId` | Vardiya | dxSelectBox | | | sorgu: Hr_T_Shift | -| `FirstIn` | İlk Giriş | dxDateBox | | ✓ | | -| `LastOut` | Son Çıkış | dxDateBox | | ✓ | | -| `NetHours` | Net Çalışma (saat) | dxNumberBox | | | | -| `BreakMinutes` | Mola Düşümü (dk) | dxNumberBox | | ✓ | | -| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | | | -| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | | | -| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | | | -| `IsAssumed` | Varsayılan | dxCheckBox | | | | -| `IsManual` | Elle | dxCheckBox | | | | -| `IsIncomplete` | Eksik Okutma | dxCheckBox | | | | -| `Note` | Not | dxTextArea | | ✓ | | -| `PeriodYear` | Yıl | dxNumberBox | | | | -| `PeriodMonth` | Ay | dxNumberBox | | | | -| `PeriodKey` | Dönem Anahtarı | dxTextBox | | | | - -### Aylık Puantaj — `App.Hr.TimesheetMonthly` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TimesheetMonthly.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Attendance` › `App.Hr.TimesheetMonthly` (sıra 3) | -| Yetki | `App.Hr.TimesheetMonthly` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Aylık Puantaj — Günlük Puantaj'ın personel bazlı aylık toplamı (salt okunur). | -| Kaynak | `Hr_V_TimesheetMonthly` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.Timesheet` (Id → PeriodKey) | -| Widget'lar | `App.Hr.Attendance.Widget.Employees`, `App.Hr.Attendance.Widget.Overtime`, `App.Hr.Attendance.Widget.Absent`, `App.Hr.Attendance.Widget.OverLimit` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `PeriodYear` | Yıl | dxNumberBox | | ✓ | | -| `PeriodMonth` | Ay | dxNumberBox | | ✓ | | -| `PeriodStatus` | Dönem Durumu | dxSelectBox | | ✓ | liste: Open, Closed | -| `WorkDays` | Çalışma Günü | dxNumberBox | | ✓ | | -| `NetHours` | Net Çalışma (saat) | dxNumberBox | | ✓ | | -| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | ✓ | | -| `LateDays` | Geç Kalınan Gün | dxNumberBox | | ✓ | | -| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | ✓ | | -| `EarlyLeaveDays` | Erken Çıkılan Gün | dxNumberBox | | ✓ | | -| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `OvertimePaidHours` | Zamlı Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `WeeklyOffDays` | Hafta Tatili | dxNumberBox | | ✓ | | -| `HolidayDays` | Resmî Tatil | dxNumberBox | | ✓ | | -| `LeaveDays` | İzinli Gün | dxNumberBox | | ✓ | | -| `UnpaidLeaveDays` | Ücretsiz İzinli Gün | dxNumberBox | | ✓ | | -| `TrainingDays` | Eğitim Günü | dxNumberBox | | ✓ | | -| `SickDays` | Raporlu Gün | dxNumberBox | | ✓ | | -| `AbsentDays` | Devamsız Gün | dxNumberBox | | ✓ | | -| `IncompleteDays` | Eksik Okutmalı Gün | dxNumberBox | | ✓ | | -| `AssumedDays` | Varsayılan Gün | dxNumberBox | | ✓ | | -| `YearOvertimeHours` | Yıllık Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `AnnualOvertimeLimit` | Yıllık Fazla Mesai Sınırı | dxNumberBox | | ✓ | | -| `IsOverAnnualLimit` | Yıllık Sınır Aşıldı | dxNumberBox | | | | - -### Puantaj Dönemleri — `App.Hr.TimesheetPeriod` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TimesheetPeriod.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Attendance` › `App.Hr.TimesheetPeriod` (sıra 4) | -| Yetki | `App.Hr.TimesheetPeriod` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Puantaj Dönemleri — aylık puantaj dönemleri: yeniden hesaplama ve kapanış. | -| Kaynak | `Hr_T_TimesheetPeriod` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Attendance.Widget.Open`, `App.Hr.Attendance.Widget.Closed`, `App.Widget.Total` | -| Komutlar | InsertAfter: `Hr_S_TimesheetPeriodAfterSave` · UpdateAfter: `Hr_S_TimesheetPeriodAfterSave` · DeleteBefore: SQL | -| Form varsayılanları | PeriodYear=@YEAR, PeriodMonth=@MONTH, Status=Open | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodYear` | Yıl | dxNumberBox | ✓ | ✓ | | -| `PeriodMonth` | Ay | dxNumberBox | ✓ | ✓ | | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, Closed | -| `CalculatedAt` | Hesaplanma | dxDateBox | | | | -| `ClosedAt` | Kapanış | dxDateBox | | | | -| `ClosedById` | Kapatan | dxSelectBox | | | sorgu: AbpUsers | -| `NightlyAt` | Gece İşi | dxDateBox | | | | -| `Note` | Not | dxTextArea | | ✓ | | - -### Puantajım — `App.Hr.MyTimesheet` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyTimesheet.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyTimesheet` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Puantajım — kendi aylık puantajınız: ay ay çalışma günü, net saat, geç kalma, erken çıkış, fazla mesai ve izinli/raporlu/devamsız günler. | -| Kaynak | `Hr_V_TimesheetMonthly` · filtre `"EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.MyTimesheetDay` (Id → PeriodKey) | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `PeriodYear` | Yıl | dxNumberBox | | ✓ | | -| `PeriodMonth` | Ay | dxNumberBox | | ✓ | | -| `PeriodStatus` | Dönem Durumu | dxSelectBox | | ✓ | liste: Open, Closed | -| `WorkDays` | Çalışma Günü | dxNumberBox | | ✓ | | -| `NetHours` | Net Çalışma (saat) | dxNumberBox | | ✓ | | -| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | ✓ | | -| `LateDays` | Geç Kalınan Gün | dxNumberBox | | ✓ | | -| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | ✓ | | -| `EarlyLeaveDays` | Erken Çıkılan Gün | dxNumberBox | | ✓ | | -| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `OvertimePaidHours` | Zamlı Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `WeeklyOffDays` | Hafta Tatili | dxNumberBox | | ✓ | | -| `HolidayDays` | Resmî Tatil | dxNumberBox | | ✓ | | -| `LeaveDays` | İzinli Gün | dxNumberBox | | ✓ | | -| `UnpaidLeaveDays` | Ücretsiz İzinli Gün | dxNumberBox | | ✓ | | -| `TrainingDays` | Eğitim Günü | dxNumberBox | | ✓ | | -| `SickDays` | Raporlu Gün | dxNumberBox | | ✓ | | -| `AbsentDays` | Devamsız Gün | dxNumberBox | | ✓ | | -| `IncompleteDays` | Eksik Okutmalı Gün | dxNumberBox | | ✓ | | -| `AssumedDays` | Varsayılan Gün | dxNumberBox | | ✓ | | -| `YearOvertimeHours` | Yıllık Fazla Mesai (saat) | dxNumberBox | | ✓ | | -| `AnnualOvertimeLimit` | Yıllık Fazla Mesai Sınırı | dxNumberBox | | ✓ | | -| `IsOverAnnualLimit` | Yıllık Sınır Aşıldı | dxNumberBox | | | | - -### Puantaj Günlerim — `App.Hr.MyTimesheetDay` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyTimesheetDay.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyTimesheetDay` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Puantaj Günlerim — puantajınızın günleri: ilk giriş, son çıkış, net çalışma, mola, geç kalma, erken çıkış, fazla mesai ve gün tipi. | -| Kaynak | `Hr_T_Timesheet` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `WorkDate` | İş Günü | dxDateBox | | | | -| `DayType` | Gün Tipi | dxSelectBox | | | liste: Work, WeeklyOff, Holiday, Training, Leave, Sick, Absent | -| `LeaveTypeId` | İzin Türü | dxSelectBox | | | sorgu: Hr_T_LeaveType | -| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | -| `FirstIn` | İlk Giriş | dxDateBox | | | | -| `LastOut` | Son Çıkış | dxDateBox | | | | -| `NetHours` | Net Çalışma (saat) | dxNumberBox | | | | -| `BreakMinutes` | Mola Düşümü (dk) | dxNumberBox | | | | -| `LateMinutes` | Geç Kalma (dk) | dxNumberBox | | | | -| `EarlyLeaveMinutes` | Erken Çıkış (dk) | dxNumberBox | | | | -| `OvertimeHours` | Fazla Mesai (saat) | dxNumberBox | | | | -| `IsAssumed` | Varsayılan | dxCheckBox | | | | -| `IsManual` | Elle | dxCheckBox | | | | -| `IsIncomplete` | Eksik Okutma | dxCheckBox | | | | -| `Note` | Not | dxTextBox | | | | -| `PeriodKey` | Dönem Anahtarı | dxTextBox | | | | - - diff --git a/configs/seeds/docs/modules/HrDefinitions.md b/configs/seeds/docs/modules/HrDefinitions.md deleted file mode 100644 index 9e397390..00000000 --- a/configs/seeds/docs/modules/HrDefinitions.md +++ /dev/null @@ -1,351 +0,0 @@ -# İK › Tanımlamalar (`App.Hr.Definitions`) - -İK modüllerinin ortak sözlükleri. Bu doküman iki işi görür: (1) Tanımlamalar menüsünün **dizinidir** -— her tanımın hangi modüle ait olduğunu ve nerede kullanıldığını gösterir; (2) belirli bir modüle ait -olmayan genel tanımları (kurum doktoru, yeterlilik belgesi, hastane, hastane bölümü, evrak türü, izin -türü, masraf türü, yan hak türü) anlatır. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Dizin - -`İnsan Kaynakları › Tanımlamalar` (`App.Hr.Definitions`, ikon `FcFilingCabinet`) - -| Sıra | Menü | `ListFormCode` | Kaynak | Ayrıntı | -| --- | --- | --- | --- | --- | -| 1 | Departmanlar | `App.Hr.Department` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | -| 2 | Pozisyonlar | `App.Hr.JobPosition` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | -| 3 | Yetenek Tipleri | `App.Hr.SkillType` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | -| 4 | Yeterlilik Belgeleri | `App.Hr.Certificate` | Wizard | bu doküman | -| 5 | Evrak Türleri | `App.Hr.DocumentType` | Wizard | bu doküman | -| 6 | Aday Kaynakları | `App.Hr.CandidateSource` | Wizard | [HrRecruitment.md](HrRecruitment.md) | -| 7 | Ret Sebepleri | `App.Hr.RejectionReason` | Wizard | [HrRecruitment.md](HrRecruitment.md) | -| 8 | Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | Wizard | [HrRecruitment.md](HrRecruitment.md) | -| 9 | Masraf Türleri | `App.Hr.ExpenseType` | Wizard | bu doküman | -| 10 | Yan Hak Türleri | `App.Hr.BenefitType` | Wizard | bu doküman | -| 11 | Vardiyalar | `App.Hr.Shift` | Wizard | [HrWorkCalendar.md](HrWorkCalendar.md) · [HrAttendance.md](HrAttendance.md) | -| 12 | İzin Türleri | `App.Hr.LeaveType` | Wizard | bu doküman | -| 13 | Kurum Doktorları | `App.Hr.Doctor` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | -| 14 | Hastaneler | `App.Hr.Hospital` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | -| 15 | Hastane Bölümleri | `App.Hr.HospitalDepartment` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | -| 16 | Performans Dereceleri | `App.Hr.PerformanceRating` | Wizard | [HrPerformance.md](HrPerformance.md) | -| 17 | Ceza Türleri | `App.Hr.DisciplinaryPenaltyType` | Wizard | [HrDisciplinaryCase.md](HrDisciplinaryCase.md) | - -Tanımlamalar dışında duran tanımlar: Eğitim tipi/konusu → [HrTrainings.md](HrTrainings.md); araç -belgesi/masrafı/gidilecek yer → [HrVehicles.md](HrVehicles.md) (her alt menüde tanım ekranları en üstte); -çalışma takvimi → [HrWorkCalendar.md](HrWorkCalendar.md). - -Sıra modül akışını izler: organizasyon → işe alım → zaman (vardiya, izin) → sağlık → performans → disiplin. -İK menüsünün kök sırası: Tanımlamalar · Organizasyon Şeması · İşe Alım · Çalışma Takvimi · İzin Yönetimi · -Puantaj ve Devam Takibi · Sağlık Kartları · Eğitim · Performans · Disiplin Dosyaları · Araçlar · Ziyaretçiler · -Olay Günlüğü · Intranet. Yetki ağacı (`AbpPermissions.Order`) aynı sırayı izler; menüsüz çalışan/yönetici -yetkileri (`MyLeaveRequest`, `MyTimesheet`, `MyPerformanceReview` …) modüllerinin hemen ardındadır. - ---- - -## 2. Analiz ve kararlar (genel tanımlar) - -> §0.13 kuralından önce üretildiler; keşif turu kaydı yoktur. Kararlar wizard ve seed dosyalarından okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Her tanım tek Wizard liste ekranı; veri seed dosyasına **aynalanır** (`SeedFilePath = data/App.Hr.{Kod}.json`, ekle/güncelle/sil senkron). Ekrandan yapılan değişiklik dosyaya yazılır, DB sıfırlanınca geri gelir | -| Aktif/Pasif | Hepsinde `IsActive` (varsayılan aktif); lookup'lar çoğunlukla yalnız aktifleri listeler | -| Kod alanı | İzin, masraf ve yan hak türlerinde iş kodu (`Code`, ör. `Annual`, `Meal`) ayrıca tutulur; yan hak kodu teklifte saklanan değerdir | -| Hazırlık tanımları | İzin türü ve masraf türü **henüz bir talep ekranına bağlı değildir** — ileride izin/masraf talep ekranlarının (onaylı talep kalıbı, `lowcode.instructions.md` §10.7) kaynağı olmak üzere tanımlanmıştır. Hastane ve hastane bölümü de şu an kullanılmıyor | - ---- - -## 3. Ekranlar - -Hepsi Grid, Card, Pivot, Chart görünümlüdür. - -| Ekran | Alanlar | Widget'lar | Seed | -| --- | --- | --- | --- | -| Kurum Doktorları | Ad soyad*, diploma no/tarihi, işyeri hekimi belge no/tarihi, T.C. kimlik no, aktif | Toplam · Aktif · Pasif | 1 | -| Yeterlilik Belgeleri | Belge adı*, aktif | Toplam · Aktif · Pasif | 16 (operatör belgeleri, kaynakçı, SRC 4, forklift, mezuniyet belgeleri, çıraklık-ustalık…) | -| Hastaneler | Kurum adı*, aktif | Toplam · Aktif · Pasif | 45 | -| Hastane Bölümleri | Bölüm adı*, aktif | Toplam · Aktif · Pasif | 31 | -| Evrak Türleri | Dosya grubu* (Genel / Özlük Evrakları / Sağlık), dosya türü*, zorunlu, aktif | Toplam · Aktif · Pasif · Zorunlu | 48 | -| İzin Türleri | Kod*, ad*, cinsiyet* (All/Male/Female), yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün kullanılabilir, bakiye aşılırsa (Engelle/Uyar), aktif | Toplam · Ücretli · Ücretsiz | 9 (Yıllık, Mazeret, Ücretsiz, Hastalık, Doğum 112 gün, Babalık 5, Evlilik 3, Ölüm 3, Süt) | -| Masraf Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, fiş/belge gerekir, aktif | Toplam · Aktif · Pasif | 7 (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) | -| Yan Hak Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, aktif | Toplam · Aktif · Pasif | 10 (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk, yakacak, diğer) | - -`*` zorunlu. Varsayılanlar: izin türünde ücretli = evet, yıllık izinden düşer/belge/yarım gün = hayır, -cinsiyet = Tümü; masraf ve yan hakta para birimi TRY, vergi/SGK = hayır, masrafta fiş gerekir = evet. - ---- - -## 4. Veri modeli - -Tablolar `sql/object/Hr_T_{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.sql` -(entity yok); kiracı + audit + `IsActive`. Kolonlar §3'teki alanlarla aynıdır. Tablo düzeyinde tekil -kısıt yoktur. - ---- - -## 5. İş kuralları - -Hesap yoktur; yalnız form varsayılanları (§3). Seed dosyası aynalandığı için tanımlar ekrandan -değiştirildiğinde `configs/seeds/data/App.Hr.*.json` dosyası da değişir — bu dosyalar commit'lenmelidir. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Her tanımın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`, -hepsi `App.Hr.Definitions` ara yetkisinin altında. Tanım ekranlarının yazma yetkisi İK'da kalmalıdır; -lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik atanmaz. - ---- - -## 7. Entegrasyonlar (kim kullanıyor) - -| Tanım | Kullanan | -| --- | --- | -| Kurum Doktorları | Sağlık Kartı (periyodik muayene, protokol, sonuç hekimleri) | -| Yeterlilik Belgeleri | Kullanıcı detayı › Eğitim ve Yetkinlik (`UserCertificate`), Performans gelişim planı (sertifika aksiyonu) | -| Evrak Türleri | Eğitim dosyaları, Disiplin belgeleri | -| Yan Hak Türleri | İşe Alım › Teklif (`BenefitCodes`, kod ile) | -| İzin Türleri | İzin Yönetimi'nin tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı); `Sick` kodlu tür Sağlık Kartı istirahatiyle eşlenir — `HrLeave.md` | -| Hastaneler, Hastane Bölümleri, Masraf Türleri | Henüz kullanan ekran yok | - ---- - -## 8. Akış örneği - -1. İK yeni bir yan hak tanımlar: kod `Gym`, ad "Spor Salonu Üyeliği", varsayılan tutar 1.500 TRY, gelir vergisine tabi. -2. Kayıt `data/App.Hr.BenefitType.json` dosyasına da yazılır. -3. İşe Alım › Teklif formundaki **Yan Haklar** listesinde yeni hak seçilebilir. - ---- - -## 9. Sık sorulanlar - -**Pasif yaptığım tanım listelerden kayboldu.** Lookup'lar yalnız aktif kayıtları listeler; eski kayıtlarda değer korunur. - -**İzin talebi nereden girilir?** Henüz izin/masraf talep ekranı yoktur; türler tanım olarak hazırdır. - -**Evrak Türleri "özlük dosyası" diyor ama özlük dosyası ekranı yok.** Doğru; türler şu an eğitim ve disiplin belgelerinde kullanılır. - ---- - -## 10. Dosyalar - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.sql` | Tablolar | -| `configs/seeds/wizard/{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.json` | 8 wizard | -| `configs/seeds/data/App.Hr.{Doctor,Certificate,Hospital,HospitalDepartment,DocumentType,LeaveType,ExpenseType,BenefitType}.json` | Aynalanan tanım verisi | - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Yeterlilik Belgeleri — `App.Hr.Certificate` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Certificate.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.Certificate` (sıra 4) | -| Yetki | `App.Hr.Certificate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yeterlilik Belgeleri — personelin sahip olabileceği mesleki yeterlilik ve mezuniyet belgeleri. | -| Geliştirme talebi | Human Resources -> Definitions | -| Kaynak | `Hr_T_Certificate` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.Certificate.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Evrak Türleri — `App.Hr.DocumentType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DocumentType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.DocumentType` (sıra 5) | -| Yetki | `App.Hr.DocumentType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Evrak Türleri — personel ve süreç belgelerinin türleri (CV, dilekçe, ibraname, sağlık raporu…), gruplarıyla. | -| Geliştirme talebi | Human Resources -> Definitions | -| Kaynak | `Hr_T_DocumentType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive`, `App.Listform.ListformField.IsRequired` | -| Veri aynası | `data/App.Hr.DocumentType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `GroupName` | Dosya Grubu | dxSelectBox | ✓ | ✓ | liste: Genel, Özlük Evrakları, Sağlık | -| `Name` | Dosya Türü | dxTextBox | ✓ | ✓ | | -| `IsRequired` | Zorunlu | dxCheckBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Masraf Türleri — `App.Hr.ExpenseType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/ExpenseType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.ExpenseType` (sıra 9) | -| Yetki | `App.Hr.ExpenseType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Masraf Türleri — personel masraf kalemleri (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) ve vergi/SGK özellikleri. | -| Kaynak | `Hr_T_ExpenseType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | CurrencyId=TRY, IsTaxable=false, IsSgkSubject=false, RequiresReceipt=true, IsActive=true | -| Veri aynası | `data/App.Hr.ExpenseType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Code` | Kod | dxTextBox | ✓ | ✓ | | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `DefaultAmount` | Varsayılan Tutar | dxNumberBox | | ✓ | | -| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | -| `IsTaxable` | Gelir Vergisine Tabi | dxCheckBox | ✓ | ✓ | | -| `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | | -| `RequiresReceipt` | Fiş / Belge Gerekir | dxCheckBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Yan Hak Türleri — `App.Hr.BenefitType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/BenefitType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.BenefitType` (sıra 10) | -| Yetki | `App.Hr.BenefitType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yan Hak Türleri — çalışanlara sağlanan yan haklar (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk ve yakacak yardımı…). | -| Kaynak | `Hr_T_BenefitType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | CurrencyId=TRY, IsTaxable=false, IsSgkSubject=false, IsActive=true | -| Veri aynası | `data/App.Hr.BenefitType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Code` | Kod | dxTextBox | ✓ | ✓ | | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `DefaultAmount` | Varsayılan Tutar | dxNumberBox | | ✓ | | -| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | -| `IsTaxable` | Gelir Vergisine Tabi | dxCheckBox | ✓ | ✓ | | -| `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### İzin Türleri — `App.Hr.LeaveType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/LeaveType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.LeaveType` (sıra 12) | -| Yetki | `App.Hr.LeaveType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İzin Türleri — izin çeşitleri ve kuralları (yıllık, mazeret, ücretsiz, hastalık, doğum, babalık, evlilik, ölüm, süt izni). | -| Kaynak | `Hr_T_LeaveType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Paid`, `App.Widget.Unpaid` | -| Form varsayılanları | IsPaid=true, DeductsFromAnnualLeave=false, RequiresDocument=false, AllowHalfDay=false, Gender=All, IsActive=true, BalanceExceedAction=Block | -| Veri aynası | `data/App.Hr.LeaveType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Code` | Kod | dxTextBox | ✓ | ✓ | | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `Gender` | Cinsiyet | dxSelectBox | ✓ | ✓ | liste: All, Male, Female | -| `MaxDaysPerYear` | Yıllık En Fazla Gün | dxNumberBox | | ✓ | | -| `IsPaid` | Ücretli | dxCheckBox | ✓ | ✓ | | -| `DeductsFromAnnualLeave` | Yıllık İzinden Düşer | dxCheckBox | ✓ | ✓ | | -| `RequiresDocument` | Belge Gerekir | dxCheckBox | ✓ | ✓ | | -| `AllowHalfDay` | Yarım Gün Kullanılabilir | dxCheckBox | ✓ | ✓ | | -| `BalanceExceedAction` | Bakiye Aşılırsa | dxRadioGroup | ✓ | ✓ | liste: Block, Warn | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Kurum Doktorları — `App.Hr.Doctor` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Doctor.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.Doctor` (sıra 13) | -| Yetki | `App.Hr.Doctor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Kurum Doktorları — işyeri hekimleri ve belge bilgileri. | -| Geliştirme talebi | Human Resources -> Definitions | -| Kaynak | `Hr_T_Doctor` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.Doctor.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `FullName` | Doktor Adı Soyadı | dxTextBox | ✓ | ✓ | | -| `DiplomaNo` | Diploma No | dxTextBox | | ✓ | | -| `DiplomaDate` | Diploma Tarihi | dxDateBox | | ✓ | | -| `OhsCertificateNo` | İşyeri Hekimi Belge No | dxTextBox | | ✓ | | -| `OhsCertificateDate` | İşyeri Hekimi Belge Tarihi | dxDateBox | | ✓ | | -| `IdentityNo` | T.C. Kimlik No | dxTextBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Hastaneler — `App.Hr.Hospital` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Hospital.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.Hospital` (sıra 14) | -| Yetki | `App.Hr.Hospital` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Hastaneler — hastane ve sağlık kurumu tanımları. | -| Geliştirme talebi | Human Resources -> Definitions | -| Kaynak | `Hr_T_Hospital` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.Hospital.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Kurum Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Hastane Bölümleri — `App.Hr.HospitalDepartment` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HospitalDepartment.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.HospitalDepartment` (sıra 15) | -| Yetki | `App.Hr.HospitalDepartment` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Hastane Bölümleri — hastane klinik/bölüm tanımları (acil, dahiliye, kardiyoloji…). | -| Geliştirme talebi | Human Resources -> Definitions | -| Kaynak | `Hr_T_HospitalDepartment` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.HospitalDepartment.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Bölüm Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrDisciplinaryCase.md b/configs/seeds/docs/modules/HrDisciplinaryCase.md deleted file mode 100644 index 58081f27..00000000 --- a/configs/seeds/docs/modules/HrDisciplinaryCase.md +++ /dev/null @@ -1,298 +0,0 @@ - -# İK › Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) - -Personel disiplin süreci: olay tutanağı (personel, tarih/saat/yer, tanıklar, tutanağı tutan) → -savunma talebi ve savunma → karar (ceza türü, yürürlük/tebliğ, ücret kesintisi) → belgeler. Tamamı -konfigürasyondur (Wizard + SQL); entity, migration ya da React kodu yoktur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK / disiplin kurulu sekreteryası | Dosya açar, tutanağı yazar, savunma ister, savunmayı ve kararı işler, belgeleri yükler, dosyayı kapatır | Disiplin Dosyaları | -| Yönetici (tutanağı tutan) | Olayı kaydeder | Disiplin Dosyaları | -| İK yöneticisi | Ceza türü tanımlarını yönetir | İK › Tanımlar › Ceza Türleri | - -Kapsam: kiracı (`IsTenant`). Satır süzmesi yoktur; disiplin kaydı hassas veridir, görünürlük yalnızca yetkiyle sınırlanır. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, -> SQL, seed, commit `130e23bc` "Disiplin Dosyaları, Çalışma Takvimi") okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Tek menü ekranı (dosya) + üç menüsüz alt form: Savunmalar, Kararlar, Belgeler | -| Menü yeri | Dosya ekranı doğrudan `İnsan Kaynakları` kökünde; ceza türü İK › Tanımlar'da | -| Dosya durumu | Open → AwaitingDefense → Decided → Closed; **elle** değiştirilir (Todo panosunda sürükleyerek ya da formdan). Savunma/karar girilmesi durumu otomatik değiştirmez | -| Savunma süresi | Son savunma tarihi = talep tarihi + **2 gün** (formda önerilir, değiştirilebilir); talep tarihinden önce olamaz | -| Ceza türü | Ağırlık (`Severity` 1–5) sırasıyla listelenir; karar ekranında yalnız aktif türler | -| Ücret kesintisi | Kararda tutar olarak saklanır; bordroya aktarım yoktur | -| Tanıklar | Çok değerli kullanıcı seçimi (`WitnessUserIds`, `dxTagBox`) | -| Dosya numarası | `DSP-YYYY-00001` (kiracı + yıl bazında, insert sonrası SQL) | -| Onay akışı, bildirim, rapor | Yok | - ---- - -## 3. Menü ve ekranlar - -| Menü (TR / EN) | `ListFormCode` | Yer | Alt formlar | Görünümler | Widget'lar | -| --- | --- | --- | --- | --- | --- | -| Disiplin Dosyaları / Disciplinary Cases | `App.Hr.DisciplinaryCase` | `İnsan Kaynakları` (sıra 10, `FcHighPriority`) | `DisciplinaryDefense`, `DisciplinaryDecision`, `DisciplinaryFile` (`Id → CaseId`) | Grid, Card, Pivot, Chart, **Todo** | Toplam · Açık · Savunma Bekleniyor · Kapanan (Karara Bağlandı + Kapandı) | -| Ceza Türleri / Penalty Types | `App.Hr.DisciplinaryPenaltyType` | `İnsan Kaynakları › Tanımlar` | — | Grid, Card, Pivot, Chart | — (tanım listesi) | - -Todo panosu: başlık `Subject`, açıklama `IncidentDescription`, tarih `IncidentDate`, sütun sırası -`Open, AwaitingDefense, Decided, Closed`. - -Seed verisi (`data/App.Hr.DisciplinaryPenaltyType.json`): Sözlü Uyarı (1), Yazılı Uyarı (2), İhtar (3), -Kınama (3), Ücret Kesintisi (4), Fesih (5). - ---- - -## 4. Veri modeli - -``` -AbpUsers ──< Hr_T_DisciplinaryCase ──< Hr_T_DisciplinaryDefense - (UserId, ReportedById, ├──< Hr_T_DisciplinaryDecision >── Hr_T_DisciplinaryPenaltyType - WitnessUserIds) └──< Hr_T_DisciplinaryFile >── Hr_T_DocumentType -``` - -| Tablo | Önemli kolonlar | -| --- | --- | -| `Hr_T_DisciplinaryPenaltyType` | `Name`, `Severity`, `Description`, `IsActive` | -| `Hr_T_DisciplinaryCase` | `CaseNo`, `UserId`, `DepartmentId`, `JobPositionId`, `IncidentDate`, `IncidentTime`, `IncidentPlace`, `ReportedById`, `Status`, `Subject`, `IncidentDescription` (HTML tutanak), `WitnessUserIds` | -| `Hr_T_DisciplinaryDefense` | `CaseId`, `RequestDate`, `DueDate`, `ResponseDate`, `Status` (Requested/Submitted/NotSubmitted), `DefenseText` (HTML) | -| `Hr_T_DisciplinaryDecision` | `CaseId`, `DecisionDate`, `PenaltyTypeId`, `EffectiveDate`, `NotificationDate`, `DeductionAmount`, `Status` (Draft/Final), `DecisionText` (HTML) | -| `Hr_T_DisciplinaryFile` | `CaseId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` | - -Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır. - ---- - -## 5. İş kuralları ve hesaplar - -| Yer | Kural | -| --- | --- | -| Dosya — yeni kayıt | Olay tarihi bugün, tutanağı tutan oturumdaki kullanıcı, durum `Open` | -| Dosya — personel seçimi | Departman ve pozisyon kullanıcı kaydından kopyalanır (olay anındaki hâli saklanır) | -| Dosya — insert sonrası | `CaseNo = 'DSP-' + yıl + '-' + 5 hane` (kiracı + yıl içinde `MAX + 1`, yalnız boşsa) | -| Savunma — yeni kayıt | Talep tarihi bugün, durum `Requested`, son tarih talep + 2 gün | -| Savunma — tarih kontrolü | Son tarih talep tarihinden önceyse uyarı + değişiklik geri alınır | -| Karar — yeni kayıt | Karar tarihi bugün, durum `Draft` | -| Belge — yeni kayıt | Tarih bugün | - -Tavsiye edilen kullanım sırası: dosya `Open` → savunma istenince `AwaitingDefense` → karar -`Final` olunca `Decided` → tebliğ ve belgeler tamamlanınca `Closed`. Bu sıra sistemce zorlanmaz. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. `App.Hr.DisciplinaryCase` kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; -`DisciplinaryDefense`, `DisciplinaryDecision`, `DisciplinaryFile` onun altındadır. Ceza türü -`App.Hr.Definitions` altındadır. Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. - -| Rol | Yetkiler | -| --- | --- | -| İK disiplin sorumlusu | Dosya + üç alt form (tam) + ceza türü | -| Tutanak tutan yönetici | `App.Hr.DisciplinaryCase` (+ `.Create`) — ancak bu yetki tüm dosyaları gösterir | - -Disiplin verisi kişisel ve hassas veridir; okuma yetkisi dar tutulmalıdır. - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `AbpUsers` | Personel, tutanağı tutan, tanıklar | -| Kullanıcı detayı › Disiplin | Disiplin Dosyaları ekranı çalışana süzülmüş açılır (`HrPersonnel.md`) | -| `Hr_T_Department`, `Hr_T_JobPosition` | Olay anındaki birim (Pivot kırılımı) | -| `Hr_T_DocumentType` | Belge türü (ortak İK tanımı) | - -Bildirim, onay akışı, rapor şablonu ya da bordro bağlantısı yoktur. - ---- - -## 8. Akış örneği - -1. Vardiya amiri **Disiplin Dosyaları**'nda yeni dosya açar: personel seçilir (departman/pozisyon - dolar), olay tarihi/saati/yeri, konu, tutanak metni ve tanıklar girilir → `DSP-2026-00001`, durum Açık. -2. İK **Savunmalar** sekmesine savunma talebi ekler; son tarih 2 gün sonrası önerilir; dosya panoda - **Savunma Bekleniyor**'a çekilir. -3. Personel savunmasını verince talep **Savunma Verildi** yapılır, metin ve tarih girilir; verilmezse **Savunma Verilmedi**. -4. Kurul kararı **Kararlar** sekmesine girilir: ceza türü Yazılı Uyarı, yürürlük ve tebliğ tarihi, durum **Kesinleşti**; dosya **Karara Bağlandı**. -5. İmzalı tutanak, savunma ve tebliğ belgesi **Belgeler** sekmesine yüklenir; dosya **Kapandı** yapılır. - ---- - -## 9. Sık sorulanlar - -**Savunma/karar girdim, dosya durumu değişmedi.** Durum elle yönetilir; panoda sürükleyin ya da formdan seçin. - -**Son savunma tarihi neden 2 gün sonrası?** Formdaki varsayılan öneridir; değiştirilebilir, yalnızca talep tarihinden önce olamaz. - -**Ücret kesintisi bordroya yansıyor mu?** Hayır; karar kaydında bilgi olarak durur. - -**Tutanak metni listede görünmüyor.** HTML alan listede gizlidir; detayda ve Todo kartında görünür. - -**Bir yöneticinin yalnız kendi tuttuğu dosyaları görmesi mümkün mü?** Şu an değil (satır süzmesi yok). Gerekirse ayrı bir persona ekranı `DefaultFilter` (`"ReportedById" = '@USERID'`) ile açılır (Performans modülündeki kalıp). - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_Disciplinary{PenaltyType,Case,Defense,Decision,File}.sql` | Tablolar | -| `configs/seeds/wizard/Disciplinary{PenaltyType,Case,Defense,Decision,File}.json` | 5 wizard | -| `configs/seeds/data/App.Hr.DisciplinaryPenaltyType.json` | Ceza türleri | -| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | - -Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar (`DisciplinaryDefense`, `DisciplinaryDecision`, -`DisciplinaryFile`) önce, sonra `DisciplinaryCase` ve `DisciplinaryPenaltyType` silinir; tablolar -yalnızca onayda seçilirse düşer. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Disiplin Dosyaları — `App.Hr.DisciplinaryCase` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DisciplinaryCase.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr` › `App.Hr.DisciplinaryCase` (sıra 10) | -| Yetki | `App.Hr.DisciplinaryCase` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Disiplin Dosyaları — bir personel hakkındaki olay tutanağı ile başlayan disiplin süreci: savunma, karar ve belgeler tek dosyada. | -| Kaynak | `Hr_T_DisciplinaryCase` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.DisciplinaryDefense` (Id → CaseId), `App.Hr.DisciplinaryDecision` (Id → CaseId), `App.Hr.DisciplinaryFile` (Id → CaseId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.DisciplinaryCase.Widget.Open`, `App.Hr.DisciplinaryCase.Widget.AwaitingDefense`, `App.Hr.DisciplinaryCase.Widget.Closed` | -| Todo | başlık `Subject`, durum `Status` (Open,AwaitingDefense,Decided,Closed) | -| Komutlar | InsertAfter: SQL | -| Form varsayılanları | IncidentDate=@DATE, ReportedById=@USERID, Status=Open | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `CaseNo` | Dosya No | dxTextBox | | | | -| `UserId` | Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `IncidentDate` | Olay Tarihi | dxDateBox | ✓ | ✓ | | -| `IncidentTime` | Olay Saati | dxDateBox | | ✓ | | -| `IncidentPlace` | Olay Yeri | dxTextBox | | ✓ | | -| `ReportedById` | Tutanağı Tutan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, AwaitingDefense, Decided, Closed | -| `Subject` | Konu | dxTextBox | ✓ | ✓ | | -| `IncidentDescription` | Olay Tutanağı | dxHtmlEditor | ✓ | ✓ | | -| `WitnessUserIds` | Tanıklar | dxTagBox | | ✓ | sorgu: AbpUsers | - -### Ceza Türleri — `App.Hr.DisciplinaryPenaltyType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DisciplinaryPenaltyType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.DisciplinaryPenaltyType` (sıra 17) | -| Yetki | `App.Hr.DisciplinaryPenaltyType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ceza Türleri — disiplin kararlarında verilebilecek cezalar ve ağırlıkları (sözlü uyarı, yazılı uyarı, ihtar, kınama, ücret kesintisi, fesih). | -| Kaynak | `Hr_T_DisciplinaryPenaltyType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | Severity=1, IsActive=true | -| Veri aynası | `data/App.Hr.DisciplinaryPenaltyType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Ad | dxTextBox | ✓ | ✓ | | -| `Severity` | Ağırlık | dxNumberBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Savunmalar — `App.Hr.DisciplinaryDefense` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DisciplinaryDefense.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DisciplinaryDefense` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Savunmalar — disiplin dosyası için personelden istenen savunma ve verilen cevap. | -| Kaynak | `Hr_T_DisciplinaryDefense` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | RequestDate=@DATE, Status=Requested | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `CaseId` | Disiplin Dosyası | dxTextBox | | | | -| `RequestDate` | Talep Tarihi | dxDateBox | ✓ | ✓ | script | -| `DueDate` | Son Savunma Tarihi | dxDateBox | ✓ | ✓ | script | -| `ResponseDate` | Savunma Tarihi | dxDateBox | | ✓ | | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Requested, Submitted, NotSubmitted | -| `DefenseText` | Savunma Metni | dxHtmlEditor | | ✓ | | - -### Kararlar — `App.Hr.DisciplinaryDecision` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DisciplinaryDecision.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DisciplinaryDecision` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Kararlar — disiplin dosyası için verilen karar ve ceza. | -| Kaynak | `Hr_T_DisciplinaryDecision` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | DecisionDate=@DATE, Status=Draft | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `CaseId` | Disiplin Dosyası | dxTextBox | | | | -| `DecisionDate` | Karar Tarihi | dxDateBox | ✓ | ✓ | | -| `PenaltyTypeId` | Ceza Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_DisciplinaryPenaltyType | -| `EffectiveDate` | Yürürlük Tarihi | dxDateBox | | ✓ | | -| `NotificationDate` | Tebliğ Tarihi | dxDateBox | | ✓ | | -| `DeductionAmount` | Kesinti Tutarı | dxNumberBox | | ✓ | | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Draft, Final | -| `DecisionText` | Karar Metni | dxHtmlEditor | | ✓ | | - -### Belgeler — `App.Hr.DisciplinaryFile` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DisciplinaryFile.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DisciplinaryFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Disiplin Belgeleri — dosyaya ait imzalı tutanak, savunma, tebliğ gibi belgeler. | -| Kaynak | `Hr_T_DisciplinaryFile` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | FileDate=@DATE | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `CaseId` | Disiplin Dosyası | dxTextBox | | | | -| `DocumentTypeId` | Dosya Türü | dxSelectBox | | ✓ | sorgu: Hr_T_DocumentType | -| `FileDate` | Tarih | dxDateBox | ✓ | ✓ | | -| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | -| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrEventLog.md b/configs/seeds/docs/modules/HrEventLog.md deleted file mode 100644 index c99dc091..00000000 --- a/configs/seeds/docs/modules/HrEventLog.md +++ /dev/null @@ -1,142 +0,0 @@ -# İK › Olay Günlüğü (`App.Hr.EventLog`) - -Vardiya amiri, güvenlik odası ve gözlem odasının tuttuğu vardiya defteri: tarih–saat, kaynak, -olayı yaşayan/kaydeden personel, vardiya, önem derecesi (1–5) ve açıklama. Tamamı konfigürasyondur -(tek Wizard ekranı). - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Vardiya amiri / güvenlik / gözlem odası | Vardiyada yaşanan önemli olayları kaydeder | Olay Günlüğü | -| Yönetim / İK | Günün olaylarını ve önemli/kritik kayıtları izler; gerekirse disiplin dosyası açar | Olay Günlüğü (widget, Pivot) | - -Kapsam: kiracı (`IsTenant`). Şube isteğe bağlıdır; satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar wizard ve SQL'den okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Tek Wizard liste ekranı | -| Kaynak | Sabit liste: Vardiya Amiri (`ShiftSupervisor`), Güvenlik Odası (`SecurityRoom`), Gözlem Odası (`ObservationRoom`) | -| Önem | 1–5 yıldız: Rutin, Düşük, Önemli, Çok Önemli, Kritik; **4 ve üstü** "önemli" kartında sayılır | -| Saat | `EventTime` `SS:dd` metin; yeni kayıtta şimdiki saat | -| Vardiya | Vardiya tanımından seçilir (`Hr_T_Shift`) | -| Disiplin bağı | Olaydan disiplin dosyasına otomatik geçiş **yoktur**; dosya elle açılır | - ---- - -## 3. Menü ve ekran - -| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | -| --- | --- | --- | --- | --- | -| Olay Günlüğü / Event Log | `App.Hr.EventLog` | `İnsan Kaynakları` (sıra 13, `FcViewDetails`) | Grid, Card, Pivot, Chart | Toplam · Bugün · Önemli (önem ≥ 4) | - ---- - -## 4. Veri modeli - -`Hr_T_EventLog` (`sql/object/Hr_T_EventLog.sql`, entity yok): - -| Kolon | Açıklama | -| --- | --- | -| `LogSource` | Kayıt kaynağı (zorunlu) | -| `BranchId` | Şube | -| `UserId` | Vardiya amiri / olayı yaşayan personel (zorunlu) | -| `EventDate`, `EventTime` | Olay tarihi ve saati (zorunlu) | -| `Importance` | 1–5 (varsayılan 1) | -| `ShiftId` | Vardiya | -| `Description` | Açıklama | - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Yeni kayıt | Olay saati boşsa şimdiki saat yazılır | -| Önem kartı | `Importance >= 4` | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`; `App.Hr.EventLog` + `.Create/.Update/.Delete/.Export/.Import/.Note`. -Kayıt tutanlara kök + `.Create` (ve gerekiyorsa `.Update`) yeter; silme yalnız yöneticide kalmalıdır. -Hiçbir yetki role otomatik atanmaz. - ---- - -## 7. Entegrasyonlar - -`Sas_T_Branch`, `AbpUsers`, `Hr_T_Shift` (bkz. `HrWorkCalendar.md`). Kritik olay için bildirim yoktur. - ---- - -## 8. Akış örneği - -1. Gece vardiyasında güvenlik odası "B kapısı alarmı" olayını kaynak Güvenlik Odası, önem 3, vardiya Gece ile kaydeder. -2. Vardiya amiri bir iş kazasını önem 5 ile girer → "Önemli" kartı artar. -3. Sabah İK önemli kayıtları süzer; gerekiyorsa Disiplin Dosyaları'nda elle dosya açar. - ---- - -## 9. Sık sorulanlar - -**Kritik olayda yöneticiye bildirim gidiyor mu?** Hayır; widget ve filtre ile izlenir. - -**Olay disiplin dosyasına bağlanabiliyor mu?** Hayır; iki kayıt arasında bağ yoktur. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_EventLog.sql` | Tablo | -| `configs/seeds/wizard/EventLog.json` | Wizard | - -Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Olay Günlüğü — `App.Hr.EventLog` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/EventLog.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr` › `App.Hr.EventLog` (sıra 13) | -| Yetki | `App.Hr.EventLog` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Olay Günlüğü — vardiya amiri, güvenlik odası ve gözlem odasının vardiya sırasında kaydettiği önemli olaylar. | -| Geliştirme talebi | Human Resources -> Olay Günlüğü | -| Kaynak | `Hr_T_EventLog` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Today`, `App.Hr.EventLog.Widget.Important` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `LogSource` | Kaynak | dxSelectBox | ✓ | ✓ | liste: ShiftSupervisor, SecurityRoom, ObservationRoom | -| `BranchId` | Şube Adı | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | -| `UserId` | Vardiya Amiri / Olayı Yaşayan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `EventDate` | Olay Tarihi | dxDateBox | ✓ | ✓ | script | -| `EventTime` | Olay Saati | dxTextBox | ✓ | ✓ | | -| `Importance` | Önem Durumu | dxSelectBox | ✓ | ✓ | liste: 1, 2, 3, 4, 5 | -| `ShiftId` | Vardiya | dxSelectBox | | ✓ | sorgu: Hr_T_Shift | -| `Description` | Açıklama | dxTextArea | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrHealthCard.md b/configs/seeds/docs/modules/HrHealthCard.md deleted file mode 100644 index c6ca6f86..00000000 --- a/configs/seeds/docs/modules/HrHealthCard.md +++ /dev/null @@ -1,430 +0,0 @@ -# İK › Sağlık Kartları (`App.Hr.HealthCard`) - -İşyeri hekimliği için çalışan sağlık kartı: soy/özgeçmiş, anamnez, laboratuvar ve fizik muayene -bulguları, çalışmaya elverişlilik sonucu (vardiya/gece çalışması dahil), periyodik muayeneler, -revir (hasta protokol defteri) başvuruları ve istirahat raporları. Kart ayrı bir tablo değildir: -tek kayıtlık bölümler doğrudan çalışanın kullanıcı satırında (`AbpUsers` genişletme kolonları), -çok kayıtlı bölümler `Adm_T_User*` tablolarındadır. Tamamı konfigürasyon + platformun kullanıcı -detay ekranıdır. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İşyeri hekimi / sağlık personeli | Kartı doldurur, periyodik muayene ve revir başvurusu girer, elverişlilik sonucunu yazar | Sağlık Kartları (detay sekmeleri) | -| İK | Kart durumunu izler, istirahat raporlarını girer; hekim, hastane ve bölüm tanımlarını yönetir | Sağlık Kartları · İK › Tanımlar | -| Sistem yöneticisi | Aynı veriyi kullanıcı detayında görür | Kimlik › Kullanıcılar › detay › Sağlık Kartı sekmesi | - -Kapsam: kiracı. Liste, kiracının **tüm kullanıcılarıdır** (aktif/pasif); satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, -> entity, `HealthCardTab.tsx`) okunmuştur. - -| Konu | Karar | -| --- | --- | -| Veri yeri | Kart başına tek değer taşıyan alanlar (kan grubu, anamnez, muayene bulguları, sonuç) **`AbpUsers` genişletme kolonlarıdır** — ayrı kart tablosu yok | -| Liste | Sağlık Kartları ekranı `AbpUsers` üzerinde salt okunur listedir (ekle/düzenle/sil kapalı); kart bilgileri detaydaki sekmelerden düzenlenir | -| Tek kayıtlık sekmeler | Soy/Özgeçmiş, Laboratuvar–Fizik Muayene, Anamnez, Sonuç: aynı kullanıcı satırını düzenleyen alt formlar (`Id → Id`, yalnız güncelleme) | -| Çok kayıtlı sekmeler | Periyodik Muayeneler, Hasta Protokol Defteri, İstirahat Raporları: `Adm_T_UserPeriodicExamination`, `Adm_T_UserPatientProtocol`, `Adm_T_UserSickLeave` (`Id → UserId`) | -| İkinci giriş | Kullanıcı detayındaki **Sağlık Kartı** sekmesi (`HealthCardTab.tsx`) aynı kolonları ve aynı üç tabloyu (`App.IdentityManagement.User{PeriodicExamination,PatientProtocol,SickLeave}` listeleriyle) düzenler | -| Hekim | Kurum doktoru tanımı (`Hr_T_Doctor`); periyodik muayenede seçilince diploma no kopyalanır | -| Koşullu alanlar | Anamnezde "evet" denmeyen sorunun not alanı, protokolde sonuç "Sevk" değilse sevk yeri kilitlidir (`readOnly` script) | - ---- - -## 3. Menü ve ekranlar - -| Menü (TR / EN) | `ListFormCode` | Yer | Kaynak | Alt formlar | -| --- | --- | --- | --- | --- | -| Sağlık Kartları / Health Cards | `App.Hr.HealthCard` | `İnsan Kaynakları` (sıra 7, `FcInspection`) | `AbpUsers` | aşağıdaki 7 sekme | - -| Sekme | `ListFormCode` (menüsüz) | Kaynak | İlişki | Düzenleme | -| --- | --- | --- | --- | --- | -| Soy / Özgeçmiş | `App.Hr.HealthCardHistory` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | -| Laboratuvar – Fizik Muayene | `App.Hr.HealthCardLabPhysical` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | -| Anamnez | `App.Hr.HealthCardAnamnesis` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | -| Sonuç | `App.Hr.HealthCardResult` | `AbpUsers` | `Id → Id` | Yalnız güncelleme | -| Periyodik Muayeneler | `App.Hr.HealthCardPeriodicExamination` | `Adm_T_UserPeriodicExamination` | `Id → UserId` | Ekle/düzenle/sil | -| Hasta Protokol Defteri | `App.Hr.HealthCardPatientProtocol` | `Adm_T_UserPatientProtocol` | `Id → UserId` | Ekle/düzenle/sil | -| İstirahat Raporları | `App.Hr.HealthCardSickLeave` | `Adm_T_UserSickLeave` | `Id → UserId` | Ekle/düzenle/sil; kayıt sonrası İzin Yönetimi'ne eşlenir (`HrLeave.md` §5.5) | - -Widget'lar (liste): Toplam · Aktif · Pasif kullanıcı. - -Tanımlar (`İnsan Kaynakları › Tanımlamalar`): - -| Menü | `ListFormCode` | Seed | -| --- | --- | --- | -| Kurum Doktorları | `App.Hr.Doctor` | 1 kayıt (diploma, işyeri hekimi belge no/tarihi, T.C. kimlik) | -| Hastaneler | `App.Hr.Hospital` | 45 kurum (devlet/özel hastaneler, sağlık ocağı, işyeri hekimliği…) | -| Hastane Bölümleri | `App.Hr.HospitalDepartment` | 31 bölüm | - ---- - -## 4. Veri modeli - -| Yer | Alanlar | -| --- | --- | -| `AbpUsers` — kimlik (liste) | `Name`, `Surname`, `IdentityNumber`, `BirthDate`, `Gender`, `BloodType`, `Email`, `PhoneNumber`, `DepartmentId`, `JobPositionId`, `HireDate`, `SskNo`, `IsActive` | -| `AbpUsers` — soy/özgeçmiş | Anne/baba/kardeş/çocuk sağlık durumu (Alive/Disease/Deceased) + not, `BloodType` (8 grup), `ChronicDisease`, tetanoz/hepatit/diğer aşı | -| `AbpUsers` — anamnez | Şikâyetler (`Complaint*`: göğüs ağrısı, balgamlı öksürük, nefes darlığı, çarpıntı, eklem/bel ağrısı, ishal/kabızlık), tanılar (`Diagnosis*`: diyabet, kalp, böbrek, sarılık, ülser, işitme, görme, sinir sistemi, deri, besin zehirlenmesi), evet/hayır + not soruları (hastanede yatış, ameliyat, iş kazası, meslek hastalığı muayenesi, malulen emeklilik, süren tedavi), sigara/alkol (None/Occasionally/Normal/Quit + not) | -| `AbpUsers` — lab/fizik | `Lab*` (biyolojik, kan, idrar, radyolojik, odyometri, SFT, psikolojik, diğer), `Exam*` (duyu, göz, KBB, deri, kalp-damar, solunum, sindirim, ürogenital, kas-iskelet, nörolojik, psikiyatrik, diğer, tansiyon, nabız, boy, kilo) | -| `AbpUsers` — sonuç | `FitForWorkJob`, `FitForWorkCondition`, `FitnessDoctorId`, `ShiftWorkFit`, `NightWorkFit`, `ShiftNightDoctorId` | -| `Adm_T_UserPeriodicExamination` | `UserId`, `ExamDate`, `Examination`, `Result`, `DoctorId`, `DoctorDiplomaNo` | -| `Adm_T_UserPatientProtocol` | `UserId`, `SequenceNo`, `ProtocolDate`, `ProtocolType` (Disease/WorkAccident/OccupationalDisease/Control/Other), `ProtocolResult` (TreatmentDischarged/Rest/Referral), `RestDays`, `ReferralPlace`, `DoctorId` | -| `Adm_T_UserSickLeave` | `UserId`, `StartDate`, `EndDate`, `Days`, `SickLeaveType` (Disease/WorkAccident/OccupationalDisease/Maternity), `Institution`, `Clinic`, `SickLeaveReason` | -| `Hr_T_Doctor` / `Hr_T_Hospital` / `Hr_T_HospitalDepartment` | Tanımlar | - -Entity'ler: `Entities/Tenant/Administration/User{PeriodicExamination,PatientProtocol,SickLeave}.cs`; -genişletme kolonları `AbpIdentityUserExtensions` ve EF genişletme eşlemeleri. - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Anamnez | Evet/hayır sorusu işaretli değilse not alanı salt okunur; sigara/alkol "Kullanmıyor" ise not kilitli | -| Periyodik muayene | Yeni satırda tarih bugün; hekim seçilince diploma no kopyalanır | -| Protokol | Yeni satırda tarih bugün; sonuç "Sevk" değilse sevk yeri kilitli | -| İstirahat | `Days = days(Başlangıç, Bitiş)` (bitiş dahil); bitiş başlangıçtan önceyse uyarı | -| Liste | Kayıt eklenemez/silinemez — kartın sahibi kullanıcı kaydıdır | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. `App.Hr.HealthCard` kökü; yedi sekme onun altındadır. Tanımlar -`App.Hr.Definitions` altındadır. Kullanıcı detayındaki sekme, kullanıcı ekranının yetkileriyle -(`AbpIdentity.Users` / `.Update`) çalışır. Hiçbir yetki role otomatik atanmaz. - -Sağlık verisi **özel nitelikli kişisel veridir** (KVKK md. 6): Sağlık Kartları ve alt sekmelerinin -yetkisi yalnız işyeri hekimi ve yetkili sağlık personeline verilmelidir. Kullanıcı detayına erişen -yöneticiler de bu sekmeyi görebileceği için kullanıcı yönetimi yetkisi de buna göre sınırlanmalıdır. - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `AbpUsers` (+ `Hr_T_Department`, `Hr_T_JobPosition`) | Kartın sahibi ve kimlik bilgisi | -| Kullanıcı detayı (`views/admin/user-management/HealthCardTab.tsx`) | Aynı verinin ikinci düzenleme yeri | -| `Hr_T_Doctor` | Periyodik muayene, protokol, sonuç hekimleri | - -Hastane ve hastane bölümü tanımları **henüz hiçbir sekmeye bağlı değildir** (istirahatte kurum/klinik -serbest metindir). Bildirim, periyodik muayene hatırlatması ya da rapor şablonu yoktur. - ---- - -## 8. Akış örneği - -1. İşe giren çalışanın kartı listede hazırdır (kullanıcı açıldığı anda). Hekim **Soy/Özgeçmiş** ve - **Anamnez** sekmelerini doldurur. -2. İşe giriş muayenesi bulguları **Laboratuvar – Fizik Muayene**'ye, kararı **Sonuç**'a yazılır - (vardiyalı/gece çalışabilir + hekimler). -3. Yıllık kontrol **Periyodik Muayeneler**'e eklenir. -4. Çalışan revire gelince **Hasta Protokol Defteri**'ne kayıt açılır (tür Hastalık, sonuç İstirahat, 1 gün). -5. Dışarıdan alınan rapor **İstirahat Raporları**'na girilir; gün sayısı hesaplanır. - ---- - -## 9. Sık sorulanlar - -**Listeye neden kayıt eklenemiyor?** Kart kullanıcı kaydıdır; yeni çalışan Kimlik › Kullanıcılar'dan açılır. - -**Sağlık kartı verisi nerede tutuluyor?** Tek değerli alanlar `AbpUsers` kolonlarında, muayene/protokol/istirahat ayrı tablolarda (§4). - -**Kullanıcı detayındaki Sağlık Kartı sekmesiyle bu ekran aynı mı?** Evet; aynı veriyi iki yerden düzenlerler. - -**Hastane tanımı nerede kullanılıyor?** Şu an hiçbir yerde; ileride istirahat/sevk alanlarına lookup olarak bağlanmak üzere duruyor. - -**İstirahat raporu izinlere yansıyor mu?** Evet, tek kayıttır: buradan (ya da kullanıcı detayındaki İstirahatler'den) girilen rapor İK › İzin Yönetimi'nde onaylı Rapor (`Sick`) talebi olur; çalışanın Intranet'ten açtığı Rapor talebi de bu sekmeye düşer (`Hr_S_LeaveSickLeaveSync`, ayrıntı `HrLeave.md` §5.5). Rapor yıllık izin bakiyesinden düşmez; yıllık izindeyken alınan raporun günleri izinden sayılmaz, bakiyeye döner. Çalışanın rapor talebi sağlık kartına onaylanınca düşer. Raporun günleri (hafta sonu dahil) puantajda Raporlu olur, devamsız yazılmaz (`Hr_S_LeaveSickLeaveSync` sonunda yeniden hesap, `HrAttendance.md` §7.1). Kapalı puantaj ayına düşen rapor kaydedilemez/silinemez; önce İK dönemi açar. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/wizard/HealthCard{,History,LabPhysical,Anamnesis,Result,PeriodicExamination,PatientProtocol,SickLeave}.json` | 8 wizard | -| `configs/seeds/wizard/{Doctor,Hospital,HospitalDepartment}.json`, `data/App.Hr.{Doctor,Hospital,HospitalDepartment}.json` | Tanım ekranları ve verisi | -| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/User{PeriodicExamination,PatientProtocol,SickLeave}.cs` | Çok kayıtlı sekmelerin entity'leri (migration'lı) | -| `ui/src/views/admin/user-management/HealthCardTab.tsx` | Kullanıcı detayındaki sekme | - -Kart sekmelerini kaldırmak wizard'ları siler; `AbpUsers` kolonları ve `Adm_T_User*` tabloları -entity/migration'a bağlı olduğu için kalır. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Sağlık Kartları — `App.Hr.HealthCard` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCard.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr` › `App.Hr.HealthCard` (sıra 7) | -| Yetki | `App.Hr.HealthCard` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Sağlık Kartları — işyeri hekimliği için her çalışanın sağlık kartı. Liste kiracının bütün kullanıcılarıdır; kart bilgileri detay sekmelerinden girilir. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.HealthCardHistory` (Id → Id), `App.Hr.HealthCardLabPhysical` (Id → Id), `App.Hr.HealthCardAnamnesis` (Id → Id), `App.Hr.HealthCardResult` (Id → Id), `App.Hr.HealthCardPeriodicExamination` (Id → UserId), `App.Hr.HealthCardPatientProtocol` (Id → UserId), `App.Hr.HealthCardSickLeave` (Id → UserId) | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Ad | dxTextBox | | ✓ | | -| `Surname` | Soyad | dxTextBox | | ✓ | | -| `IdentityNumber` | T.C. Kimlik No | dxTextBox | | ✓ | | -| `BirthDate` | Doğum Tarihi | dxDateBox | | ✓ | | -| `Gender` | Cinsiyet | dxSelectBox | | ✓ | liste: Male, Female | -| `BloodType` | Kan Grubu | dxTextBox | | ✓ | | -| `Email` | E-posta | dxTextBox | | ✓ | | -| `PhoneNumber` | Telefon | dxTextBox | | ✓ | | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `HireDate` | İşe Giriş Tarihi | dxDateBox | | ✓ | | -| `SskNo` | SSK No | dxTextBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Soy / Özgeçmiş — `App.Hr.HealthCardHistory` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardHistory.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardHistory` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Soy / Özgeçmiş — çalışanın aile sağlık geçmişi, kan grubu, kronik hastalıkları ve aşıları. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `MotherHealthStatus` | Anne | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | -| `MotherHealthNote` | Anne Notu | dxTextBox | | ✓ | | -| `FatherHealthStatus` | Baba | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | -| `FatherHealthNote` | Baba Notu | dxTextBox | | ✓ | | -| `SiblingHealthStatus` | Kardeş | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | -| `SiblingHealthNote` | Kardeş Notu | dxTextBox | | ✓ | | -| `ChildHealthStatus` | Çocuk | dxSelectBox | | ✓ | liste: Alive, Disease, Deceased | -| `ChildHealthNote` | Çocuk Notu | dxTextBox | | ✓ | | -| `BloodType` | Kan Grubu | dxSelectBox | | ✓ | liste: 0 Rh+, 0 Rh-, A Rh+, A Rh-, B Rh+, B Rh-, AB Rh+, AB Rh- | -| `ChronicDisease` | Doğuştan / Kronik Hastalık | dxTextBox | | ✓ | | -| `TetanusVaccination` | Tetanoz | dxTextBox | | ✓ | | -| `HepatitisVaccination` | Hepatit | dxTextBox | | ✓ | | -| `OtherVaccination` | Diğer | dxTextBox | | ✓ | | - -### Laboratuvar - Fizik Muayene — `App.Hr.HealthCardLabPhysical` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardLabPhysical.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardLabPhysical` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Laboratuvar – Fizik Muayene — işe giriş ya da periyodik muayenedeki tahlil ve fizik muayene bulguları. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `LabBiologicalAnalysis` | Biyolojik Analizler | dxTextBox | | ✓ | | -| `LabBlood` | Kan | dxTextBox | | ✓ | | -| `LabUrine` | İdrar | dxTextBox | | ✓ | | -| `LabRadiological` | Radyolojik Analizler | dxTextBox | | ✓ | | -| `LabRadiologicalPhysiological` | Radyolojik Fizyolojik | dxTextBox | | ✓ | | -| `LabAudiometry` | Odyometri | dxTextBox | | ✓ | | -| `LabPulmonaryFunction` | Solunum Fonksiyon Testi | dxTextBox | | ✓ | | -| `LabPsychologicalTests` | Psikolojik Testler | dxTextBox | | ✓ | | -| `LabOther` | Diğer Laboratuvar Bulguları | dxTextBox | | ✓ | | -| `ExamSensoryOrgans` | Duyu Organları | dxTextBox | | ✓ | | -| `ExamEye` | Göz | dxTextBox | | ✓ | | -| `ExamEnt` | Kulak-Burun-Boğaz | dxTextBox | | ✓ | | -| `ExamSkin` | Deri | dxTextBox | | ✓ | | -| `ExamCardiovascular` | Kalp-Damar Sistemi Muayenesi | dxTextBox | | ✓ | | -| `ExamRespiratory` | Solunum Sistemi Muayenesi | dxTextBox | | ✓ | | -| `ExamDigestive` | Sindirim Sistemi Muayenesi | dxTextBox | | ✓ | | -| `ExamUrogenital` | Ürogenital Sistem Muayenesi | dxTextBox | | ✓ | | -| `ExamMusculoskeletal` | Kas-İskelet Sistemi Muayenesi | dxTextBox | | ✓ | | -| `ExamNeurological` | Nörolojik Muayene | dxTextBox | | ✓ | | -| `ExamPsychiatric` | Psikiyatrik Muayene | dxTextBox | | ✓ | | -| `ExamOther` | Diğer Muayene Bulguları | dxTextBox | | ✓ | | -| `ExamBloodPressure` | Tansiyon | dxTextBox | | ✓ | | -| `ExamPulse` | Nabız / dk | dxTextBox | | ✓ | | -| `ExamHeight` | Boy (cm) | dxNumberBox | | ✓ | | -| `ExamWeight` | Kilo (kg) | dxNumberBox | | ✓ | | - -### Anamnez — `App.Hr.HealthCardAnamnesis` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardAnamnesis.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardAnamnesis` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Anamnez — çalışanın sağlık geçmişine dair soru formu. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ComplaintChestPain` | Göğüs Ağrısı | dxCheckBox | | ✓ | | -| `ComplaintProductiveCough` | Balgamlı Öksürük | dxCheckBox | | ✓ | | -| `ComplaintDyspnea` | Nefes Darlığı | dxCheckBox | | ✓ | | -| `ComplaintPalpitation` | Çarpıntı | dxCheckBox | | ✓ | | -| `ComplaintJointPain` | Eklem Ağrısı | dxCheckBox | | ✓ | | -| `ComplaintBackPain` | Bel Ağrısı | dxCheckBox | | ✓ | | -| `ComplaintDiarrheaConstipation` | İshal veya Kabızlık | dxCheckBox | | ✓ | | -| `DiagnosisDiabetes` | Şeker Hastalığı | dxCheckBox | | ✓ | | -| `DiagnosisHeartDisease` | Kalp Hastalığı | dxCheckBox | | ✓ | | -| `DiagnosisKidneyDisease` | Böbrek Hastalığı | dxCheckBox | | ✓ | | -| `DiagnosisJaundice` | Sarılık | dxCheckBox | | ✓ | | -| `DiagnosisPepticUlcer` | Mide / Oniki Parmak Ülseri | dxCheckBox | | ✓ | | -| `DiagnosisHearingLoss` | İşitme Kaybı | dxCheckBox | | ✓ | | -| `DiagnosisVisionImpairment` | Görme Bozukluğu | dxCheckBox | | ✓ | | -| `DiagnosisNervousSystemDisease` | Sinir Sistemi Hastalığı | dxCheckBox | | ✓ | | -| `DiagnosisSkinDisease` | Deri Hastalığı | dxCheckBox | | ✓ | | -| `DiagnosisFoodPoisoning` | Besin Zehirlenmesi | dxCheckBox | | ✓ | | -| `Hospitalized` | 3. Hastanede yattınız mı? | dxCheckBox | | ✓ | script | -| `HospitalizedNote` | Hastanede Yatış Notu | dxTextBox | | ✓ | | -| `HadSurgery` | 4. Ameliyat oldunuz mu? | dxCheckBox | | ✓ | script | -| `HadSurgeryNote` | Ameliyat Notu | dxTextBox | | ✓ | | -| `HadWorkAccident` | 5. İş kazası geçirdiniz mi? | dxCheckBox | | ✓ | script | -| `HadWorkAccidentNote` | İş Kazası Notu | dxTextBox | | ✓ | | -| `OccupationalDiseaseExam` | 6. Meslek hastalığı şüphesiyle tetkik veya muayene oldunuz mu? | dxCheckBox | | ✓ | script | -| `OccupationalDiseaseExamNote` | Meslek Hastalığı Muayene Notu | dxTextBox | | ✓ | | -| `DisabilityPension` | 7. Malulen emeklilik aldınız mı? | dxCheckBox | | ✓ | script | -| `DisabilityPensionNote` | Malulen Emeklilik Notu | dxTextBox | | ✓ | | -| `UnderTreatment` | 8. Şu anda bir tedavi görüyor musunuz? | dxCheckBox | | ✓ | script | -| `UnderTreatmentNote` | Tedavi Notu | dxTextBox | | ✓ | | -| `Smoking` | 9. Sigara kullanıyor musunuz? | dxSelectBox | | ✓ | liste: None, Occasionally, Normal, Quit · script | -| `SmokingNote` | Sigara Notu | dxTextBox | | ✓ | | -| `Alcohol` | 10. Alkol kullanıyor musunuz? | dxSelectBox | | ✓ | liste: None, Occasionally, Normal, Quit · script | -| `AlcoholNote` | Alkol Notu | dxTextBox | | ✓ | | - -### Sonuç — `App.Hr.HealthCardResult` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardResult.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardResult` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Sonuç — işyeri hekiminin çalışmaya elverişlilik kararı. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `AbpUsers` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `FitForWorkJob` | Çalışmaya Elverişli - İş | dxTextBox | | ✓ | | -| `FitForWorkCondition` | Çalışmaya Elverişli - Koşul | dxTextBox | | ✓ | | -| `FitnessDoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | -| `ShiftWorkFit` | Vardiyalı Çalışabilir | dxCheckBox | | ✓ | | -| `NightWorkFit` | Gece Çalışabilir | dxCheckBox | | ✓ | | -| `ShiftNightDoctorId` | Vardiya / Gece Çalışması Doktoru | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | - -### Periyodik Muayeneler — `App.Hr.HealthCardPeriodicExamination` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardPeriodicExamination.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardPeriodicExamination` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Periyodik Muayeneler — çalışanın yasal periyodik sağlık muayeneleri. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `Adm_T_UserPeriodicExamination` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | -| `ExamDate` | Tarih | dxDateBox | ✓ | ✓ | script | -| `Examination` | Muayene | dxTextBox | ✓ | ✓ | | -| `Result` | Sonuç | dxTextBox | | ✓ | | -| `DoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor · script | -| `DoctorDiplomaNo` | Diploma No | dxTextBox | | ✓ | | - -### Hasta Protokol Defteri — `App.Hr.HealthCardPatientProtocol` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardPatientProtocol.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardPatientProtocol` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Hasta Protokol Defteri — çalışanın revir başvuruları. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `Adm_T_UserPatientProtocol` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | -| `SequenceNo` | Sıra No | dxNumberBox | | ✓ | | -| `ProtocolDate` | Tarih | dxDateBox | ✓ | ✓ | script | -| `ProtocolType` | Protokol Türü | dxSelectBox | ✓ | ✓ | liste: Disease, WorkAccident, OccupationalDisease, Control, Other | -| `ProtocolResult` | Sonuç | dxSelectBox | | ✓ | liste: TreatmentDischarged, Rest, Referral · script | -| `RestDays` | İstirahat Günü | dxNumberBox | | ✓ | | -| `ReferralPlace` | Sevk Yeri | dxTextBox | | ✓ | | -| `DoctorId` | Doktor | dxSelectBox | | ✓ | sorgu: Hr_T_Doctor | - -### İstirahat Raporları — `App.Hr.HealthCardSickLeave` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/HealthCardSickLeave.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.HealthCardSickLeave` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İstirahat Raporları — çalışanın aldığı istirahat (rapor) kayıtları. | -| Geliştirme talebi | Human Resources -> Health Card | -| Kaynak | `Adm_T_UserSickLeave` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_LeaveSickLeaveSync` · UpdateAfter: `Hr_S_LeaveSickLeaveSync` · DeleteAfter: `Hr_S_LeaveSickLeaveSync` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `UserId` | Kullanıcı | dxSelectBox | | | sorgu: AbpUsers | -| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | -| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | -| `Days` | Gün | dxNumberBox | ✓ | ✓ | | -| `SickLeaveType` | İstirahat Türü | dxSelectBox | ✓ | ✓ | liste: Disease, WorkAccident, OccupationalDisease, Maternity | -| `Institution` | Kurum | dxTextBox | | ✓ | | -| `Clinic` | Klinik | dxTextBox | | ✓ | | -| `SickLeaveReason` | İstirahat Nedeni | dxTextBox | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrIntranet.md b/configs/seeds/docs/modules/HrIntranet.md deleted file mode 100644 index c2ecfc54..00000000 --- a/configs/seeds/docs/modules/HrIntranet.md +++ /dev/null @@ -1,219 +0,0 @@ -# İK › Intranet (`App.Hr.Intranet`) - -Kurum içi iletişim: ana sayfa panosu (bugün doğanlar, dokümanlar, aktif anketler, sosyal duvar, -duyurular, yaklaşan etkinlikler), bunların yönetim ekranları (duyuru, anket, sosyal paylaşım, -etkinlik), doküman kütüphanesi ve kullanıcılar arası mesajlaşma. Bu modül **entity + C# seeder + -özel React sayfalarıyla** kuruludur (wizard değil); pano kutuları Developer Kit › Intranet Widgets -kaydıyla yönetilir. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Tüm çalışanlar | Panoyu görür; duyuru okur/beğenir/yorumlar, anket doldurur, paylaşım yapar, beğenir, yorumlar, ankete oy verir, etkinliği beğenir/yorumlar, doküman indirir, mesajlaşır | `/admin/dashboard` · mesajlaşma penceresi | -| İK / iç iletişim | Duyuru, anket (soru/seçenek), etkinlik ve tanımlarını yönetir; yanıtları ve etkileşimleri izler | İK › Intranet › Duyurular · Anketler · Sosyal Paylaşımlar · Etkinlik Türleri/Kategorileri · Etkinlikler | -| İK / doküman sorumlusu | Doküman yükler, yayına alır/kaldırır | İK › Intranet › Dokümanlar (`/admin/intranet-documents`) | -| Sistem yöneticisi | Pano kutularını (hazır ya da custom component) tanımlar, sırasını ve yetkisini belirler | Developer Kit › Intranet Widgets | - -Kapsam: kiracı. Bütün tablolar `IMultiTenant`; satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan -> (`ListFormSeeder_Hr.cs`, `Entities/Tenant/Hr/Intranet`, `IntranetAppService`, `views/intranet`) okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Yönetim ekranları entity + seeder ListForm'u; pano ve etkileşimler özel React + `IntranetAppService` | -| Modül yeri | Intranet İK'dadır: menü `App.Hr.Intranet`, yetkiler `App.Hr.Intranet.*`, tablolar `Hr_T_*`; pano kutusu kaydı (`Sas_T_IntranetWidget`) Saas › Developer Kit'te kalır | -| Pano kutuları | Veritabanı kaydıdır (kod, kolon, sıra, yetki, aktiflik). **Builtin** kutu koda kayıtlı React bileşenidir (`id` = kayıt `Code`); **Custom** kutu Developer Kit custom component'idir (Props JSON ile) | -| Kullanıcı yerleşimi | Pano tasarım modunda sürükle-bırak, gizle/göster, kolon oranı hazır ayarları; tercih **tarayıcıda (localStorage)** saklanır, sunucuya yazılmaz | -| Doğum günleri | Her pano isteğinde kullanıcıların `BirthDate` genişletme alanından canlı hesaplanır (gün + ay) | -| Duyuru panoda | Kutu yalnız **sabitlenmiş** (`IsPinned`) duyuruları, en fazla 3 tane gösterir | -| Anket | `Status = active` anketler; kullanıcı yanıtını sonradan **güncelleyebilir**; anonim ankette yanıt `UserId` taşımaz | -| Sosyal medya | Bir paylaşımda tek medya kaydı (resim(ler), video ya da anket); yüklenen dosya **base64 data URL** olarak `SocialMedia.Urls`'e yazılır | -| Doküman yayını | Fiziksel CDN klasörleri: `intranet` (yayında) ve `intranet/_passive` (yayında değil); yayına alma = klasörler arası taşıma | -| Mesajlaşma | Yalnız tablo öneki ile İK'dadır (`Hr_T_Messenger*`); menüsü/yetkisi yoktur, kabuk düzenine gömülü pencere + SignalR | -| Bildirim / zamanlanmış iş | Yok | - ---- - -## 3. Menü ve ekranlar - -`İnsan Kaynakları › Intranet` (`App.Hr.Intranet`, sıra 14) - -| Sıra | Menü | `ListFormCode` / rota | Alt formlar | Widget'lar | -| --- | --- | --- | --- | --- | -| 1 | Etkinlik Türleri | `App.Hr.Intranet.Events.EventType` | — | — | -| 2 | Etkinlik Kategorisi | `App.Hr.Intranet.Events.EventCategory` | — | — | -| 3 | Duyurular | `App.Hr.Intranet.Announcement` | `…Announcement.AnnouncementLike`, `…Announcement.AnnouncementComment` (`Id → AnnouncementId`) | Aktif · Sabitlenmiş · Süresi dolan · Toplam görüntülenme | -| 4 | Anketler | `App.Hr.Intranet.Survey` | `SurveyQuestion` (→ `SurveyQuestionOption`), `SurveyResponse` (→ `SurveyAnswer`) — iki seviyeli | Aktif · Pasif · Toplam yanıt | -| 5 | Sosyal Paylaşımlar | `App.Hr.Intranet.SocialPost` | `SocialComment`, `SocialMedia` (→ `SocialPollOption`), `SocialLike` (`Id → SocialPostId`) | Toplam · Bugün · Toplam beğeni | -| 6 | Etkinlikler | `App.Hr.Intranet.Events.Event` | `EventLike`, `EventComment` (`Id → EventId`) | Yaklaşan · Yayında · Taslak · İptal | -| 7 | Dokümanlar | `/admin/intranet-documents` (özel sayfa) | — | — | - -Diğer giriş noktaları: - -| Ne | Nerede | -| --- | --- | -| Pano | `/admin/dashboard` (`views/Dashboard.tsx` → `views/intranet/Dashboard.tsx`); rota yetkisizdir, menüde ayrı kaydı yoktur | -| Pano kutusu tanımı | Developer Kit › Intranet Widgets (`App.DeveloperKit.IntranetWidgets`, `Sas_T_IntranetWidget`); veri `data/App.DeveloperKit.IntranetWidgets.json`'a aynalanır | -| Mesajlaşma | Uygulama kabuğundaki `MessengerWidget` | - -Pano kutuları (seed): - -| Kod | Kolon / sıra | Yetki | Ne gösterir | -| --- | --- | --- | --- | -| `today-birthdays` | Sol / 10 | `AbpIdentity.Users.Widget` | Bugün doğanlar: avatar, ad, yaş, departman | -| `documents` | Sol / 20 | `App.Files.Widget` | Yayındaki ilk 3 doküman (tür, boyut, tarih, indir) | -| `active-surveys` | Sol / 30 | `App.Hr.Intranet.Survey.Widget` | Aktif anketler (kalan gün, soru/yanıt sayısı, doldurdum/doldur) | -| `my-leave` | Sol / 35 | `App.Hr.MyLeaveRequest` | Custom `MyLeaveWidget`: izin bakiyesi, süren talepler → İzin Talebi Oluştur · Taleplerim · Bakiyem | -| `team-leave` | Sol / 36 | `App.Hr.TeamLeaveRequest` | Custom `TeamLeaveWidget`: müdürün onayını bekleyen izin talepleri, bugün izinde olanlar → Onay Bekleyenler | -| `my-timesheet` | Sol / 37 | `App.Hr.MyTimesheet` | Custom `MyTimesheetWidget`: seçilen ayın puantajı (net saat, geç/erken dk, fazla mesai, devamsız/izinli/raporlu) ve yıl toplamı, 270 saatlik fazla mesai çubuğu → Puantajım | -| `social-wall` | Orta / 40 | `App.Hr.Intranet.SocialPost.Widget` | Sosyal duvar (Tümü / Paylaşımlarım, sonsuz kaydırma 10'arlı) | -| `announcements` | Sağ / 50 | `App.Hr.Intranet.Announcement.Widget` | Sabitlenmiş duyurular (en fazla 3) | -| `upcoming-events` | Sağ / 60 | `App.Hr.Intranet.Events.Event.Widget` | Bugünden sonraki yayınlanmış ilk 3 etkinlik | -| `my-performance` | Sağ / 70 | `App.Hr.MyPerformanceReview` | Custom `MyPerformanceWidget`: aktif performans değerlendirmesi, puanlar, gelişim aksiyonları → Değerlendirmelerim | -| `team-performance` | Sağ / 80 | `App.Hr.TeamPerformanceReview` | Custom `TeamPerformanceWidget`: yöneticinin ekip değerlendirmeleri → Ekibimin Değerlendirmeleri | -| `my-360-feedback` | Sağ / 90 | `App.Hr.My360Feedback` | Custom `My360FeedbackWidget`: kullanıcıya atanan 360 talepleri → 360 Taleplerim | - -İlk altı kutu Builtin'dir (koddaki `Code`). `my-leave` / `team-leave` İzin Yönetimi'nin (`HrLeave.md` §3.3), `my-timesheet` Puantaj ve Devam Takibi'nin (`HrAttendance.md` §3.3), son üçü Performans Yönetimi'nin çalışana ait özetleridir: -İK menüsü İK departmanınındır, çalışan kendi değerlendirmesini buradan takip eder; listeler menüsüzdür ve -kutudaki bağlantıyla açılır. Ayrıntı: `HrPerformance.md` §3.3. - ---- - -## 4. Veri modeli - -Entity'ler `Entities/Tenant/Hr/Intranet` (`FullAuditedEntity, IMultiTenant`); tablolar migration'lıdır. - -| Tablo | Önemli kolonlar | Kural | -| --- | --- | --- | -| `Hr_T_Announcement` | `Title`, `Excerpt`, `Content` (HTML), `ImageUrl`, `Category` (general/event/urgent/announcement), `UserId`, `PublishDate`, `ExpiryDate`, `IsPinned`, `ViewCount`, `Likes`, `Attachments` | Başlık kiracıda tekil | -| `Hr_T_AnnouncementComment` / `Hr_T_AnnouncementLike` | `AnnouncementId`, `UserId`, (`Content`) | Beğeni kullanıcı başına tekil | -| `Hr_T_Survey` | `Title`, `Description`, `Deadline`, `Responses`, `Status`, `IsAnonymous` | Başlık kiracıda tekil | -| `Hr_T_SurveyQuestion` | `SurveyId`, `QuestionText`, `Type` (rating/multiple-choice/text/textarea/yes-no), `Order`, `IsRequired` | — | -| `Hr_T_SurveyQuestionOption` | `QuestionId`, `Text`, `Order` | — | -| `Hr_T_SurveyResponse` / `Hr_T_SurveyAnswer` | `SurveyId`, `UserId`, `SubmissionTime` / `ResponseId`, `QuestionId`, `QuestionType`, `Value` | — | -| `Hr_T_SocialPost` | `UserId`, `Content`, `LikeCount`, `IsLiked`, `IsOwnPost` | — | -| `Hr_T_SocialMedia` | `SocialPostId` (1:1), `Type` (image/video/poll), `Urls`, `PollQuestion`, `PollTotalVotes`, `PollEndsAt`, `PollUserVoteId` | — | -| `Hr_T_SocialPollOption` | `SocialMediaId`, `Text`, `Votes` | — | -| `Hr_T_SocialComment` / `Hr_T_SocialLike` | `SocialPostId`, `UserId`, (`Content`) | Beğeni kullanıcı başına tekil | -| `Hr_T_SocialLocation` | Konum bilgisi | Kullanan ekran/servis yok | -| `Hr_T_EventType` / `Hr_T_EventCategory` | `Name` | Kiracıda tekil | -| `Hr_T_Event` | `CategoryId`, `TypeId`, `Date`, `Name`, `Description`, `Place`, `Status` (published/draft/cancelled), `UserId`, `ParticipantsCount`, `Likes`, `isPublished`, `Photos` | `(CategoryId, TypeId, Name)` tekil | -| `Hr_T_EventComment` / `Hr_T_EventLike` | `EventId`, `UserId`, (`Content`) | Beğeni tekil | -| `Sas_T_IntranetWidget` | `Code`, `Name`, `LabelKey`, `SourceType` (0 Builtin / 1 Custom), `ComponentName`, `PermissionName`, `Column` (0 sol / 1 orta / 2 sağ), `Order`, `Props`, `IsActive` | Kod kiracıda tekil | -| `Hr_T_MessengerConversation` / `Hr_T_MessengerConversationMessage` | Konuşma (katılımcılar, son mesaj) / mesaj (gönderen, alıcılar, metin, ekler, zaman) | — | - ---- - -## 5. İş kuralları (`IntranetAppService`) - -| İşlem | Kural | -| --- | --- | -| Pano verisi | Doğum günleri (bugün), `intranet` klasöründeki dosyalar (`_passive` hariç), son 50 duyuru, `active` anketler + kullanıcının yanıtı, `isPublished` son 50 etkinlik, aktif ve yetkisi verilmiş pano kutuları. Duyuru için tarih/sabitleme süzmesi, anket için son tarih süzmesi **sunucuda yoktur** | -| Duyuru aç | Her açılışta `ViewCount + 1` | -| Beğeni (duyuru, paylaşım, etkinlik) | Aç/kapa: beğeni satırı eklenir/silinir, sayaç ±1 | -| Yorum | Satır eklenir; listelenirken yazar bilgisi doldurulur | -| Anket yanıtı | Kullanıcının önceki yanıtı varsa cevaplar güncellenir; yoksa yeni yanıt + `Responses + 1`; anonimde `UserId` boş | -| Paylaşım | İsteğe bağlı tek medya ya da 2–6 seçenekli anket; yalnız sahibi silebilir | -| Ankete oy | Seçenek ve toplam oy +1, `PollUserVoteId` = seçenek; tekrar oy UI'da engellenir | -| Doküman | Yüklemede görünen ad zorunlu (uzantı korunur); yayına al/kaldır = klasör taşıma; silme toplu | -| Mesaj | Aynı kiracıdaki aktif kullanıcılara (en fazla 100 kişi listelenir); en fazla 10 ek; çevrimiçi durumu SignalR (`/messengerhub`) | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Kök `App.Hr.Intranet`; her yönetim ekranının kökü + standart alt -yetkiler (`.Create/.Update/.Delete/.Export/.Import`, ana ekranlarda `.Note`). Duyuru, Anket, Sosyal -Paylaşım ve Etkinlik ayrıca **`.Widget`** taşır — pano kutusunu görme yetkisidir. Dokümanlar: -`App.Hr.Intranet.Document` + `.Create` (yükle) / `.Update` (yayına al/kaldır) / `.Delete`. -Intranet Widgets: `App.DeveloperKit.IntranetWidgets` (+ CRUD). Hiçbir yetki role otomatik atanmaz. - -Önerilen dağıtım: - -| Rol | Yetkiler | -| --- | --- | -| Tüm çalışanlar | `AbpIdentity.Users.Widget`, `App.Files.Widget`, dört `.Widget` yetkisi, `App.Hr.Intranet.Document` (okuma); performans kutuları için `HrPerformance.md` §6 | -| İç iletişim | `App.Hr.Intranet` dalının tamamı | -| Sistem yöneticisi | `App.DeveloperKit.IntranetWidgets` | - -**Kontrol edilmeli — güvenlik:** `IntranetAppService`, `MessengerAppService` ve dosya yöneticisi servisi -yalnız oturum ister (`[Authorize]`); `App.Hr.Intranet.*` yetkilerini sunucuda denetlemez. Pano -kutularının yetkisi (`PermissionName`) sunucuda süzülür, doküman yetkileri ise **yalnız arayüzde** -uygulanır. - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `AbpUsers` (+ departman, pozisyon) | Doğum günleri, yazar/kullanıcı kartları, mesajlaşma rehberi | -| Dosya yöneticisi / CDN (`intranet`, `intranet/_passive`) | Doküman kütüphanesi ve pano doküman kutusu | -| Developer Kit › Custom Components | Custom pano kutuları | -| SignalR (`/messengerhub`) | Mesajlaşma ve çevrimiçi durumu | -| Organizasyon Şeması | Kullanıcı satırlarında sosyal duvarın `UserProfileCard` bileşenini kullanır | - ---- - -## 8. Akış örneği - -1. İç iletişim **Duyurular**'a "Yeni ofis açılışı"nı görsel ve HTML içerikle ekler, **sabitler** → panonun sağ kolonunda görünür. -2. **Anketler**'de "Çalışan Memnuniyet Anketi"ni anonim ve aktif açar; **Sorular** sekmesine puanlama, çoktan seçmeli (seçenekleriyle) ve metin soruları ekler. -3. Çalışan panoda anketi doldurur, sonradan yanıtını günceller; İK **Yanıtlar** sekmesinden sonuçları görür (anonimde kişi boş). -4. **Etkinlikler**'de "Jazz Akşamı" tarih, yer ve fotoğraflarla yayınlanır → "Yaklaşan Etkinlikler" kutusunda çıkar; çalışanlar beğenir/yorumlar. -5. Çalışan sosyal duvarda iki seçenekli bir anket paylaşır; diğerleri oy verir. -6. Doküman sorumlusu "İzin Prosedürü.pdf"i yükler ve yayına alır → pano doküman kutusunda indirilebilir olur. -7. Sistem yöneticisi Intranet Widgets'a bir custom component'i (ör. kurum KPI kartı) orta kolona ekler. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Duyuru panoda görünmüyor.** Kutu yalnız sabitlenmiş duyuruları (en fazla 3) gösterir; listelenmek için **Sabitle** işaretli olmalı. - -**Süresi dolmuş duyuru/anket hâlâ görünüyor.** Sunucuda son tarih süzmesi yoktur; duyuru sabitlemesi kaldırılmalı, anket `passive` yapılmalıdır. - -**Pano yerleşimim başka bilgisayarda yok.** Yerleşim tarayıcıda saklanır. - -**Pano kutusu görünmüyor.** Kayıt aktif olmalı ve kullanıcıda `PermissionName` yetkisi bulunmalı; Custom kutuda bileşen aktif olmalı. - -**Yanıtlarımı değiştirebilir miyim?** Evet; anketi tekrar açıp kaydetmek önceki yanıtı günceller. - -Kontrol edilmeli (koddan tespit edilenler): -- Ankete oy sunucuda kullanıcı bazında tutulmaz (`PollUserVoteId` tek kolon); aynı kullanıcı API'yi doğrudan çağırarak tekrar oy verebilir. -- `SocialPost.IsLiked` beğenen son kullanıcıya göre veritabanına yazılır; listelerken sunucu kullanıcıya göre yeniden hesaplar. -- Duyuru modalındaki ekler bölümü dizi bekler, `Attachments` metindir; ekler görünmeyebilir. -- Anket entity açıklaması `draft|active|closed` der, ekran `active|passive` sunar. -- Sosyal paylaşımda yüklenen medya base64 olarak veritabanına yazılır; büyük dosyalar tabloyu büyütür. -- `Hr_T_EventPhoto` tablosu ve `sql/object/Hr_T_EventPhoto.sql` yoktur (referans dokümanda geçer); etkinlik fotoğrafları `Hr_T_Event.Photos` kolonundadır. - ---- - -## 10. Dosyalar - -| Dosya | İçerik | -| --- | --- | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Hr.cs` | Yönetim ekranları | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Saas.cs` | Intranet Widgets ekranı | -| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Hr/Intranet/*.cs`, `Entities/Tenant/Administration/IntranetWidget.cs`, `Entities/Tenant/Messenger*.cs` | Entity'ler | -| `api/src/Sozsoft.Platform.Application/Intranet/IntranetAppService.cs`, `Messenger/MessengerAppService.cs` | Servisler | -| `ui/src/views/intranet/Dashboard.tsx`, `widgets/*`, `SocialWall/*`, `documents/IntranetDocuments.tsx` | Pano, kutular, sosyal duvar, doküman sayfası | -| `ui/src/components/template/MessengerWidget.tsx` | Mesajlaşma penceresi | -| `configs/seeds/data/App.Hr.Intranet.*.json`, `App.DeveloperKit.IntranetWidgets.json` | Örnek veri ve pano kutuları | - -Örnek veri: -- 5 duyuru (3'ü sabitlenmiş). -- 3 anket, 10 soru ve 13 seçenek. -- 6 paylaşım: 4 medya (2 resim, 1 video, 1 anket), 8 yorum. -- 50 etkinlik türü, 5 kategori, 3 etkinlik ve 9 yorum. diff --git a/configs/seeds/docs/modules/HrLeave.md b/configs/seeds/docs/modules/HrLeave.md deleted file mode 100644 index cd91d2c3..00000000 --- a/configs/seeds/docs/modules/HrLeave.md +++ /dev/null @@ -1,593 +0,0 @@ -# İK › İzin Yönetimi (`App.Hr.Leave`) - -İzin talebi, iki aşamalı onay (departman müdürü → İK), yıllık izin bakiyesi ve rapor (istirahat) -eşlemesi. **İnsan Kaynakları menüsü yalnız İK içindir**: tüm talepleri ve bakiyeleri İK izler. -Çalışan ve müdür izinle ilgili her şeyi **Intranet › Dashboard**'daki widget'lardan yapar. Wizard -ekranları, SQL nesneleri ve custom component widget'larıyla kuruludur. Çerçeve dışında iki ek -vardır (kullanıcı onayıyla): Grid Workflow'da kayıttan okunan onaycı (`@Kolon`) ve kullanıcı -detayındaki **İzinler** sekmesi. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Çalışan | Bakiyesini izler, izin talebi açar, taleplerinin onay durumunu takip eder, henüz karar verilmemiş talebini düzeltir/siler | Intranet panosu: **İzinlerim** widget'ı → İzin Talebi Oluştur · Taleplerim · Bakiyem · Profil › İzinlerim (bakiye + talepler salt okunur, İzin Talebi Oluştur) | -| Departman müdürü | Departmanının taleplerini onaylar/reddeder | Intranet panosu: **Ekibimin İzinleri** widget'ı → Ekibimin İzin Talepleri | -| İK | Tüm talepleri izler, ikinci onayı verir, çalışan adına talep girer, bakiyeleri izler, açılış/devir düzeltmesi girer, çalışma günlerini ve kademeleri ayarlar | İK › İzin Yönetimi › İzin Talepleri · İzin Bakiyeleri · Ayarlar › İnsan Kaynakları › İzin · Kullanıcı detayı › İzinler | -| Sağlık birimi | Raporu Sağlık Kartı'na girer; kayıt izin listesine onaylı düşer | İK › Sağlık Kartları › İstirahat Raporları | - -Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur. - ---- - -## 2. Analiz ve kararlar - -### 2.1 Talep - -> İnsan Kaynakları › İzin Yönetimi. Kullanıcı Intranet Dashboard'dan kendi bakiye raporunu izler, -> izin talebi oluşturur, bir butonla taleplerini ve onay durumlarını takip eder (Performansım -> widget'ındaki Değerlendirmelerim gibi). İzin türüne göre gerekli alanlar doldurulur; bakiye -> yetmezse talep engellenir veya uyarı verilir; aynı tarihlerde çakışan talep oluşturulamaz. -> Sağlık Kartı › İstirahatler ile Rapor türündeki izin tek kayıttır. İzin bakiyesi kullanıcı -> kartında gösterilir. Alanlar: izin türü, başlangıç/bitiş tarihi ve saati, yarım gün, gün sayısı -> (otomatik), açıklama, ek belge, durum. Yıllık hak çalışma yılına göre hesaplanır. Onay önce -> departman müdürü (İş Pozisyonları'ndaki departman müdürü), sonra İK. Talep gelince yöneticiye -> bildirim gider. İK menüsü yalnız İK kullanır; widget'lar Aktif Anketler'in altına (sol kolon). - -### 2.2 Depodan okunanlar (sorulmadı) - -- İzin türleri `Hr_T_LeaveType` (İK › Tanımlamalar): cinsiyet, yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün. -- Rapor kayıtları `Adm_T_UserSickLeave`; iki ekran kullanır: Sağlık Kartı (`App.Hr.HealthCardSickLeave`) ve kullanıcı detayı (`App.IdentityManagement.UserSickLeave`). -- Kıdem `AbpUsers.SeniorityStartDate` (boşsa `HireDate`), doğum `BirthDate`, cinsiyet `Gender`, departman/pozisyon `DepartmentId`/`JobPositionId`. -- Tatiller `Hr_T_WorkCalendar` (`Holiday` / `HalfDay`, `FREQ=YEARLY` tekrar). -- Pozisyon ağacı `Hr_T_JobPosition` (`DepartmentId` + `ParentId`); departmanda "müdür" alanı yoktur. -- Grid Workflow onaycıyı düğümde sabit tutuyordu — kayda göre değişen müdür için motor eki gerekti. - -### 2.3 Keşif turu cevapları - -| # | Soru | Seçilen | -| --- | --- | --- | -| 1 | Onay akışı | Grid Workflow + motor eki: düğüm onaycısı `@Kolon` ise kayıttan okunur | -| 2 | Müdür nasıl bulunur | Departmanın en üst pozisyonu (üst pozisyonu başka departmanda ya da üstü olmayan); çalışan o pozisyondaysa bir üst pozisyonun sahibi; birden çok müdür varsa herhangi biri | -| 3 | Yıllık hak | İş Kanunu md.53 kademeleri + devir (kullanılmayan izin devreder) | -| 4 | Bakiye yetersiz | İzin türü bazında İK seçer: `BalanceExceedAction` = Engelle / Uyar ve kaydet | -| 5 | İK onaycısı | Düğümde sabit kullanıcı(lar) (İzin Talepleri akışının "İK Onayı" düğümü) | -| 6 | Gün sayısı | Ayarlar › İnsan Kaynakları › İzin'deki çalışma günleri + Çalışma Takvimi tatilleri (kullanıcı kararı: tüm İK ayarları bu grupta) | -| 7 | Rapor talebi | Onay akışından geçer; onaylanınca Sağlık Kartı'nda görünür (onay beklerken sağlık kartına ve puantaja düşmez), reddedilirse kalkar | -| 8 | Kullanıcı kartı | Kullanıcı detayına **İzinler** sekmesi (bakiye özeti + talepler + defter) | -| 9 | Üstü olmayan pozisyon (Genel Müdür) | Müdür adımı atlanır, talep doğrudan İK Onayı'na gider (üretim sırasında soruldu) | - -### 2.4 Üretimde verilen kararlar - -| Konu | Karar | Neden | -| --- | --- | --- | -| Persona ekranında akış | **İzin Taleplerim** ekranında Workflow yoktur; ilk adımı (`Müdür Onayı` + müdür kullanıcı adları) kayıt sonrası prosedür yazar | Workflow alanlarını yazabilen persona ekranı, çalışanın durumu API ile "Onaylandı" yapmasına izin verirdi; alanlar İK yetkisine kilitli | -| Müdür ekranı | **Ekibimin İzin Talepleri** ayrı ekran, aynı akış başlıklarıyla; satır `ManagerIds` ile süzülür | Akış düğümleri ekrana bağlıdır, durum başlıkla eşleşir (`FindCurrentCriteria`) | -| İK onaycısının tek kaynağı | Kayıt sonrası prosedür İK adımına girerken onaycıyı **İzin Talepleri** akışının "İK Onayı" düğümünden okur | Ekibimin İzin Talepleri akışındaki İK düğümü ayrı düzenlenirse sapma olmasın | -| Yöneticinin geçişleri | Müdür yalnız Müdür Onayı → İK Onayı / Reddedildi yapabilir; başka geçiş geri alınır | Workflow alanları müdür ekranında yazılabilir olmak zorunda (motor ekranın kayıt yolunu kullanır) | -| Bakiye defteri | Hak ediş yılı başına satır; 0. yıl düzeltmeler ve ilk hak edişten önceki kullanım | Devirli kümülatif bakiyenin denetlenebilir dökümü | -| Açılış bakiyesi | **Bakiye Düzeltmeleri** (± gün) | Devirli hesapta sistem öncesi kullanım girilmezse geçmiş bütün yıllar kullanılmamış görünür | -| Bildirim | Uygulama içi + toast (`IzinTalebiOnayBekliyor`, `IzinTalebiSonuclandi`); Workflow `Inform` düğümü kullanılmadı | Inform yalnız e-posta gönderir ve onaycısı sabittir | -| Ek belge | `dxImageUpload` (base64, `nvarchar(MAX)`), listede gizli | Platform standardı | -| En üst pozisyon | Prosedür `RequiresManagerApproval`'ı yazar (1 = müdür onayı gerekir, 0 = atlanır); İzin Talepleri akışında Başlangıç ile Müdür Onayı arasında bu kolona bakan karşılaştırma düğümü vardır, çalışanın kendi talebinde prosedür durumu doğrudan İK Onayı yapar | Motorun karşılaştırma düğümü yalnız sayısal kolon okur (`EvaluateCondition`) ve satırı ekranın sorgusundan alır; kolon İzin Talepleri'nde gizli alandır | -| Form günü | Gün formda tarayıcıda önizlenir (hafta içi gün, yarım günde 0,5), kalıcı değer prosedürün hesabıdır; İzin Türü lookup'ı cascade değildir | Cascade ebeveyni çocuğu kilitler ve değiştiğinde temizler; ayrıntı §5.1 | -| Bildirim başlığı | Bildirim panelinde ve etkinlik kaydında tip adı yerine kaydın `Subject`'i gösterilir (bütün modüller) | Tip adı (`PerformansDurumDegisti`) koddur; konu çevrilmiş metindir | - -### 2.5 Varsayılan kalanlar - -- Çalışma günleri Pzt–Cum; kademeler 14 / 20 / 26, genç/yaşlı en az 20 (ayarlarda değiştirilir). -- İzin türü varsayılanı: yıllık izinden düşen ya da yıllık sınırı olan türler **Engelle**, diğerleri **Uyar ve kaydet** (seed). -- Rapor kaydı `SickLeaveType = Disease`, gün sayısı takvim günü (Sağlık Kartı kuralı); izin talebindeki gün çalışma günüdür. - ---- - -## 3. Menü ve ekranlar - -### 3.1 İK menüsü - -`İnsan Kaynakları › İzin Yönetimi` (`App.Hr.Leave`, sıra 14, `FcOvertime`) — yalnız İK. - -| Sıra | Menü (TR / EN) | `ListFormCode` | Wizard | Kaynak | Alt formlar | Widget'lar | -| --- | --- | --- | --- | --- | --- | --- | -| 1 | İzin Talepleri / Leave Requests | `App.Hr.LeaveRequest` | `LeaveRequest.json` | `Hr_T_LeaveRequest` | — | Müdür Onayında · İK Onayında · Onaylanan (bu yıl) · Reddedilen (bu yıl) | -| 2 | İzin Bakiyeleri / Leave Balances | `App.Hr.LeaveBalance` | `LeaveBalance.json` | `Hr_V_LeaveSummary` (salt okunur) | `LeaveBalanceAdjustment`, `LeaveBalanceYear` (`Id → EmployeeId`) | Çalışan · Toplam Kalan Gün · Eksi Bakiye · Onay Bekleyen Gün | - -Menüsüz alt formlar: **Bakiye Düzeltmeleri** (`App.Hr.LeaveBalanceAdjustment`, `Hr_T_LeaveBalanceAdjustment`), -**İzin Defteri** (`App.Hr.LeaveBalanceYear`, `Hr_V_LeaveBalanceYear`, salt okunur). - -Görünümler: hepsi Grid, Card, Pivot, Chart. - -### 3.2 Çalışana ve müdüre ait ekranlar (menüsüz) - -| Ekran | `ListFormCode` | Satır süzmesi | Yapılabilen | -| --- | --- | --- | --- | -| İzin Taleplerim | `App.Hr.MyLeaveRequest` | `EmployeeId = @USERID` | Ekle; karar verilmeden düzelt/sil. `EmployeeId` sunucuda `@USERID` ile yazılır | -| Bakiyem | `App.Hr.MyLeaveBalance` | `EmployeeId = @USERID` | Defteri görür | -| Ekibimin İzin Talepleri | `App.Hr.TeamLeaveRequest` | `ManagerIds` içinde kullanıcı | Müdür adımında Onayla / Reddet | - -Talep formu doğrudan açılır: `/admin/form/App.Hr.MyLeaveRequest`. - -### 3.3 Intranet › Dashboard widget'ları - -Sol kolon (`Column: 0`), Aktif Anketler'in (30) altında; kayıtlar `data/App.DeveloperKit.IntranetWidgets.json`. - -| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Butonlar | -| --- | --- | --- | --- | --- | -| `my-leave` · 35 | `MyLeaveWidget` | `App.Hr.MyLeaveRequest` | Kalan / kullanılan / onay bekleyen gün, sonraki hak ediş, süren ilk 3 talep ve durumu | İzin Talebi Oluştur · Taleplerim · Bakiyem | -| `team-leave` · 36 | `TeamLeaveWidget` | `App.Hr.TeamLeaveRequest` | Onayımı bekleyen talep sayısı ve ilk 5'i, bugün izinde olanlar | Onay Bekleyenler | - -Bileşenler code modunda, rotasızdır; veriyi ekranların kendi sorgusundan okur -(`GET /api/app/list-form-select/select`). Bakiye kartları `App.Hr.MyLeaveBalance` yetkisi yoksa gizlenir. - -### 3.4 Kullanıcı detayı › İzinler - -`ui/src/views/admin/user-management/LeaveTab.tsx`: İzin Bakiyeleri satırından altı kart (hak edilen, -düzeltme, kullanılan, bekleyen, kalan, kullanılabilir), altında kullanıcıya süzülmüş **İzin Talepleri** -ve **İzin Defteri** listeleri. Her parça kendi ekran yetkisiyle görünür; İK buradan çalışan adına talep -ekleyebilir (yeni satırın `EmployeeId`'si süzgeçten dolar). - -### 3.5 Ayarlar - -Ayarlar › İnsan Kaynakları › İzin (`App.HrSettings` › `App.HrSettings.Leave`, sağlayıcılar `T|G|D`): - -| Kod | Varsayılan | -| --- | --- | -| `App.HrSettings.Leave.Work{Monday…Sunday}` | Pzt–Cum `True`, Cmt–Paz `False` | -| `App.HrSettings.Leave.AnnualDays1To5` / `AnnualDays5To15` / `AnnualDays15Plus` | 14 / 20 / 26 | -| `App.HrSettings.Leave.MinDaysYoungOld` | 20 | - -SQL tarafı ayarı `dbo.Hr_F_HrSetting` ile ABP'nin sırasıyla okur (kiracı → genel → tanım varsayılanı). - ---- - -## 4. Veri modeli - -``` -AbpUsers ──< Hr_T_LeaveRequest >── Hr_T_LeaveType - │ └── Adm_T_UserSickLeave (SickLeaveId, Rapor türünde) - └──< Hr_T_LeaveBalanceAdjustment -Hr_V_LeaveBalanceYear (defter) ──▶ Hr_V_LeaveSummary (çalışan başına toplam) -``` - -| Nesne | Önemli kolonlar | Kural | -| --- | --- | --- | -| `Hr_T_LeaveRequest` | `RequestNo`, `EmployeeId`/`EmployeeName`/`DepartmentId`/`JobPositionId`, `LeaveTypeId`, `StartDate`/`EndDate` (tarih+saat), `IsHalfDay`, `HalfDayPart` (Morning/Afternoon), `Days` (0,5 adımlı), `Description`, `DocumentFileName`/`DocumentContent`, `BalanceWarning`, `SickLeaveId`, `ManagerIds`/`ManagerUserNames`, `RequiresManagerApproval` (int, 1/0), `ApprovalStatus`/`ApprovalUser`/`ApprovalDate`/`ApprovalDescription`, `LastNotifiedStatus`, `IsActive` | `EndDate ≥ StartDate`; kiracı + tam audit | -| `Hr_T_LeaveBalanceAdjustment` | `EmployeeId`, `AdjustmentDate`, `Days` (≠ 0, ±), `Reason`, `IsActive` | — | -| `Hr_T_LeaveType` (+ kolon) | `BalanceExceedAction` (`Block`/`Warn`, varsayılan `Block`) | Kayıpsız `ALTER ADD` | -| `Hr_V_LeaveBalanceYear` | `Id` (`{EmployeeId}-{YearNo}`), `YearNo`, `AccrualDate`, `PeriodEndDate`, `EntitledDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `CumulativeRemainingDays`, `NextAccrualDate`, `NextAccrualDays` | Görünüm | -| `Hr_V_LeaveSummary` | `Id` (= kullanıcı), `ServiceYears`, `EntitledDays`, `AdjustmentDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `AvailableDays`, `NextAccrualDate/Days`, `IsActive` | Görünüm | - -Durum değerleri (Workflow düğüm başlıkları): `Onaya Gönderildi` · `Müdür Onayı` · `İK Onayı` · `Onaylandı` · `Reddedildi`. - ---- - -## 5. İş kuralları ve hesaplar - -### 5.1 Gün sayısı (`Hr_F_LeaveWorkDays`) - -Başlangıç–bitiş tarihleri (saat dikkate alınmaz) arasındaki her gün: ayarlarda çalışma günü değilse 0; -Çalışma Takvimi'nde `Holiday` ise 0, `HalfDay` ise 0,5; aksi 1. Yıllık tekrarlı satır başlangıç -yılından itibaren her yıl aynı gün/aya düşer. Yarım gün talepte sonuç en fazla 0,5'tir. - -Formda gün veri girerken dolar (Başlangıç, Bitiş ve Yarım Gün alanlarının `EditorScript`'i, `custom` tarifi). -Bu bir önizlemedir: iki tarih arasındaki hafta içi günler sayılır, yarım günde 0,5 yazılır; Çalışma Günleri -ayarı ve Çalışma Takvimi tatilleri formda düşülmez. Kayıtta prosedür günü `Hr_F_LeaveWorkDays` ile yeniden -hesaplar ve kayıtlı değer odur. - -| Olay | Formda | -| --- | --- | -| Başlangıç / Bitiş değişir | Gün yeniden hesaplanır; yarım gün açıkken Başlangıç değişirse Bitiş onu izler | -| Yarım Gün işaretlenir | Bitiş = Başlangıç, Gün 0,5, Yarım Gün Dilimi açılır | -| Yarım Gün kaldırılır | Dilim temizlenip kilitlenir, Gün tam gün olarak hesaplanır | - -Notlar: - -- **Dilim kilidi `custom` kuralıdır** (`readOnly` tarifi değil). Grid popup'ında editörler yeniden çizilince - kural açılış olayıyla (`isReady`) tekrar çalışır; o anda form verisi güncel değildir (`form.getEditor` popup - editörünü döndürmez) ve tarif Yarım Gün'ü eski hâliyle okuyup kilidi geri kapatırdı. Kural bu çalışmada - değeri grid'in düzenlenen satırından (`editor.component.cellValue`) okur; form sayfasında form verisinden. -- **Dilimin script'i yoktur.** Form sayfası script'li bir editör değişince `formData`'yı baştan yazar; bu sırada - açılır liste temizlenip yeniden dolar ve script'i olsaydı kendini tetikleyip sonsuz döngüye girerdi. - Tutarlılığı prosedür sağlar: yarım gün değilse dilim silinir, yarım günde boş dilim `Morning` olur. -- **İzin Türü düz bir lookup'tır**, cascade kullanılmaz: bool ebeveyn `false` iken çocuğu kilitler, tarih - değişince değeri silerdi. - -### 5.2 Yıllık hak ve bakiye (`Hr_V_LeaveBalanceYear`) - -| Değer | Formül | -| --- | --- | -| Hak ediş tarihi | Kıdem başlangıcı + n yıl (n = 1, 2, …), bugün ve (varsa) işten çıkış tarihine kadar | -| Hak edilen | n ≤ 5 → `AnnualDays1To5`; 6 ≤ n ≤ 14 → `AnnualDays5To15`; n ≥ 15 → `AnnualDays15Plus`. Hak ediş tarihindeki yaş ≤ 18 ya da ≥ 50 ise en az `MinDaysYoungOld` | -| Kullanılan / bekleyen | Yıllık izinden düşen türdeki onaylı / onay bekleyen taleplerin günü; talep başlangıcının düştüğü hak ediş dönemine yazılır | -| 0. yıl | Düzeltmelerin toplamı ve ilk hak edişten önce başlayan talepler | -| Kalan | Σ(hak edilen + düzeltme) − Σ kullanılan (devirli) | -| Kullanılabilir | Kalan − onay bekleyen | - -### 5.3 Kayıt sonrası (`Hr_S_LeaveRequestAfterSave`) - -Her ekleme/güncellemede (Workflow kararı dahil) çalışır; `THROW` kaydı geri alır. - -1. Çalışan adı, departman, pozisyon kullanıcı kartından; talep no `IZN-YYYY-00001`. (İK formunda çalışan seçilince departman ve pozisyon formda da hemen dolar: Çalışan lookup'ı iki kolonu döndürür, `copy` tarifi yazar.) -2. Müdür (§2.3 karar 2) bulunur → `ManagerIds`, `ManagerUserNames`. Bulunamazsa: çalışanın pozisyonunun üst pozisyonu yoksa (Genel Müdür) `RequiresManagerApproval = 0` yazılır ve müdür adımı atlanır; değilse ve talep müdür adımına kadar ise `THROW 51110` (yapılandırma eksik). -3. Müdür ekranından izinsiz geçiş önceki duruma geri alınır. -4. Çalışanın yeni talebi `Müdür Onayı`'na (müdür adımı atlanıyorsa `İK Onayı`'na) alınır; adıma girerken onaycı yazılır (müdür adımı → `ManagerUserNames`, İK adımı → İzin Talepleri akışının "İK Onayı" düğümü). -5. Gün sayısı hesaplanır. -6. Talep sonuçlanmamışsa doğrulanır: - -| Kod | Kural | -| --- | --- | -| 51111 | Tür cinsiyeti çalışana uymuyor | -| 51112 | Tür yarım güne izin vermiyor | -| 51113 | Yarım günde başlangıç ve bitiş aynı gün olmalı | -| 51114 | Tür belge istiyor, belge yok | -| 51115 | Aralıkta çalışma günü yok | -| 51116 | Reddedilmemiş başka bir talep ya da talebe bağlı olmayan istirahat aynı güne düşüyor (aynı günün iki ayrı yarısı serbest) | -| 51117 | Yıllık izinden düşen türde gün > kullanılabilir bakiye, ya da türün yıllık sınırı aşılıyor — tür `Block` ise; `Warn` ise kayıt yapılır, uyarı `BalanceWarning`'e yazılır | -| 51118 | Talebin (yeni ya da eski) tarihleri kapalı puantaj dönemine düşüyor — ekleme, düzeltme, karar ve silme reddedilir (`Hr_F_TimesheetPeriodClosed`; eski tarihleri `Hr_S_LeaveRequestGuard` denetler) | -| 51119 | Tarihler çalışanın işe giriş – işten çıkış aralığının dışında | - -7. Rapor (`Code = Sick`) türünde talep **onaylandığında** istirahat satırı açılır/güncellenir; reddedilen, onay bekleyen ya da türü değişen talebin istirahati kalkar. Rapor türü dışındaki talebin gün sayısı rapora denk gelen günleri saymaz (`Hr_F_LeaveNetDays`); rapor değişince çalışanın diğer taleplerinin gün sayısı yenilenir (`Hr_S_LeaveDaysRefresh`). -8. Silinen talep (silme sonrası komut aynı prosedürü çağırır): bağlı istirahat kalkar, puantaj yeniden hesaplanır. -9. Durum bildirim taşıyan bir değere geçtiyse bir kez bildirim gider, `LastNotifiedStatus` güncellenir. -10. Puantaj: talebin günleri yeniden hesaplanır; tarihi değişen talebin eski günlerini hesap kendisi aralığa katar. - -### 5.4 Satır koruması (`Hr_S_LeaveRequestGuard`, before-command) - -| Aktör | Kural | -| --- | --- | -| Çalışan | Yalnız kendi talebi (`51100`); durum `Onaya Gönderildi`/`Müdür Onayı` değilse düzeltme/silme yok (`51101`) | -| Müdür | Silemez (`51102`); `ManagerIds` içinde olmalı (`51103`); talep `Müdür Onayı`'nda olmalı (`51104`) | -| İK | Serbest | -| Hepsi | Talebin kayıttaki (eski) tarihleri kapalı puantaj dönemine düşüyorsa düzeltme/silme yok (`51118`) | - -Alan kilidi: persona ekranlarında çalışanın/müdürün değiştirmemesi gereken alanların yazma yetkisi -`App.Hr.LeaveRequest.Create/.Update`'e bağlıdır; sunucu yetkisi olmayan alanı düşürür. Bu yüzden -çalışan/müdür rolüne İzin Talepleri'nin `.Create/.Update` yetkisi verilmez. - -### 5.5 Rapor ↔ izin (tek kayıt) - -| Nereden | Ne olur | -| --- | --- | -| İzin talebi, tür Rapor | Onayda `Adm_T_UserSickLeave` satırı açılır (`SickLeaveId`); onaylı talep güncellenince güncellenir, silinince/reddedilince kalkar | -| Sağlık Kartı › İstirahat Raporları ya da kullanıcı detayı › İstirahatler | `Hr_S_LeaveSickLeaveSync`: onaylı Rapor talebi açılır (onay akışına girmez), güncellemede tarih/gün, silmede (silme sonrası komut aynı prosedürü çağırır) talep kalkar. Rapora denk gelen yıllık izin günleri bakiyeye döner. Kapalı puantaj ayına düşen rapor kaydedilmez (`51120`). Kiracıda `Sick` kodlu tür yoksa eşleme yapılmaz | -| Çalışma Takvimi | Takvim satırı kaydedilince denk gelen taleplerin gün sayısı yeniden hesaplanır (`Hr_S_WorkCalendarAfterSave`) | - -### 5.6 Onay akışı (Grid Workflow) - -`Onaya Gönderildi` (Start) → `Müdür Onayı Gerekli mi?` (Compare, `RequiresManagerApproval = 1`) → -evet: `Müdür Onayı` (Approval, `@ManagerUserNames`) / hayır: doğrudan `İK Onayı` (Approval, seed'de -`system@sozsoft.com`) → `Onaylandı` (End); iki onay adımının reddi → `Reddedildi` (End). -Karşılaştırma düğümü yalnız İzin Talepleri akışındadır (akış İK grid'inden eklenen kayıtta orada başlar); -Ekibimin İzin Talepleri akışı başlatılmaz, yalnız müdür adımından ilerler. Akış iki ekranda aynı başlıklarla durur. İK onaycısı İzin -Talepleri › ListForm › Workflow › "İK Onayı" düğümünden değiştirilir (§2.4). - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Dal `App.Hr.Leave` → `App.Hr.LeaveRequest`, `App.Hr.LeaveBalance` -(altında `LeaveBalanceAdjustment`, `LeaveBalanceYear`). Kökte menüsüz `App.Hr.MyLeaveRequest`, -`App.Hr.MyLeaveBalance`, `App.Hr.TeamLeaveRequest`. Ayar: `App.HrSettings` › `App.HrSettings.Leave` -(Administration grubu, `App.Setting` altında). Her ekranda `.Create/.Update/.Delete/.Export/.Import/.Note`. -**Hiçbir yetki role otomatik atanmaz.** - -| Rol | Verilecek yetkiler | -| --- | --- | -| Tüm çalışanlar | `App.Hr.MyLeaveRequest` (+ `.Create/.Update/.Delete`), `App.Hr.MyLeaveBalance` | -| Müdürler | Yukarıdakiler + `App.Hr.TeamLeaveRequest` (+ `.Update` — Workflow kararı güncelleme yetkisi ister) | -| İK | `App.Hr.Leave` dalının tamamı + `App.HrSettings.Leave` | - -Widget'lar liste okuma yetkisiyle görünür (İzinlerim `App.Hr.MyLeaveRequest`, Ekibimin İzinleri `App.Hr.TeamLeaveRequest`). - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `AbpUsers` | Çalışan, kıdem, doğum tarihi, cinsiyet, departman/pozisyon; onaycı kullanıcı adları | -| `Hr_T_JobPosition` / `Hr_T_Department` | Departman müdürü çözümü | -| `Hr_T_LeaveType` | Tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı) | -| `Hr_T_WorkCalendar` | Tatil ve yarım günler | -| `AbpSettings` / `Sas_H_SettingDefinition` | Çalışma günleri ve kademeler | -| `Adm_T_UserSickLeave` | Rapor eşlemesi | -| Puantaj ve Devam Takibi | `Hr_S_LeaveRequestAfterSave` sonunda talebin günleri `Hr_S_TimesheetCalculate` ile yeniden hesaplanır: onaylı izin İzinli, rapor Raporlu gün olur; ücretli izne denk gelen tatil İzinli değil tatil, ücretsiz izin hafta sonu dahil İzinli yazılır. Tarihi değişen ya da silinen talebin eski günleri aynı işlemde düzelir (`HrAttendance.md` §7.1). Kapalı puantaj ayına düşen talep değiştirilemez; onay bekleyen talebi olan ay kapatılamaz. Çalışma günü ayarları puantajda hafta tatilini de belirler | -| Bildirimler | `IzinTalebiOnayBekliyor` (müdür / İK onaycısı), `IzinTalebiSonuclandi` (çalışan); kurallar `Custom` + `UiActivity`/`UiToast`. Metinler `App.Hr.Leave.Notification.{Approval,Result}.{Subject,Message}` (TR), yer tutucular `[Employee]`, `[LeaveType]`, `[StartDate]`, `[EndDate]`, `[Days]`, `[Status]`. Yazan: `Hr_S_LeaveNotify` | - ---- - -## 8. Akış örneği - -1. İK Ayarlar › İnsan Kaynakları › İzin'de Cumartesi'yi çalışma günü yapar (gerekirse); eski çalışanlar için İzin Bakiyeleri › Bakiye Düzeltmeleri'ne sistem öncesi kullanılan günleri eksi olarak girer. -2. Muhasebe Şefi panodaki **İzinlerim** widget'ında kalan 18 günü görür, **İzin Talebi Oluştur** ile 3 günlük yıllık izin açar. -3. Gün kayıtta 3 hesaplanır, talep `Müdür Onayı`'na düşer, Muhasebe Müdürü bildirim alır. -4. Müdür **Ekibimin İzinleri** → Onay Bekleyenler'den talebi seçip **Onayla** der → talep `İK Onayı`'na geçer, İK onaycısı bildirim alır. -5. İK İzin Talepleri'nde onaylar → `Onaylandı`; çalışan bildirim alır, bakiye 15'e iner. -6. Çalışan rapor alır, Rapor türünde talep açıp raporu ekler → Sağlık Kartı › İstirahat Raporları'nda görünür; aynı onay akışından geçer. -7. Sağlık birimi başka bir raporu doğrudan Sağlık Kartı'na girer → İzin Talepleri'nde onaylı Rapor talebi olarak görünür. - ---- - -## 9. Sık sorulanlar - -**"Departman müdürü bulunamadı" hatası.** Çalışanın kullanıcı kartında departman ve pozisyon dolu olmalı; departmanın en üst pozisyonunda (ya da üst pozisyonlarda) aktif bir kullanıcı bulunmalı (§5.3 adım 2). Üst pozisyonu olmayan çalışan (Genel Müdür) bu hatayı almaz; talebi doğrudan İK onayına gider. - -**Genel Müdür'ün talebini kim onaylar?** Müdür adımı atlanır, yalnız İK onaylar (§2.3 karar 9). - -**Gün sayısı beklenenden az.** Hafta sonu, ayarlarda kapalı gün ve Çalışma Takvimi tatilleri sayılmaz; arife 0,5 sayılır. - -**Bakiye çok yüksek görünüyor.** Devirli hesap kıdem başlangıcından bugüne bütün yılları sayar; sistem öncesi kullanılan izin Bakiye Düzeltmeleri'ne eksi olarak girilmelidir. - -**Bakiyem/İzinlerim'de kıdem uyarısı.** Kullanıcı kartında Kıdem Başlangıç ya da İşe Giriş tarihi yok. - -**Talebimi değiştiremiyorum.** Müdür karar verdikten sonra çalışan değiştiremez/silemez (`51101`); İK ile görüşülür. - -**Müdür Onayla butonunu görmüyor.** Rolünde `App.Hr.TeamLeaveRequest.Update` olmalı; talep `Müdür Onayı`'nda ve kullanıcı o departmanın müdürü olmalı. - -**İK onaycısı nasıl değişir?** İzin Talepleri › ListForm › Workflow › "İK Onayı" düğümü. Ekibimin İzin Talepleri'ndeki aynı düğüm akışı ilerletir; onaycı kayda İzin Talepleri düğümünden yazılır. - -**Bildirim gelmiyor.** Kiracıda `IzinTalebiOnayBekliyor` / `IzinTalebiSonuclandi` tipi ve `Custom` kuralları olmalı (yeni kiracıya kopyalanır, mevcut kiracıda Administration › Bildirimler'den eklenir). - -**Kullanıcı detayındaki İstirahatler'den girilen rapor izinlere düşmüyor.** O ekranın kancaları C# seeder'dadır (`ListFormSeeder_Administration`); daha önce kurulmuş bir veritabanında ekran yeniden kurulmadıkça kanca yoktur. Sağlık Kartı ekranı wizard'dır ve migrate ile güncellenir. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_LeaveRequest.sql`, `Hr_T_LeaveBalanceAdjustment.sql`, `Hr_T_LeaveType.sql` (`BalanceExceedAction`) | Tablolar | -| `…/Hr_F_HrSetting.sql`, `Hr_F_LeaveWorkDays.sql` | Ayar okuma, gün sayısı | -| `…/Hr_V_LeaveBalanceYear.sql`, `Hr_V_LeaveSummary.sql` | Bakiye görünümleri | -| `…/Hr_S_LeaveRequestAfterSave.sql`, `Hr_S_LeaveRequestGuard.sql`, `Hr_S_LeaveNotify.sql`, `Hr_S_LeaveSickLeaveSync.sql` | Prosedürler | -| `configs/seeds/wizard/{LeaveRequest,MyLeaveRequest,TeamLeaveRequest,LeaveBalance,LeaveBalanceAdjustment,LeaveBalanceYear,MyLeaveBalance}.json` | 7 wizard; `LeaveType.json` (alan), `HealthCardSickLeave.json` (kancalar) | -| `configs/seeds/data/App.DeveloperKit.CustomComponents/{23744edc-eda9-512e-8079-fe2e8e5fd2a8,3b7b16c6-aa96-5765-8e19-fe5e727feb52}.json` | `MyLeaveWidget`, `TeamLeaveWidget` | -| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json`, `App.SettingDefinitions.json`, `App.Notifications.Notification{Types,Rules}.json`, `App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json`, `App.Hr.LeaveType.json` | Seed satırları | -| `api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs` | `@Kolon` onaycı | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` | Kullanıcı detayı istirahat kancaları | -| `ui/src/views/admin/listForm/workflow/WorkflowCriteria.tsx` | Tasarımcıda alan onaycısı seçeneği | -| `ui/src/views/admin/user-management/LeaveTab.tsx`, `Details.tsx` | İzinler sekmesi | - -Kurulum: DB Migrate (SQL nesneleri, ekranlar `WizardDataSeeder`, satırlar `ListFormSeedDataApplier`), -ardından rollere yetki (§6). Ayar tanımları uygulama yeniden başlayınca ayar ekranında görünür. - -Geri alma: Wizard Manager'dan 7 wizard silinir (alt formlar önce); tabloları düşürmek onayda seçilirse olur. -Widget bileşenleri ve pano kayıtları, bildirim tip/kural satırları, ayar tanımları, `Hr_F_*`/`Hr_V_*`/`Hr_S_Leave*` -nesneleri elle kaldırılır. `BalanceExceedAction` kolonu kalır (kayıpsız ekleme geri alınmaz). - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### İzin Talepleri — `App.Hr.LeaveRequest` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/LeaveRequest.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Leave` › `App.Hr.LeaveRequest` (sıra 1) | -| Yetki | `App.Hr.LeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İzin Talepleri — kurumdaki bütün izin talepleri ve onay durumları. Yalnız İnsan Kaynakları kullanır. | -| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Leave.Widget.ManagerApproval`, `App.Hr.Leave.Widget.HrApproval`, `App.Hr.Leave.Widget.Approved`, `App.Hr.Leave.Widget.Rejected` | -| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: `Hr_S_LeaveRequestAfterSave` | -| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE | -| Onay akışı | Start 'Onaya Gönderildi' → Compare 'Müdür Onayı Gerekli mi?' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `RequestNo` | Talep No | dxTextBox | | ✓ | | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType | -| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | -| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | -| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script | -| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | -| `Days` | Gün | dxNumberBox | | ✓ | | -| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | -| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | | -| `RequiresManagerApproval` | Müdür Onayı Gerekli | dxNumberBox | | | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | -| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | -| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | -| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | -| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | -| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | - -### İzin Bakiyeleri — `App.Hr.LeaveBalance` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/LeaveBalance.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Leave` › `App.Hr.LeaveBalance` (sıra 2) | -| Yetki | `App.Hr.LeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İzin Bakiyeleri — her çalışanın yıllık izin bakiyesi. | -| Kaynak | `Hr_V_LeaveSummary` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.LeaveBalanceAdjustment` (Id → EmployeeId), `App.Hr.LeaveBalanceYear` (Id → EmployeeId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Leave.Widget.RemainingDays`, `App.Hr.Leave.Widget.NegativeBalance`, `App.Hr.Leave.Widget.PendingDays` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeName` | Çalışan Adı | dxTextBox | | ✓ | | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `SeniorityStartDate` | Kıdem Başlangıcı | dxDateBox | | ✓ | | -| `ServiceYears` | Kıdem Yılı | dxNumberBox | | ✓ | | -| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | -| `AdjustmentDays` | Düzeltme Günü | dxNumberBox | | ✓ | | -| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | -| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | -| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | -| `AvailableDays` | Kullanılabilir Gün | dxNumberBox | | ✓ | | -| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | -| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Bakiye Düzeltmeleri — `App.Hr.LeaveBalanceAdjustment` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/LeaveBalanceAdjustment.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.LeaveBalanceAdjustment` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Bakiye Düzeltmeleri — çalışanın yıllık izin bakiyesine elle yapılan ekleme ve düşümler. | -| Kaynak | `Hr_T_LeaveBalanceAdjustment` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | IsActive=true, AdjustmentDate=@DATE | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `AdjustmentDate` | Düzeltme Tarihi | dxDateBox | ✓ | ✓ | | -| `Days` | Gün | dxNumberBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `Reason` | Neden | dxTextArea | ✓ | ✓ | | - -### İzin Defteri — `App.Hr.LeaveBalanceYear` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/LeaveBalanceYear.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.LeaveBalanceYear` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İzin Defteri — çalışanın yıllık izninin yıl yıl dökümü. | -| Kaynak | `Hr_V_LeaveBalanceYear` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | | -| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | | -| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | | -| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | -| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | -| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | -| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | -| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | | -| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | -| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | - -### İzin Taleplerim — `App.Hr.MyLeaveRequest` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyLeaveRequest.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İzin Taleplerim — oturum açan çalışanın kendi izin talepleri ve onay durumları. | -| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: `Hr_S_LeaveRequestAfterSave` | -| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `RequestNo` | Talep No | dxTextBox | | ✓ | | -| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType | -| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script | -| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script | -| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script | -| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | -| `Days` | Gün | dxNumberBox | | ✓ | | -| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | -| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | -| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | -| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | -| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | -| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | - -### Ekibimin İzin Talepleri — `App.Hr.TeamLeaveRequest` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TeamLeaveRequest.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TeamLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ekibimin İzin Talepleri — müdürü olduğunuz departmandaki çalışanların izin talepleri. | -| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND '\|' + "ManagerIds" + '\|' LIKE '%\|@USERID\|%'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | -| Komutlar | UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` | -| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `RequestNo` | Talep No | dxTextBox | | ✓ | | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `LeaveTypeId` | İzin Türü | dxSelectBox | | ✓ | sorgu: Hr_T_LeaveType | -| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | -| `EndDate` | Bitiş Tarihi | dxDateBox | | ✓ | | -| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | | -| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon | -| `Days` | Gün | dxNumberBox | | ✓ | | -| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | | -| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | | -| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | | -| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | -| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | -| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | -| `ApprovalDescription` | Onay Açıklaması | dxTextArea | | ✓ | | - -### Bakiyem — `App.Hr.MyLeaveBalance` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyLeaveBalance.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyLeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Bakiyem — yıllık izin hakkınızın ve kullanımınızın yıl yıl dökümü. | -| Kaynak | `Hr_V_LeaveBalanceYear` · filtre `"EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | | -| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | | -| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | | -| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | | -| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | | -| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | | -| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | | -| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | | -| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | | -| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrOrganization.md b/configs/seeds/docs/modules/HrOrganization.md deleted file mode 100644 index 2f9be711..00000000 --- a/configs/seeds/docs/modules/HrOrganization.md +++ /dev/null @@ -1,187 +0,0 @@ -# İK › Organizasyon ve Yetkinlik (Departman, Pozisyon, Organizasyon Şeması, Yetenek Tipleri) - -Şirketin organizasyon iskeleti ve yetkinlik sözlüğü: şubeye bağlı departman ağacı, departmana bağlı -pozisyon ağacı, bunların görsel organizasyon şeması ve yetenek tipi → yetenek → seviye sözlüğü. -Çalışanın departman/pozisyon/işe giriş/vardiya bilgileri ve yetkinlikleri kullanıcı kaydında tutulur. -Diğer bütün İK modülleri (İşe Alım, Eğitim, Performans, Disiplin, Sağlık Kartı…) bu tanımları lookup -olarak kullanır. Bu bölüm **entity + C# seeder** ile kuruludur (wizard değil); Organizasyon Şeması -özel bir React sayfasıdır. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK | Departman ve pozisyon ağacını, yetenek sözlüğünü yönetir | İK › Tanımlamalar › Departmanlar · Pozisyonlar · Yetenek Tipleri | -| İK / sistem yöneticisi | Çalışanın departman, pozisyon, işe giriş, vardiya, yetkinlik ve dil bilgilerini girer | Kimlik › Kullanıcılar › detay (İş Bilgileri, Eğitim ve Yetkinlik sekmeleri) | -| Tüm kullanıcılar (yetkili) | Organizasyonu departman ya da pozisyon bazında görür, JPG olarak dışa aktarır | İK › Organizasyon Şeması | - -Kapsam: kiracı. Departman ve pozisyon **şube bazlıdır** (`BranchId` zorunlu); ekranlarda satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Bu bölüm §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan -> (`ListFormSeeder_Hr.cs`, entity'ler, `OrgChartAppService`, `OrgChart.tsx`) okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Entity + `ListFormSeeder_Hr.cs` (migration'lı tablolar); şema için özel React sayfası + AppService | -| Departman | Ağaç (`ParentId`), şubeye bağlı; varsayılan görünüm **Tree**; aynı şubede ad tekil | -| Pozisyon | Ağaç (`ParentId` = üst pozisyon), departmana ve şubeye bağlı; varsayılan görünüm **Tree**; aynı departmanda ad tekil | -| Yönetici ilişkisi | Departmanda yönetici alanı **yoktur**; hiyerarşi pozisyon ağacından okunur | -| Host şubesi | Host varsayılan şubesi sabit kimlikle kurulur (`PlatformConsts.Branches.BranchIdDefaultValue = 1c125bf3-…`); seed departman/pozisyon satırları buna bağlıdır, kiracı şubeleri yeni GUID alır | -| Admin varsayılanı | Admin kullanıcı departman **Yönetim**, pozisyon **Genel Müdür** ile kurulur | -| Yetkinlik sözlüğü | Yetenek Tipi ekranının iki alt formu: Seviyeler (ad + `Progress` 0–100 kaydırıcı + varsayılan) ve Yetenekler | -| Çalışan yetkinliği | İki ayrı ölçek: **diller** `Hr_T_SkillLevel` seviyesiyle (`UserLanguage`), **diğer yetkinlikler** sabit 1–5 ile (`Adm_T_UserSkill`) | -| Tip adı bağımlılığı | Bazı lookup'lar tip adını sabit yazar (`'Languages'`, `'Technical Skills'`) — bu tipler yeniden adlandırılmamalıdır | - ---- - -## 3. Menü ve ekranlar - -| Menü (TR) | `ListFormCode` / rota | Yer | Görünüm | Alt formlar | -| --- | --- | --- | --- | --- | -| Yetenek Tipleri | `App.Hr.SkillType` | Tanımlamalar (1) | Grid | `App.Hr.SkillLevel`, `App.Hr.Skill` (`Id → SkillTypeId`) | -| Departmanlar | `App.Hr.Department` | Tanımlamalar (2) | **Tree** (`Id`/`ParentId`, tümü açık) | — | -| Pozisyonlar | `App.Hr.JobPosition` | Tanımlamalar (3) | **Tree** | — | -| Organizasyon Şeması | `/admin/organization` (`@/views/admin/hr/OrgChart`) | `İnsan Kaynakları` (4) | Özel sayfa | — | - -Bu ekranlarda widget yoktur ve veri seed dosyasına aynalanmaz (`SeedSync*` kapalı). - -**Organizasyon Şeması** (`ui/src/views/admin/hr/OrgChart.tsx`): -- **Mod:** Departman ya da Pozisyon. -- **Kullanıcıları göster:** Açık/kapalı seçilebilir. -- **Yakınlaştırma:** %30–300 arası, Ctrl + tekerlek ile de. -- **Dışa aktarma:** JPG olarak. -- **Kartlar:** Derinliğe göre renklenir, alt sayısı ve aç/kapa düğmesi taşır, sürüklenerek yeri değiştirilir (yer kaydedilmez). -- **Kullanıcı satırı:** Avatar gösterir; üzerine gelince profil kartı açılır (unvan, departman, e-posta, telefon). - ---- - -## 4. Veri modeli - -``` -Sas_T_Branch ──< Hr_T_Department (ParentId ağacı) ──< Hr_T_JobPosition (ParentId ağacı) - ▲ -AbpUsers.DepartmentId / JobPositionId / HireDate / ShiftId ┘ - -Hr_T_SkillType ──< Hr_T_SkillLevel (Progress, IsDefault) - └────────< Hr_T_Skill ──< Adm_T_UserSkill (Level 1–5) - └────< UserLanguage (SkillLevelId) -``` - -| Tablo | Kolonlar | Kural | -| --- | --- | --- | -| `Hr_T_Department` | `BranchId` (zorunlu), `Name` (64), `ParentId` | `UX (TenantId, BranchId, Name)` | -| `Hr_T_JobPosition` | `BranchId` (zorunlu), `DepartmentId` (zorunlu, FK Restrict), `Name` (64), `ParentId` | `UX (TenantId, Name, DepartmentId)` | -| `Hr_T_SkillType` | `Name` (128) | `UX (TenantId, Name)`; silinince yetenek/seviye kademeli silinir | -| `Hr_T_SkillLevel` | `SkillTypeId`, `Name`, `Progress` (int, 0), `IsDefault` | `UX (TenantId, SkillTypeId, Name)` | -| `Hr_T_Skill` | `SkillTypeId`, `Name` | `UX (TenantId, SkillTypeId, Name)` | -| `Adm_T_UserSkill` | `UserId`, `SkillId`, `Level`, `Note` (512) | `CHECK Level BETWEEN 1 AND 5`; `UX (TenantId, UserId, SkillId)` | -| `AbpUsers` (genişletme) | `DepartmentId`, `JobPositionId`, `HireDate`, `ShiftId`, sözleşme/fesih/ehliyet alanları | `PlatformModuleExtensionConfigurator`, `AbpIdentityUserExtensions` | - -Entity'ler: `Entities/Tenant/Hr/Definitions/{SkillType,Skill,SkillLevel,Department,JobPosition}.cs` -(`FullAuditedEntity, IMultiTenant`); EF yapılandırması `PlatformDbContext.cs`. - -Seed (`configs/seeds/data/`): - -| Dosya | İçerik | -| --- | --- | -| `App.Hr.Department.json` | Yönetim (kök) → Üretim, Satış, Finans (→ Muhasebe), Bilgi İşlem | -| `App.Hr.JobPosition.json` | Genel Müdür (kök) → BT, İhracat, İç Piyasa, Üretim, Finans müdürleri; Finans Müdürü → Muhasebe Müdürü → Muhasebe Şefi | -| `App.Hr.SkillType.json` | Languages, Soft Skills, Technical Skills | -| `App.Hr.Skill.json` | 31 yetenek: 21 dil, 3 soft skill, 7 teknik | -| `App.Hr.SkillLevel.json` | Diller C2 100 · C1 85 · B2 75 · B1 60 · A2 40 · A1 10 (varsayılan); Soft Skills Expert 100 · Advanced 80 · Intermediate 50 · Elementary 25 · Beginner 15 (varsayılan); **Technical Skills için seviye yok** | - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Departman formu | Ad → üst departman → şube; şube değişince üst departman temizlenir; üst departman listesi şubeye göre süzülür | -| Pozisyon formu | Ad → üst pozisyon → şube → departman; şube değişince departman ve üst pozisyon, departman değişince üst pozisyon temizlenir. Üst pozisyon listesi seçilen departmanın **ve üst departmanlarının** pozisyonları + tüm kök pozisyonlardır (`JobPositionFullValues`) | -| Seviye — yeni kayıt | `IsDefault = true` (tek varsayılan zorlanmaz) | -| Kullanıcı — İş Bilgileri | Departman değişince pozisyon temizlenir, pozisyon listesi departmana göre süzülür; deneme süresi sonu işe girişten önce ya da 4 aydan sonra olamaz (`PlatformIdentityAppService`) | -| Şema — Departman modu | Her departman kartında o departmanın **en üst pozisyonu** ve yalnızca o pozisyondaki kullanıcılar gösterilir (üst pozisyonu olmayan ya da üstü başka departmanda olan; ada göre ilk) | -| Şema — Pozisyon modu | Her pozisyon bir kart; o pozisyondaki tüm kullanıcılar | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`: - -| Yetki | Üst | Alt yetkiler | -| --- | --- | --- | -| `App.Hr.SkillType` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import, Note | -| `App.Hr.SkillLevel`, `App.Hr.Skill` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import | -| `App.Hr.Department`, `App.Hr.JobPosition` | `App.Hr.Definitions` | Create, Update, Delete, Export, Import | -| `App.Hr.OrgChart` | grup kökü | — (menü ve rota bu yetkiyi ister) | - -Çalışanın iş bilgileri ve yetkinlikleri kullanıcı ekranının yetkileriyle (`AbpIdentity.Users.*`) düzenlenir. -Hiçbir yetki role otomatik atanmaz. - ---- - -## 7. Entegrasyonlar (kim kullanıyor) - -| Tanım | Kullanan modüller | -| --- | --- | -| Departman / Pozisyon | İşe Alım (talep, ilan, teklif), Eğitim katılımcısı, Disiplin dosyası, Sağlık Kartı listesi, Performans değerlendirmesi, kullanıcı ekranı, Organizasyon Şeması | -| Yetenek / Seviye | Aday yetkinlikleri, eğitimin kazandırdıkları, Performans yetkinlik değerlendirmesi (seviye `Progress` = puan), kullanıcı dil ve yetkinlik listeleri | -| `Adm_T_UserSkill` | Performans Yönetimi tamamlanınca yönetici seviyesini buraya yazar (bkz. `HrPerformance.md`) | -| Vardiya (`ShiftId`) | Bkz. `HrWorkCalendar.md` | - ---- - -## 8. Akış örneği - -1. İK **Departmanlar**'a "Kalite" departmanını şube Merkez, üst departman Üretim olarak ekler (ağaçta Üretim'in altında görünür). -2. **Pozisyonlar**'a "Kalite Şefi"ni departman Kalite, üst pozisyon Üretim Müdürü olarak ekler. -3. Kullanıcı detayının **İş Bilgileri** sekmesinde çalışanın departmanı Kalite, pozisyonu Kalite Şefi, işe giriş tarihi ve vardiyası girilir; **Eğitim ve Yetkinlik** sekmesine İngilizce B2 ve "Kaynak Uzmanı 4/5" eklenir. -4. **Organizasyon Şeması** Pozisyon modunda Kalite Şefi kartı Üretim Müdürü'nün altında, çalışanla birlikte görünür; şema JPG olarak dışa aktarılır. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Departman yöneticisi nerede?** Yok; hiyerarşi pozisyon ağacındadır. (Performans modülü bu yüzden yöneticiyi değerlendirme kaydında tutar.) - -**Şemada departman kartında neden tüm çalışanlar yok?** Departman modunda yalnız en üst pozisyondakiler gösterilir; herkes için Pozisyon modunu kullanın. - -**Şemadaki kart yerleri kaydedilmiyor.** Sürükleme yalnız görünümü değiştirir. - -**Teknik yetenekler için seviye seçilemiyor.** Seed'de Technical Skills tipine seviye tanımlı değil; kullanıcı yetkinliği 1–5 ölçeğiyle girilir. Performans modülünde bu tipe seviye eklenmesi gerekir. - -**"Languages" tipinin adını değiştirdim, dil listesi boşaldı.** Lookup'lar tip adını sabit kullanır (`TenantLanguageSkillValues`, `TechnicalSkillsValues`). - -Kontrol edilmeli (koddan tespit edilen tutarsızlıklar): -- Organizasyon Şeması API'si (`api/app/org-chart`) yalnız oturum ister, `App.Hr.OrgChart` yetkisini denetlemez; menü ve rota yetkiyle korunur. -- `BranchDepartmentValues` ve `JobPositionFullValues` lookup'larında açık kiracı koşulu yoktur; `JobPositionFullValues` departmandan bağımsız tüm kök pozisyonları da listeler. -- Yetenek alt formunun popup başlığı Seviye ekranının anahtarını kullanır (`ListFormSeeder_Hr.cs`). -- Yetenek Tipi/Seviye/Yetenek yetkileri `MultiTenancySide 2`, Departman/Pozisyon `3`'tür. -- Bir tipte birden çok varsayılan seviye işaretlenebilir. - ---- - -## 10. Dosyalar - -| Dosya | İçerik | -| --- | --- | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Hr.cs` | Beş ekranın ListForm tanımı | -| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Hr/Definitions/*.cs` | Entity'ler | -| `api/src/Sozsoft.Platform.Application/OrgChart/OrgChartAppService.cs`, `Application.Contracts/OrgChart/OrgChartDto.cs` | Şema API'si (`GET departments`, `GET job-positions`) | -| `ui/src/views/admin/hr/OrgChart.tsx`, `ui/src/services/orgChart.service.ts` | Şema sayfası | -| `ui/src/views/admin/user-management/Details.tsx`, `EducationSkillsTab.tsx` | Kullanıcı iş bilgileri ve yetkinlik sekmeleri | -| `api/src/Sozsoft.Platform.Application.Contracts/LookUpQueryValues.cs` | Şube/departman/pozisyon/yetenek lookup'ları | -| `configs/seeds/data/App.Hr.{Department,JobPosition,SkillType,Skill,SkillLevel}.json` | Seed | -| `configs/seeds/data/App.Menus.Routes.json` (`admin.hr.organization`) | Şema rotası | - -Bu tablolar migration'lıdır; ekranlar seeder'dan kurulduğu için Wizard Manager'dan silinmez. diff --git a/configs/seeds/docs/modules/HrPerformance.md b/configs/seeds/docs/modules/HrPerformance.md deleted file mode 100644 index 278c6dea..00000000 --- a/configs/seeds/docs/modules/HrPerformance.md +++ /dev/null @@ -1,1061 +0,0 @@ - -# İK › Performans Yönetimi (`App.Hr.Performance`) - -Dönem bazlı performans süreci: İK dönemi açar, çalışan hedeflerini ve öz değerlendirmesini yapar, -yönetici değerlendirir, isteğe bağlı 360 derece geri bildirim toplanır, İK kalibre eder, sonuç -gelişim planına ve çalışanın yetkinlik profiline yansır. **İnsan Kaynakları menüsü İK -departmanınındır** (şartları belirler, değerlendirmeleri takip eder ve girer); çalışan ve yönetici -kendisiyle ilgili her şeyi **Intranet › Dashboard**'daki widget'lardan takip eder. Tamamı konfigürasyondur (Wizard + Custom -Component + SQL nesneleri); yeni entity, migration ya da React kodu yoktur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK | Dönem ve yetkinlik seti tanımlar, tüm değerlendirmeleri izler, 360 değerlendiricisi atar, kalibre eder, gelişim planlarını izler | Dönemler · Tüm Değerlendirmeler · Kalibrasyon · Gelişim Planları · Performans Dereceleri | -| Çalışan | Hedeflerini girer, gerçekleşeni ve öz değerlendirmesini yazar, yöneticiye gönderir, gelişim aksiyonlarının ilerlemesini günceller | Intranet panosu: **Performansım** widget'ı → Değerlendirmelerim · Gelişim Planım · Profil › Performansım (Değerlendirmelerim · Hedeflerim · Gelişim Planım · 360 Taleplerim salt okunur) | -| Yönetici | Hedefleri onaylar, yetkinlik seviyesini ve yorumunu verir, kalibrasyona gönderir, gelişim aksiyonu planlar | Intranet panosu: **Ekibimin Performansı** widget'ı → Ekibimin Değerlendirmeleri | -| 360 değerlendiricisi | Kendisine atanan çalışanın yetkinliklerini puanlar ve gönderir | Intranet panosu: **360 Taleplerim** widget'ı → 360 Taleplerim | - -Kapsam: kiracı (`IsTenant`). Şube/birim kırılımı yoktur. - ---- - -## 2. Analiz ve kararlar - -### 2.1 Talep - -> İnsan Kaynakları › Performans Yönetimi: değerlendirme dönemi tanımı, hedefler (KPI/OKR, ağırlık %, -> gerçekleşme), yetkinlik değerlendirmesi (Skill Types üzerinden), öz değerlendirme + yönetici -> değerlendirmesi, isteğe bağlı 360 derece, kalibrasyon ekranı, gelişim planı; uygulamanın diğer -> özellikleriyle entegre. - -### 2.2 Depodan okunanlar (sorulmadı) - -- Çalışan = `AbpUsers` (`DepartmentId`, `JobPositionId` taşır). -- Yetkinlik zinciri `Hr_T_SkillType → Hr_T_Skill → Hr_T_SkillLevel` (`Progress` 0–100); çalışan profili `Adm_T_UserSkill` (`Level` 1–5). -- Kök menü `App.Hr`, izin grubu `App.Hr`, modül `Hr`; tanımlar `App.Hr.Definitions` altında. -- **Yönetici ilişkisi ne `AbpUsers`'ta ne `Hr_T_Department`'ta vardır** — bu yüzden sorudur. - -### 2.3 Keşif turu cevapları - -| # | Soru | Seçilen | Gerekçe | -| --- | --- | --- | --- | -| 1 | Ekran yapısı | Wizard ekranları + çalışana ait özet (Custom Component) | Liste/form kalıbına sığan her şey Wizard; özet ilk sürümde İK menüsünde "Performansım" panosuydu, §2.4'teki kararla Intranet widget'larına taşındı | -| 2 | Yönetici nereden gelir | Değerlendirme kaydında seçilir (`ManagerId`, `AbpUsers` lookup) | Platform tablosu şeması değişmez (çerçeve içi) | -| 3 | Genel puan formülü | Dönemde ağırlık tanımlı: Genel = Hedef puanı × a + Yetkinlik puanı × b | Dönem bazında değiştirilebilir (varsayılan 60/40) | -| 4 | Akış | Durum alanıyla, onaysız (WorkflowDto yok) | Geçiş kuralları prosedürde | -| 5 | Yetkinlik ölçeği | `SkillLevel` + `Progress %`; tamamlanınca `UserSkill`'e yazılır | Skill Types'ın kendi seviyeleri kullanılır, profil güncel kalır | -| 6 | Hedef gerçekleşme | Yönlü, %150 tavanlı | Artan/Azalan hedef ayrımı, aşım ödüllendirilir ama sınırlıdır | -| 7 | 360 | Dönem bayrağı, bilgi amaçlı | Ortalama gösterilir, genel puana girmez | -| 8 | Görünürlük | Rol + kullanıcı süzmesi | İK hepsini, diğerleri kendi/ekibinin kaydını görür | - -### 2.4 Onaylanan tariften sapmalar (üretimde verilen kararlar) - -| Tarifte | Üretilen | Neden | -| --- | --- | --- | -| Gelişim planında Gantt | **Scheduler** (takvim) + Todo | Gantt `ParentIdExpr` ister; aksiyonlar arasında hiyerarşi yok | -| Derece ölçeği "Performans › Tanımlar" | **İK › Tanımlar** (`App.Hr.Definitions`) | İK tanımlarının (aday kaynağı, değerlendirme kriteri…) mevcut yeri | -| Dönem ekranında "Değerlendirmeler" sekmesi | Yalnız **Yetkinlik Seti** sekmesi | Widget'lı menü ekranı alt form olamaz (standing default 13); değerlendirmeler Tüm Değerlendirmeler'de döneme göre süzülür | -| Persona alt formları | Hedef/yetkinlik/gelişim için İK, çalışan, yönetici olmak üzere **üçer ayrı menüsüz ekran** | Alan kilidi ve satır süzmesi ekran bazındadır | -| Todo kart başlığı | `EmployeeName` kolonu eklendi (prosedür doldurur) | Todo başlığı metin kolon ister (İşe Alım'daki `CandidateName` kalıbı) | -| Eğitim entegrasyonu | Plan eğitime katılımcı **yazmaz**; çalışan eğitime "Katıldı" işlenmişse plan kendiliğinden tamamlanır | `Hr_T_TrainingParticipant.AttendanceStatus` "planlandı" değeri taşımıyor | -| "Performansım" panosu ve persona listeleri İK › Performans Yönetimi menüsünde | Persona listeleri **menüsüz**; özetleri Intranet › Dashboard'da üç ayrı widget (Performansım, Ekibimin Performansı, 360 Taleplerim), widget'taki bağlantı listeyi açar | İK menüsü İK departmanınındır; çalışan kendisiyle ilgili bilgiyi Intranet'ten takip eder (kullanıcı kararı, 2026-10-04). Widget içeriği özet + bağlantıdır; pano kolonları dar olduğu için liste gömülmez | - -### 2.5 Varsayılan kalanlar - -- Derece ölçeği (host seed'i): 1 Beklentinin Çok Altında 0–50 (%5) · 2 Geliştirilmeli 50–70 (%15) · 3 Beklenen Düzeyde 70–90 (%60) · 4 Beklentinin Üstünde 90–110 (%15) · 5 Olağanüstü 110+ (%5). Alt sınır dahil, üst sınır hariç. -- Ağırlık toplamı 100 değilse kayıt engellenmez; yalnızca hedef belirleme aşamasından çıkış engellenir. -- Bildirim kanalları: `UiActivity` + `UiToast`. - ---- - -## 3. Menü ve ekranlar - -### 3.1 İK menüsü - -`İnsan Kaynakları › Performans Yönetimi` (`App.Hr.Performance`, ikon `FcBullish`) — yalnız İK. - -| Sıra | Menü (TR / EN) | `ListFormCode` | Wizard dosyası | Alt formlar | Görünümler | -| --- | --- | --- | --- | --- | --- | -| 1 | Değerlendirme Dönemleri / Review Periods | `App.Hr.PerformancePeriod` | `PerformancePeriod.json` | `PerformancePeriodSkill` | Grid, Card, Pivot, Chart | -| 2 | Tüm Değerlendirmeler / All Reviews | `App.Hr.PerformanceReview` | `PerformanceReview.json` | `PerformanceGoal`, `PerformanceCompetency`, `PerformanceFeedback` (→ `PerformanceFeedbackScore`), `ReviewDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | -| 3 | Kalibrasyon / Calibration | `App.Hr.PerformanceCalibration` | `PerformanceCalibration.json` | — | Grid, Card, Pivot, Chart | -| 4 | Gelişim Planları / Development Plans | `App.Hr.DevelopmentPlan` | `DevelopmentPlan.json` | — | Grid, Card, Pivot, Chart, Todo, Scheduler | -| — | Performans Dereceleri (İK › Tanımlar) | `App.Hr.PerformanceRating` | `PerformanceRating.json` | — | Grid, Card, Pivot, Chart; veri `data/App.Hr.PerformanceRating.json` ile aynalı | - -Widget şeritleri: - -| Ekran | Kartlar | -| --- | --- | -| Dönemler | Toplam · Aktif · Kalibrasyonda · Kapanan | -| Tüm Değerlendirmeler | Toplam · Hedef/Öz Değerlendirme · Yönetici Değerlendirmesinde · Kalibrasyonda · Tamamlanan | -| Kalibrasyon | Kalibrasyonda · Tamamlanan · Ortalama Puan · Ortalama Kalibre Puan | -| Gelişim Planları | Toplam · Açık Aksiyon · Geciken · Tamamlanan | - -### 3.2 Çalışana ait ekranlar (menüsüz) - -Menüde yer almazlar; Intranet panosundaki widget'tan `/admin/list/{ListFormCode}` adresiyle açılırlar. -Menüsüz wizard olduklarından widget şeritleri yoktur (deploy menüsüz ekranın `Widgets`'ını düşürür); -özetleri panodaki widget'tadır. - -| Ekran (TR / EN) | `ListFormCode` | Wizard dosyası | Satır süzmesi | Alt formlar | Görünümler | -| --- | --- | --- | --- | --- | --- | -| Değerlendirmelerim / My Reviews | `App.Hr.MyPerformanceReview` | `MyPerformanceReview.json` | `EmployeeId = @USERID` | `MyPerformanceGoal`, `MyPerformanceCompetency`, `MyDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | -| Ekibimin Değerlendirmeleri / Team Reviews | `App.Hr.TeamPerformanceReview` | `TeamPerformanceReview.json` | `ManagerId = @USERID` | `TeamPerformanceGoal`, `TeamPerformanceCompetency`, `TeamDevelopmentPlan` | Grid, Card, Pivot, Chart, Todo | -| 360 Taleplerim / My 360 Requests | `App.Hr.My360Feedback` | `My360Feedback.json` | `ReviewerId = @USERID` | `My360FeedbackScore` | Grid, Card, Pivot, Chart | -| Gelişim Planım / My Development Plan | `App.Hr.MyDevelopmentPlan` | `MyDevelopmentPlan.json` | `EmployeeId = @USERID` | — (Değerlendirmelerim'in sekmesi; widget'tan tek liste olarak da açılır) | Grid | - -### 3.3 Intranet › Dashboard widget'ları - -`Sas_T_IntranetWidget` kayıtları (`data/App.DeveloperKit.IntranetWidgets.json`, `SourceType: 1` = -Custom) üç custom component'i sağ kolona (`Column: 2`) yerleştirir. Widget'ı yalnız `PermissionName` -yetkisi olan kullanıcı alır (sunucu süzer, `IntranetAppService.GetWidgetsAsync`); kullanıcı panoda -yerini değiştirebilir, gizleyebilir. - -| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Açtığı liste | -| --- | --- | --- | --- | --- | -| `my-performance` · 70 | `MyPerformanceWidget` | `App.Hr.MyPerformanceReview` | Aktif (tamamlanmamış) değerlendirmenin aşaması ve hedef/yetkinlik/genel puanı; tamamlanan sayısı ve ortalama puanı; `App.Hr.MyDevelopmentPlan` yetkisi varsa açık ve geciken gelişim aksiyonu | Değerlendirmelerim, Gelişim Planım | -| `team-performance` · 80 | `TeamPerformanceWidget` | `App.Hr.TeamPerformanceReview` | Değerlendirmemi bekleyen (`ManagerReview`), hedef/öz değerlendirmede, tamamlanan, toplam; bekleyen ilk 5 çalışanın adı | Ekibimin Değerlendirmeleri | -| `my-360-feedback` · 90 | `My360FeedbackWidget` | `App.Hr.My360Feedback` | Bekleyen ve gönderilen 360 talebi | 360 Taleplerim | - -Bileşenler code modundadır ve rotasızdır (`RoutePath: null`). Veriyi ekranın kendi sorgusundan okur -(`GET /api/app/list-form-select/select?listFormCode=…`): satır süzmesi (`DefaultFilter`), kiracı ve -liste yetkisi ListForm'da kalır, bileşen yalnızca sayar — ayrı endpoint ya da SQL yoktur. Başlıklar -`App.DashboardWidget.{MyPerformance,TeamPerformance,My360Feedback}`, boş durum ve aktif değerlendirme -metinleri `App.DashboardWidget.Performance.*`; kart etiketleri İK şeritlerindeki -`App.Hr.Performance.Widget.*` anahtarlarıdır. - ---- - -## 4. Veri modeli - -Hepsi `sql/object/Hr_T_*.sql`; kiracı + tam audit + `IsActive`, `Guid` anahtar. - -``` -Hr_T_PerformancePeriod ──< Hr_T_PerformancePeriodSkill >── Hr_T_Skill - │ - └──< Hr_T_PerformanceReview >── AbpUsers (EmployeeId, ManagerId) - │ └── Hr_T_PerformanceRating (RatingId) - ├──< Hr_T_PerformanceGoal - ├──< Hr_T_PerformanceCompetency >── Hr_T_Skill / Hr_T_SkillLevel ×3 - ├──< Hr_T_PerformanceFeedback ──< Hr_T_PerformanceFeedbackScore >── Hr_T_SkillLevel - └──< Hr_T_DevelopmentPlan >── Hr_T_Skill / Hr_T_Training / Hr_T_Certificate / AbpUsers (Mentor) -``` - -| Tablo | Önemli kolonlar | Tekillik / kural | -| --- | --- | --- | -| `Hr_T_PerformanceRating` | `Level`, `Name`, `MinScore`, `MaxScore`, `Color`, `TargetDistribution` | `(TenantId, Level)` tekil; `MinScore < MaxScore` | -| `Hr_T_PerformancePeriod` | `StartDate`, `EndDate`, `SelfReviewDueDate`, `ManagerReviewDueDate`, `GoalWeight`, `CompetencyWeight`, `Is360Enabled`, `Status` | Ağırlık toplamı = 100 (CHECK); `Status` ∈ Planned, Active, Calibration, Closed | -| `Hr_T_PerformancePeriodSkill` | `PeriodId`, `SkillId`, `ExpectedLevelId` | `(PeriodId, SkillId)` tekil | -| `Hr_T_PerformanceReview` | `PeriodId`, `EmployeeId`, `EmployeeName`, `ManagerId`, `DepartmentId`, `JobPositionId`, `Status`, `LastStatus`, `GoalScore`, `CompetencyScore`, `Feedback360Score`, `OverallScore`, `CalibratedScore`, `RatingId`, yorumlar, gönderim tarihleri | `(PeriodId, EmployeeId)` tekil; `Status` ∈ GoalSetting, SelfReview, ManagerReview, Calibration, Completed; `CalibratedScore` 0–150 | -| `Hr_T_PerformanceGoal` | `GoalType` (KPI/OKR), `Title`, `Direction` (Increasing/Decreasing), `Unit`, `TargetValue`, `ActualValue`, `Weight`, `AchievementRate` | `TargetValue > 0`, `0 < Weight ≤ 100` | -| `Hr_T_PerformanceCompetency` | `SkillId`, `ExpectedLevelId`, `SelfLevelId`, `ManagerLevelId`, `Score` | `(ReviewId, SkillId)` tekil | -| `Hr_T_PerformanceFeedback` | `ReviewerId`, `Relation` (Peer/Subordinate/Superior/InternalCustomer), `Status` (Pending/Submitted), `Score`, `Comment`, `SubmittedDate` | `(ReviewId, ReviewerId)` tekil | -| `Hr_T_PerformanceFeedbackScore` | `FeedbackId`, `SkillId`, `LevelId`, `Comment` | `(FeedbackId, SkillId)` tekil | -| `Hr_T_DevelopmentPlan` | `EmployeeId`, `ReviewId`, `SkillId`, `Title`, `ActionType`, `TrainingId`, `CertificateId`, `MentorId`, `StartDate`, `DueDate`, `Status`, `Progress` | `ActionType` ∈ Training, Mentoring, Project, Reading, Certificate, Other; `Status` ∈ Planned, InProgress, Completed, Cancelled; `Progress` 0–100 | - -Seviye listeleri (`ExpectedLevelId`, `SelfLevelId`, `ManagerLevelId`, `LevelId`) seçilen yetkinliğin -`SkillTypeId`'sine göre süzülür (lookup cascade `SkillId` → `@param0`). - ---- - -## 5. İş kuralları ve hesaplar - -### 5.1 Formüller (`Hr_S_PerformanceReviewRecalc`) - -| Değer | Formül | -| --- | --- | -| Hedef gerçekleşme % | Artan: `Gerçekleşen / Hedef × 100` · Azalan: `Hedef / Gerçekleşen × 100` (gerçekleşen ≤ 0 ise 150) · sonuç **0–150** aralığına kırpılır · gerçekleşen boşsa boş | -| Hedef puanı | `Σ(Gerçekleşme% × Ağırlık) / 100` (gerçekleşmesi boş hedef 0 sayılır; hedef yoksa boş) | -| Yetkinlik satır puanı | Yönetici seviyesinin `Hr_T_SkillLevel.Progress` değeri | -| Yetkinlik puanı | Puanı dolu yetkinlik satırlarının ortalaması | -| 360 satır puanı | Değerlendiricinin verdiği seviyelerin `Progress` ortalaması | -| 360 ortalaması | `Status = Submitted` geri bildirimlerin ortalaması — **genel puana girmez** | -| Genel puan | `(Hedef puanı × GoalWeight + Yetkinlik puanı × CompetencyWeight) / 100` (eksik bileşen 0; ikisi de boşsa boş) | -| Derece | `COALESCE(KalibrePuan, GenelPuan)` değerinin düştüğü aralık (`MinScore ≤ x < MaxScore`, aynı kiracının aktif dereceleri) | - -Formda gerçekleşme % anlık önizlenir (`ActualValue`/`TargetValue`/`Direction` alanlarının -`EditorScript`'i); kalıcı değer her kayıtta prosedürle yeniden hesaplanır. Dönemde ağırlık -alanlarından biri değişince diğeri `100 - x` olur (`EditorScript`). - -### 5.2 Durum akışı (`Hr_S_PerformanceReviewAfterSave`) - -``` -GoalSetting ──(Yönetici)──▶ SelfReview ──(Çalışan)──▶ ManagerReview ──(Yönetici)──▶ Calibration ──(İK)──▶ Completed - ▲ ◀──(Yönetici iade)──┘ ◀──(Yönetici iade)──┘ -``` - -| Aktör (ekran) | İzinli geçişler | -| --- | --- | -| İK (Tüm Değerlendirmeler, Kalibrasyon) | Her geçiş | -| Çalışan (Değerlendirmelerim) | SelfReview → ManagerReview | -| Yönetici (Ekibimin Değerlendirmeleri) | GoalSetting → SelfReview · SelfReview → GoalSetting · ManagerReview → SelfReview · ManagerReview → Calibration | - -- **GoalSetting'ten çıkış** için en az bir hedef olmalı ve ağırlık toplamı tam **100** olmalıdır (her aktör için). -- İzinsiz geçiş hata vermez, **kayıt sonrası durum `LastStatus`'a geri alınır** (kayıt yenilenince eski aşama görünür). -- Geçiş damgaları: → ManagerReview `SelfSubmittedDate`, → Calibration `ManagerSubmittedDate`, → Completed `CompletedDate`. -- → **Completed**: yönetici seviyeleri `Adm_T_UserSkill`'e yazılır (`Level = ⌈Progress / 20⌉`, 1–5; var olan kayıt güncellenir, `Note = "Performans: {Dönem}"`). -- Her kayıtta: `EmployeeName`/`DepartmentId`/`JobPositionId` çalışandan tamamlanır, dönemin eksik yetkinlikleri eklenir, puanlar yeniden hesaplanır. -- Todo panosunda kartı sürüklemek de aynı kuraldan geçer. - -### 5.3 Satır ve aşama güvenliği (`Hr_S_PerformanceGuard`, before-command) - -Persona ekranları satırı `DefaultFilter` ile süzer; kayıt uçları satırı yalnızca `Id` ile -güncellediği için aynı kural yazma tarafında prosedürle uygulanır. Kural dışı istek -`THROW 51000–51005` ile reddedilir. - -| Aktör | Sahiplik | Değerlendirme kaydı | Hedef / Yetkinlik | Gelişim planı | 360 | -| --- | --- | --- | --- | --- | --- | -| Çalışan | `EmployeeId = kullanıcı` | GoalSetting, SelfReview | GoalSetting, SelfReview | Her aşama (yalnız ilerleme/not) | — | -| Yönetici | `ManagerId = kullanıcı` | GoalSetting, SelfReview, ManagerReview | aynı | Her aşama | — | -| Değerlendirici | `Feedback.ReviewerId = kullanıcı` | — | — | — | GoalSetting → ManagerReview arası | -| İK | — | Serbest | Serbest | Serbest | Serbest | - -Dönem `Closed` ise İK dışındaki her yazma reddedilir. "Gelişim Planım" guard prosedüründen değil, -yalnızca satırın `EmployeeId`'sini denetleyen komuttan geçer (`THROW 51020`); aksiyon dönemden -bağımsız olabildiği için kapalı dönemde de ilerleme güncellenebilir. - -**Alan kilidi:** persona ekranında çalışanın/yöneticinin değiştirmemesi gereken alanlar salt -okunur çizilir **ve** yazma yetkisi İK ekranının `.Create`/`.Update` yetkisine bağlanır; -sunucu, kullanıcının yetkisi olmayan alanı güncelleme isteğinden düşürür (`ListFormFieldManager.CanUpdate`). - -| Ekran | Düzenlenebilir alanlar | -| --- | --- | -| Değerlendirmelerim | `Status`, `SelfComment` | -| Hedeflerim | Yönetici yorumu ve gerçekleşme % dışında hepsi | -| Yetkinliklerim | `SelfLevelId`, `SelfComment` (ekleme/silme yok) | -| Gelişim Planım | `Status`, `Progress`, `EmployeeNote` (ekleme/silme yok) | -| Ekibimin Değerlendirmeleri | `Status`, `ManagerComment` | -| Ekip Hedefleri | Öz yorum ve gerçekleşme % dışında hepsi | -| Ekip Yetkinlikleri | Öz seviye ve öz yorum dışında hepsi (ekleme/silme var) | -| Ekip Gelişim Planı | Çalışan notu dışında hepsi | -| 360 Taleplerim | `Status`, `Comment`; puan satırlarında `LevelId`, `Comment` | -| Kalibrasyon | `Status`, `CalibratedScore`, `CalibrationNote` | - -### 5.4 Kancalar - -| Ekran | Komut | Ne çalışır | -| --- | --- | --- | -| Dönemler | Insert/UpdateAfter | `Hr_S_PerformancePeriodActivate` — dönem **Active** ise kiracının aktif her kullanıcısına değerlendirme açar (var olana dokunmaz), dönemin yetkinlik setini eksik değerlendirmelere kopyalar, yeni açılanlara bildirim gönderir | -| Yetkinlik Seti | Insert/UpdateAfter | Aynı prosedür (sonradan eklenen yetkinlik açık değerlendirmelere eklenir) | -| Değerlendirme ekranları | InsertAfter / UpdateAfter | `Hr_S_PerformanceReviewAfterSave @rid, @kullanıcı, N'Hr' \| 'Employee' \| 'Manager'` | -| Persona ekranları | Insert/Update/DeleteBefore | `Hr_S_PerformanceGuard` | -| Hedef / Yetkinlik / 360 ekranları | After | `Hr_S_PerformanceReviewRecalc` | -| 360 (İK) | InsertBefore | Dönemde 360 kapalıysa ya da değerlendirici çalışanın kendisiyse reddeder | -| 360 (İK) | InsertAfter | `Hr_S_PerformanceFeedbackOpen` — değerlendirmenin yetkinlikleri için puan satırlarını açar, değerlendiriciye bildirim gönderir | -| 360 ekranları | UpdateAfter | `Status = Submitted` iken `SubmittedDate` damgalanır, puan yeniden hesaplanır | -| Gelişim planı ekranları | Insert/UpdateAfter | `Hr_S_DevelopmentPlanSync` — eğitime "Katıldı" işlenen ya da `Completed` aksiyonu %100 ve Tamamlandı yapar | - -Güncelleme komutunda `@Id` bir dizidir (`IN @Id` ile açılır); aktör `UpdateFieldsDefaultValue` -ile yazılan `@LastModifierId`'den okunur. Ekleme komutunda `@Id` tekildir, aktör `@CreatorId`'dir. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Her ekranın kök yetkisi + `.Create/.Update/.Delete/.Export/.Import/.Note` -Menüsüz alt formların yetkisi ana ekranın altındadır; menüsüz persona ekranlarının -(Değerlendirmelerim, Ekibimin Değerlendirmeleri, 360 Taleplerim) yetkisi menü dalı olmadığından -`App.Hr` grubunun kökündedir (deploy menüsüz ekranı böyle yazar). -**Hiçbir yetki role otomatik atanmaz** — rol ekranından verilir. - -Önerilen dağıtım: - -| Rol | Verilecek yetkiler | -| --- | --- | -| Tüm çalışanlar | `App.Hr.MyPerformanceReview` (+ `.Update`), `App.Hr.MyPerformanceGoal` (+ `.Create/.Update/.Delete`), `App.Hr.MyPerformanceCompetency` (+ `.Update`), `App.Hr.MyDevelopmentPlan` (+ `.Update`), `App.Hr.My360Feedback` (+ `.Update`), `App.Hr.My360FeedbackScore` (+ `.Update`) | -| Yöneticiler | Yukarıdakiler + `App.Hr.TeamPerformanceReview` (+ `.Update`), `App.Hr.TeamPerformanceGoal`, `App.Hr.TeamPerformanceCompetency`, `App.Hr.TeamDevelopmentPlan` (+ `.Create/.Update/.Delete`) | -| İK | `App.Hr.Performance` dalının tamamı + `App.Hr.PerformanceRating` | - -Persona ekranlarındaki kilitli alanlar İK ekranının yetkisine bağlı olduğundan, çalışan/yönetici -rolüne **İK ekranlarının `.Update`/`.Create` yetkisi verilmez**; verilirse persona ekranlarında -kilitli alanlar o kullanıcı için yazılabilir hâle gelir. - -Intranet widget'ı listenin okuma yetkisiyle görünür: Performansım `App.Hr.MyPerformanceReview`, -Ekibimin Performansı `App.Hr.TeamPerformanceReview`, 360 Taleplerim `App.Hr.My360Feedback`. Ayrı -widget yetkisi yoktur — listeyi açamayan kullanıcıya özet de gösterilmez. - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `AbpUsers` | Çalışan, yönetici, değerlendirici, mentor; departman/pozisyon kopyası | -| Kullanıcı detayı › Performans | Değerlendirmeler ve Gelişim Planları ekranları çalışana süzülmüş açılır (`HrPersonnel.md`) | -| `Hr_T_Department`, `Hr_T_JobPosition` | Değerlendirmenin organizasyon kırılımı (Pivot/Chart) | -| `Hr_T_SkillType` / `Hr_T_Skill` / `Hr_T_SkillLevel` | Dönem yetkinlik seti, beklenen/öz/yönetici/360 seviyeleri, puan (`Progress`) | -| `Adm_T_UserSkill` | Tamamlanan değerlendirmenin yönetici seviyeleri kullanıcı profiline yazılır | -| `Hr_T_Training` / `Hr_T_TrainingParticipant` | Gelişim aksiyonu bir eğitime bağlanır; katılım "Katıldı" ise aksiyon tamamlanır | -| `Hr_T_Certificate` | Sertifika aksiyonları | -| Bildirimler | Tipler `PerformansDurumDegisti`, `Performans360Talebi`; kurallar `Custom` + `UiActivity`/`UiToast` (yalnız kanalı belirler). Metinler `App.Hr.Performance.Notification.{Status,Feedback}.{Subject,Message}` (TR), yer tutucular `[Employee]`, `[Period]`, `[Status]`. Yazan: `Hr_S_PerformanceNotify` | - -Bildirim alıcıları: → GoalSetting / SelfReview / Completed çalışana; → ManagerReview / Completed -yöneticiye; dönem aktivasyonunda yeni açılan her değerlendirmenin çalışanına; 360 eklenince -değerlendiriciye. - ---- - -## 8. Akış örneği - -1. İK **Yetkinlik Seti**'ni hazırlar (ör. İletişim → beklenen B2), **Dönemler**'de "2026 Yıl Sonu"nu - 60/40 ağırlık ve 360 açık olarak girer, durumu **Aktif** yapar → tüm aktif çalışanlara - değerlendirme açılır, yetkinlikler kopyalanır, çalışanlar bildirim alır. -2. İK **Tüm Değerlendirmeler**'de her kaydın **Yönetici**'sini seçer. -3. Çalışan Intranet panosundaki **Performansım** widget'ından **Değerlendirmelerim**'i açar, - **Hedeflerim**'de hedeflerini girer (ağırlık toplamı 100). -4. Yönetici **Ekibimin Performansı** widget'ından **Ekibimin Değerlendirmeleri**'ni açar, hedefleri gözden geçirir, durumu **Öz Değerlendirme** - yapar → çalışan bildirim alır. -5. Çalışan gerçekleşenleri, öz seviyelerini ve yorumunu girer, durumu **Yönetici Değerlendirmesi** - yapar → yönetici bildirim alır. -6. İK 360 sekmesinde değerlendirici ekler → değerlendiriciler panodaki **360 Taleplerim** widget'ından talebi açıp puanlayıp gönderir. -7. Yönetici seviyeleri ve yorumu girer, gelişim aksiyonu planlar (ör. "İleri Excel" eğitimi), - durumu **Kalibrasyon** yapar. -8. İK **Kalibrasyon**'da dağılımı (Chart/Pivot, derece × departman) hedef dağılımla karşılaştırır, - gerekenlerin **Kalibre Puan**ını girer, durumu **Tamamlandı** yapar → derece kesinleşir, - yetkinlikler `UserSkill`'e yazılır, çalışan ve yönetici bildirim alır. -9. Çalışan eğitime "Katıldı" işlendiğinde gelişim aksiyonu bir sonraki kayıtta kendiliğinden tamamlanır. - ---- - -## 9. Sık sorulanlar - -**Durumu değiştirdim ama kayıt eski aşamaya döndü.** O geçiş sizin rolünüze açık değil (§5.2) ya da -hedef belirlemeden çıkarken ağırlık toplamı 100 değil. Geçersiz geçiş hata vermez, geri alınır. - -**"Değerlendirme bu aşamada bu işlem için açık değil" hatası.** Guard tablosu (§5.3): çalışan -yönetici değerlendirmesi başladıktan sonra hedef/yetkinlik değiştiremez; kalibrasyon ve sonrası -yalnız İK'dadır; dönem kapalıysa yalnız İK yazar. - -**Genel puan neden hedef puanından düşük/yüksek?** Genel = (Hedef × GoalWeight + Yetkinlik × -CompetencyWeight) / 100. Yetkinlik puanı yalnızca yönetici seviyesinden gelir; öz seviye ve 360 -puana girmez. - -**Gerçekleşme %150'de kalıyor.** Tavan bilinçlidir (§2.3, karar 6). - -**Derece boş.** Kiracıda derece ölçeği tanımlı değil. Host seed'i (`data/App.Hr.PerformanceRating.json`) -host içindir; her kiracı İK › Tanımlar › Performans Dereceleri'ni kendisi girer. - -**Teknik yetkinlikte seviye listesi boş.** Seed'de "Technical Skills" tipine seviye tanımlı değildir -(`HrOrganization.md` §9). İK › Tanımlamalar › Yetenek Tipleri › Teknik Yetenekler › Seviyeler'e -`Progress` değerli seviyeler eklenmeden bu yetkinlikler puanlanamaz. - -**Yöneticiyi kim belirliyor?** İK, değerlendirme kaydındaki `ManagerId` alanından. Platformda -kullanıcı/departman üzerinde yönetici ilişkisi yoktur (§2.2). - -**Yeni işe giren çalışana değerlendirme nasıl açılır?** Aktif dönem kaydını yeniden kaydetmek -eksik değerlendirmeleri açar; ya da İK Tüm Değerlendirmeler'den elle ekler. - -**360 puanı neden genel puanda yok?** Karar 7: bilgi amaçlıdır; `Feedback360Score` olarak gösterilir. - -**Bildirim gelmiyor.** Kiracıda `PerformansDurumDegisti` / `Performans360Talebi` tipi ve `Custom` -kuralları olmalı; yeni kiracıya host seed'inden kopyalanır, mevcut kiracıda Administration › -Bildirimler'den eklenir. - -**Değerlendirmelerim / Ekibimin Değerlendirmeleri menüde yok.** Bilinçli: İK menüsü İK içindir (§2.4). -Çalışan ve yönetici Intranet › Dashboard'daki widget'tan açar. Widget görünmüyorsa rolüne liste -yetkisi verilmemiştir (§6) ya da kullanıcı widget'ı panoda gizlemiştir (tasarım modundan geri açılır). - -**Çalışan kendi gelişim aksiyonunu ekleyemiyor.** "Gelişim Planım" ekleme kapalıdır; aksiyonu -yönetici (Ekip Gelişim Planı) ya da İK açar. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_Performance{Rating,Period,PeriodSkill,Review,Goal,Competency,Feedback,FeedbackScore}.sql`, `Hr_T_DevelopmentPlan.sql` | Tablolar, CHECK ve tekil indeksler | -| `configs/seeds/sql/object/Hr_S_Performance{Notify,ReviewRecalc,PeriodActivate,Guard,ReviewAfterSave,FeedbackOpen}.sql`, `Hr_S_DevelopmentPlanSync.sql` | Prosedürler | -| `configs/seeds/wizard/{PerformanceRating,PerformancePeriodSkill,PerformancePeriod,PerformanceGoal,PerformanceCompetency,PerformanceFeedbackScore,PerformanceFeedback,ReviewDevelopmentPlan,PerformanceReview,MyPerformanceGoal,MyPerformanceCompetency,MyDevelopmentPlan,MyPerformanceReview,TeamPerformanceGoal,TeamPerformanceCompetency,TeamDevelopmentPlan,TeamPerformanceReview,My360FeedbackScore,My360Feedback,PerformanceCalibration,DevelopmentPlan}.json` | 21 wizard (List) | -| `configs/seeds/data/App.DeveloperKit.CustomComponents/{b2d9fa60-b052-5039-a0fc-146f4e5b2e8c,98a5c0b9-c8d6-5e83-ae76-d9ccb5b70cba,d669129d-52fe-56e1-972d-d20fe1b3360e}.json` | `MyPerformanceWidget`, `TeamPerformanceWidget`, `My360FeedbackWidget` (code modu, rotasız) | -| `configs/seeds/data/App.DeveloperKit.IntranetWidgets.json` | `my-performance`, `team-performance`, `my-360-feedback` pano kayıtları | -| `configs/seeds/data/App.Hr.PerformanceRating.json` | 5 kademeli derece ölçeği | -| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları (wizard'lara ait) | -| `configs/seeds/data/App.Notifications.Notification{Types,Rules}.json` | 2 tip, 4 kural | -| `ui/safelist.txt` | Widget bileşenlerinin Tailwind sınıfları (`twSafelistGenerator` derlemede yeniler) | - -Kurulum: DB Migrate (tablolar/prosedürler `sql/object`, ekranlar `WizardDataSeeder`, satırlar -`ListFormSeedDataApplier`). Ardından rollere yetki verilir (§6). - -Geri alma: Wizard Manager'dan talebin wizard'ları silinir (alt formlar önce); tabloyu düşürmek -yalnızca onayda seçilirse olur. Widget bileşenleri ve pano kayıtları, bildirim tip/kural satırları, derece seed'i ve -`Hr_S_*` prosedürleri elle kaldırılır. `Adm_T_UserSkill`'e yazılmış seviyeler kullanıcı verisidir, -geri alınmaz. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Değerlendirme Dönemleri — `App.Hr.PerformancePeriod` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformancePeriod.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Performance` › `App.Hr.PerformancePeriod` (sıra 1) | -| Yetki | `App.Hr.PerformancePeriod` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Değerlendirme Dönemleri — performans değerlendirmesinin yapıldığı dönem (ör. 2026 Yıl Sonu), puan ağırlıkları ve 360 derece ayarı. | -| Kaynak | `Hr_T_PerformancePeriod` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.PerformancePeriodSkill` (Id → PeriodId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.ActivePeriod`, `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.ClosedPeriod` | -| Komutlar | InsertAfter: `Hr_S_PerformancePeriodActivate` · UpdateAfter: `Hr_S_PerformancePeriodActivate` | -| Form varsayılanları | Status=Planned, GoalWeight=60, CompetencyWeight=40, Is360Enabled=false, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Ad | dxTextBox | ✓ | ✓ | | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Planned, Active, Calibration, Closed | -| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | | -| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | | -| `SelfReviewDueDate` | Öz Değerlendirme Son Tarihi | dxDateBox | | ✓ | | -| `ManagerReviewDueDate` | Yönetici Değerlendirmesi Son Tarihi | dxDateBox | | ✓ | | -| `GoalWeight` | Hedef Ağırlığı % | dxNumberBox | ✓ | ✓ | script | -| `CompetencyWeight` | Yetkinlik Ağırlığı % | dxNumberBox | ✓ | ✓ | script | -| `Is360Enabled` | 360 Derece Açık | dxCheckBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `Description` | Açıklama | dxTextBox | | ✓ | | - -### Tüm Değerlendirmeler — `App.Hr.PerformanceReview` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceReview.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Performance` › `App.Hr.PerformanceReview` (sıra 2) | -| Yetki | `App.Hr.PerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir. | -| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.PerformanceGoal` (Id → ReviewId), `App.Hr.PerformanceCompetency` (Id → ReviewId), `App.Hr.PerformanceFeedback` (Id → ReviewId), `App.Hr.ReviewDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.InGoalOrSelf`, `App.Hr.Performance.Widget.ManagerReview`, `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.Completed` | -| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | -| Komutlar | InsertAfter: `Hr_S_PerformanceReviewAfterSave` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | -| Form varsayılanları | Status=GoalSetting, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `EmployeeName` | Çalışan Adı | dxTextBox | | | | -| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | -| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | -| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | -| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | -| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | -| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | -| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | -| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | -| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | -| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | - -### Kalibrasyon — `App.Hr.PerformanceCalibration` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceCalibration.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Performance` › `App.Hr.PerformanceCalibration` (sıra 3) | -| Yetki | `App.Hr.PerformanceCalibration` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Kalibrasyon — yöneticilerin gönderdiği değerlendirmelerin İK tarafından birlikte gözden geçirilip puanların dengelenmesi. | -| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "Status" IN ('Calibration', 'Completed')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Performance.Widget.Calibration`, `App.Hr.Performance.Widget.Completed`, `App.Hr.Performance.Widget.AverageScore`, `App.Hr.Performance.Widget.AverageCalibrated` | -| Komutlar | UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | -| Form varsayılanları | Status=GoalSetting, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `EmployeeName` | Çalışan Adı | dxTextBox | | | | -| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | -| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | -| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | -| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | -| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | -| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | -| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | -| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | -| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | -| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | - -### Gelişim Planları — `App.Hr.DevelopmentPlan` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DevelopmentPlan.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Performance` › `App.Hr.DevelopmentPlan` (sıra 4) | -| Yetki | `App.Hr.DevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Gelişim Planları — bütün çalışanların gelişim aksiyonları; yetkinlik, eğitim ve sertifikalarla bağlantılı. | -| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Scheduler, Todo (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Hr.Performance.Widget.Open`, `App.Hr.Performance.Widget.Overdue`, `App.Hr.Performance.Widget.Completed` | -| Todo | başlık `Title`, durum `Status` (Planned,InProgress,Completed,Cancelled) | -| Komutlar | InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateAfter: `Hr_S_DevelopmentPlanSync` | -| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `ReviewId` | Değerlendirme | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceReview | -| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | -| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | -| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | -| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | -| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | -| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | -| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | -| `Progress` | İlerleme % | dxNumberBox | | ✓ | | -| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Performans Dereceleri — `App.Hr.PerformanceRating` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceRating.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.PerformanceRating` (sıra 16) | -| Yetki | `App.Hr.PerformanceRating` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Performans Dereceleri — genel performans puanının hangi dereceye karşılık geldiğini ve kalibrasyonda hedeflenen dağılımı tanımlayan ölçek. | -| Kaynak | `Hr_T_PerformanceRating` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Form varsayılanları | IsActive=true | -| Veri aynası | `data/App.Hr.PerformanceRating.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Level` | Seviye | dxNumberBox | ✓ | ✓ | | -| `Name` | Ad | dxTextBox | ✓ | ✓ | | -| `MinScore` | Alt Puan | dxNumberBox | ✓ | ✓ | | -| `MaxScore` | Üst Puan (hariç) | dxNumberBox | ✓ | ✓ | | -| `TargetDistribution` | Hedef Dağılım % | dxNumberBox | | ✓ | | -| `Color` | Renk | dxColorBox | | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Yetkinlik Seti — `App.Hr.PerformancePeriodSkill` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformancePeriodSkill.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.PerformancePeriodSkill` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yetkinlik Seti — dönemde her çalışanın değerlendirileceği yetkinlikler ve beklenen seviyeleri. | -| Kaynak | `Hr_T_PerformancePeriodSkill` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_PerformancePeriodActivate` · UpdateAfter: `Hr_S_PerformancePeriodActivate` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodId` | Dönem | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Hedefler — `App.Hr.PerformanceGoal` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceGoal.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.PerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Hedefler — değerlendirmenin ağırlıklı KPI / OKR hedefleri ve gerçekleşmeleri (İK görünümü). | -| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | -| `Title` | Hedef | dxTextBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | -| `Unit` | Birim | dxTextBox | | ✓ | | -| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | -| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | -| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | -| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Yetkinlikler — `App.Hr.PerformanceCompetency` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceCompetency.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.PerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yetkinlikler — değerlendirmede yetkinliklerin beklenen, öz ve yönetici seviyeleri (İK görünümü). | -| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `Score` | Puan | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | - -### 360 Puanları — `App.Hr.PerformanceFeedbackScore` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceFeedbackScore.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.PerformanceFeedbackScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | 360 Puanları — 360 derece değerlendiricisinin yetkinlik bazında verdiği seviyeler (İK görünümü). | -| Kaynak | `Hr_T_PerformanceFeedbackScore` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `FeedbackId` | Geri Bildirim | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `LevelId` | Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `Comment` | Yorum | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### 360 Derece — `App.Hr.PerformanceFeedback` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/PerformanceFeedback.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.PerformanceFeedback` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | 360 Derece — değerlendirmeye atanan 360 derece değerlendiriciler (akran, ast, üst, iç müşteri). | -| Kaynak | `Hr_T_PerformanceFeedback` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.PerformanceFeedbackScore` (Id → FeedbackId) | -| Komutlar | InsertBefore: SQL · InsertAfter: `Hr_S_PerformanceFeedbackOpen`, `Hr_S_PerformanceReviewRecalc` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | Relation=Peer, Status=Pending, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxSelectBox | | | sorgu: Hr_T_PerformanceReview | -| `ReviewerId` | Değerlendirici | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `Relation` | İlişki | dxSelectBox | ✓ | ✓ | liste: Peer, Subordinate, Superior, InternalCustomer | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Pending, Submitted | -| `Score` | Puan | dxNumberBox | | ✓ | | -| `SubmittedDate` | Gönderim Tarihi | dxDateBox | | ✓ | | -| `Comment` | Yorum | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Gelişim Planı — `App.Hr.ReviewDevelopmentPlan` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/ReviewDevelopmentPlan.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.ReviewDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Gelişim Planı — değerlendirmeden çıkan gelişim aksiyonları (İK görünümü). | -| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateAfter: `Hr_S_DevelopmentPlanSync` | -| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxTextBox | | | | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | -| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | -| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | -| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | -| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | -| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | -| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | -| `Progress` | İlerleme % | dxNumberBox | | ✓ | | -| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Hedeflerim — `App.Hr.MyPerformanceGoal` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyPerformanceGoal.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyPerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Hedeflerim — çalışanın kendi değerlendirmesindeki hedefler. | -| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "EmployeeId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | -| `Title` | Hedef | dxTextBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | -| `Unit` | Birim | dxTextBox | | ✓ | | -| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | -| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | -| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | -| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Yetkinliklerim — `App.Hr.MyPerformanceCompetency` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyPerformanceCompetency.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyPerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yetkinliklerim — çalışanın yetkinlik öz değerlendirmesi. | -| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "EmployeeId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `Score` | Puan | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | - -### Gelişim Planım — `App.Hr.MyDevelopmentPlan` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyDevelopmentPlan.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Gelişim Planım — çalışanın kendi gelişim aksiyonları. | -| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Komutlar | UpdateBefore: SQL · UpdateAfter: `Hr_S_DevelopmentPlanSync` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxTextBox | | | | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | -| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | -| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | -| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | -| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | -| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | -| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | -| `Progress` | İlerleme % | dxNumberBox | | ✓ | | -| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Değerlendirmelerim — `App.Hr.MyPerformanceReview` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/MyPerformanceReview.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.MyPerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Değerlendirmelerim — oturum açan çalışanın kendi performans değerlendirmeleri. | -| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.MyPerformanceGoal` (Id → ReviewId), `App.Hr.MyPerformanceCompetency` (Id → ReviewId), `App.Hr.MyDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | -| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | -| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | -| Form varsayılanları | Status=GoalSetting, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `EmployeeName` | Çalışan Adı | dxTextBox | | | | -| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | -| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | -| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | -| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | -| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | -| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | -| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | -| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | -| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | -| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | - -### Ekip Hedefleri — `App.Hr.TeamPerformanceGoal` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TeamPerformanceGoal.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TeamPerformanceGoal` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ekip Hedefleri — yöneticinin, ekibindeki çalışanın hedefleri üzerindeki görünümü. | -| Kaynak | `Hr_T_PerformanceGoal` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | GoalType=KPI, Direction=Increasing, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `GoalType` | Tür | dxRadioGroup | ✓ | ✓ | liste: KPI, OKR | -| `Title` | Hedef | dxTextBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `Direction` | Yön | dxSelectBox | ✓ | ✓ | liste: Increasing, Decreasing · script | -| `Unit` | Birim | dxTextBox | | ✓ | | -| `TargetValue` | Hedef Değer | dxNumberBox | ✓ | ✓ | script | -| `Weight` | Ağırlık % | dxNumberBox | ✓ | ✓ | | -| `ActualValue` | Gerçekleşen | dxNumberBox | | ✓ | script | -| `AchievementRate` | Gerçekleşme % | dxNumberBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Ekip Yetkinlikleri — `App.Hr.TeamPerformanceCompetency` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TeamPerformanceCompetency.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TeamPerformanceCompetency` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ekip Yetkinlikleri — yöneticinin yetkinlik değerlendirmesi; yönetici seviyesi yetkinlik puanını belirler. | -| Kaynak | `Hr_T_PerformanceCompetency` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_PerformanceReviewRecalc` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` · DeleteBefore: `Hr_S_PerformanceGuard` · DeleteAfter: `Hr_S_PerformanceReviewRecalc` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `ExpectedLevelId` | Beklenen Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `SelfLevelId` | Öz Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `ManagerLevelId` | Yönetici Seviyesi | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `Score` | Puan | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `SelfComment` | Öz Yorum | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | - -### Ekip Gelişim Planı — `App.Hr.TeamDevelopmentPlan` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TeamDevelopmentPlan.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TeamDevelopmentPlan` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ekip Gelişim Planı — yöneticinin ekibindeki çalışan için planladığı gelişim aksiyonları. | -| Kaynak | `Hr_T_DevelopmentPlan` · filtre `"IsDeleted" = 'false' AND "ReviewId" IN (SELECT "Id" FROM "Hr_T_PerformanceReview" WHERE "ManagerId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertBefore: `Hr_S_PerformanceGuard` · InsertAfter: `Hr_S_DevelopmentPlanSync` · UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_DevelopmentPlanSync` · DeleteBefore: `Hr_S_PerformanceGuard` | -| Form varsayılanları | ActionType=Training, Status=Planned, Progress=0, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `EmployeeId` | Çalışan | dxTextBox | | | | -| `ReviewId` | Değerlendirme | dxTextBox | | | | -| `Title` | Aksiyon | dxTextBox | ✓ | ✓ | | -| `ActionType` | Aksiyon Türü | dxSelectBox | ✓ | ✓ | liste: Training, Mentoring, Project, Reading, Certificate, Other | -| `SkillId` | Yetkinlik | dxSelectBox | | ✓ | sorgu: Hr_T_Skill | -| `TrainingId` | Eğitim | dxSelectBox | | ✓ | sorgu: Hr_T_Training | -| `CertificateId` | Sertifika | dxSelectBox | | ✓ | sorgu: Hr_T_Certificate | -| `MentorId` | Mentor | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | | -| `DueDate` | Bitiş Tarihi | dxDateBox | | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, InProgress, Completed, Cancelled | -| `Progress` | İlerleme % | dxNumberBox | | ✓ | | -| `EmployeeNote` | Çalışan Notu | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Ekibimin Değerlendirmeleri — `App.Hr.TeamPerformanceReview` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TeamPerformanceReview.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TeamPerformanceReview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ekibimin Değerlendirmeleri — kullanıcının yönetici olarak atandığı çalışanların değerlendirmeleri. | -| Kaynak | `Hr_T_PerformanceReview` · filtre `"IsDeleted" = 'false' AND "ManagerId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.TeamPerformanceGoal` (Id → ReviewId), `App.Hr.TeamPerformanceCompetency` (Id → ReviewId), `App.Hr.TeamDevelopmentPlan` (Id → ReviewId, EmployeeId → EmployeeId) | -| Todo | başlık `EmployeeName`, durum `Status` (GoalSetting,SelfReview,ManagerReview,Calibration,Completed) | -| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewAfterSave` | -| Form varsayılanları | Status=GoalSetting, IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PeriodId` | Dönem | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_PerformancePeriod | -| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `EmployeeName` | Çalışan Adı | dxTextBox | | | | -| `ManagerId` | Yönetici | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Pozisyon | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: GoalSetting, SelfReview, ManagerReview, Calibration, Completed | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `GoalScore` | Hedef Puanı | dxNumberBox | | ✓ | | -| `CompetencyScore` | Yetkinlik Puanı | dxNumberBox | | ✓ | | -| `Feedback360Score` | 360 Ortalaması | dxNumberBox | | ✓ | | -| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | -| `CalibratedScore` | Kalibre Puan | dxNumberBox | | ✓ | | -| `RatingId` | Derece | dxSelectBox | | ✓ | sorgu: Hr_T_PerformanceRating | -| `SelfComment` | Öz Değerlendirme Yorumu | dxTextArea | | ✓ | | -| `ManagerComment` | Yönetici Yorumu | dxTextArea | | ✓ | | -| `CalibrationNote` | Kalibrasyon Notu | dxTextArea | | ✓ | | -| `SelfSubmittedDate` | Öz Değerlendirme Gönderimi | dxDateBox | | ✓ | | -| `ManagerSubmittedDate` | Yönetici Değerlendirmesi Gönderimi | dxDateBox | | ✓ | | -| `CompletedDate` | Tamamlanma | dxDateBox | | ✓ | | - -### Yetkinlik Puanları — `App.Hr.My360FeedbackScore` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/My360FeedbackScore.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.My360FeedbackScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Yetkinlik Puanları — 360 değerlendiricisinin kendi talebinde her yetkinliğe verdiği seviye. | -| Kaynak | `Hr_T_PerformanceFeedbackScore` · filtre `"IsDeleted" = 'false' AND "FeedbackId" IN (SELECT "Id" FROM "Hr_T_PerformanceFeedback" WHERE "ReviewerId" = '@USERID')` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `FeedbackId` | Geri Bildirim | dxTextBox | | | | -| `SkillId` | Yetkinlik | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Skill | -| `LevelId` | Seviye | dxSelectBox | | ✓ | sorgu: Hr_T_SkillLevel (← SkillId) | -| `Comment` | Yorum | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### 360 Taleplerim — `App.Hr.My360Feedback` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/My360Feedback.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.My360Feedback` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | 360 Taleplerim — kullanıcıya değerlendirici olarak atanan 360 derece değerlendirme talepleri. | -| Kaynak | `Hr_T_PerformanceFeedback` · filtre `"IsDeleted" = 'false' AND "ReviewerId" = '@USERID'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✗ · düzenle ✓ · sil ✗ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.My360FeedbackScore` (Id → FeedbackId) | -| Komutlar | UpdateBefore: `Hr_S_PerformanceGuard` · UpdateAfter: `Hr_S_PerformanceReviewRecalc` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ReviewId` | Değerlendirme | dxSelectBox | | | sorgu: Hr_T_PerformanceReview | -| `ReviewerId` | Değerlendirici | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `Relation` | İlişki | dxSelectBox | ✓ | ✓ | liste: Peer, Subordinate, Superior, InternalCustomer | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Pending, Submitted | -| `Score` | Puan | dxNumberBox | | ✓ | | -| `SubmittedDate` | Gönderim Tarihi | dxDateBox | | ✓ | | -| `Comment` | Yorum | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrPersonnel.md b/configs/seeds/docs/modules/HrPersonnel.md deleted file mode 100644 index 60b8757c..00000000 --- a/configs/seeds/docs/modules/HrPersonnel.md +++ /dev/null @@ -1,186 +0,0 @@ -# İK › Personel Kaydı (Kimlik › Kullanıcılar › detay) - -Çalışanın özlük kaydı ayrı bir İK ekranında değil, kullanıcı detay sayfasındadır -(`/admin/users/detail/:userId`): iletişim ve ek bilgiler, askerlik, engellilik, nüfus/kimlik, doğum ve -aile, yabancı uyruklu belgeleri, organizasyon (departman/pozisyon/vardiya), sözleşme ve deneme süresi, -işten çıkış, sürücü belgesi, eğitim geçmişi, yabancı diller, yetenekler, yeterlilik belgeleri, eş ve -çocuklar, acil durum kişileri, banka ve ücret bilgileri, yan haklar, iş deneyimi. (Sağlık Kartı sekmesi -için bkz. [HrHealthCard.md](HrHealthCard.md).) Tek değerli alanlar `AbpUsers` genişletme kolonlarında, -çok kayıtlılar `Adm_T_User*` tablolarındadır; diğer İK modüllerinin hepsi çalışanı buradan okur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK / özlük | Personelin bütün özlük, sözleşme, eğitim, aile ve mali bilgisini girer | Kimlik › Kullanıcılar › Detay | -| Sistem yöneticisi | Kullanıcıyı açar; listede temel alanları (departman, pozisyon, cinsiyet, adres…) düzenler | Kimlik › Kullanıcılar | -| Yönetici | Deneme süresi bitimine 15 gün kala bildirim alır | Bildirimler | - -Kapsam: kiracı. Rota yetkisi `AbpIdentity.Users.Update`. - ---- - -## 2. Analiz ve kararlar - -> §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar koddan (`Details.tsx` ve sekme -> bileşenleri, `PlatformIdentityAppService`, `ListFormSeeder_Administration.cs`, entity'ler) okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yer | Ayrı "personel" tablosu yok; özlük = kullanıcı. Tek değerli alanlar ABP extra property olarak `AbpUsers` kolonları | -| Çok kayıtlı bilgiler | `Adm_T_User{WorkExperience,Education,Language,Skill,Certificate,FamilyMember,EmergencyContact,Benefit}`; detay sekmelerinde gömülü liste (`App.IdentityManagement.*`), yeni satırın `UserId`'si sayfa filtresinden dolar | -| Kaydetme | Her form sekmesi kendi formuyla bütün modeli `PUT /api/app/platform-identity/user` (`UpdateUserAsync`) ile gönderir; başka sekmede kaydedilmemiş değişiklik gitmez | -| Mali bilgiler | Ayrı DTO ve uç (`GetFinancialAsync` / `UpdateFinancialAsync`, `Users.Update` yetkisi) — intranet listelerine akan `UserInfoViewModel`'de taşınmasın diye | -| Deneme süresi | İşe giriş ile işe giriş + **4 ay** arasında olmalı (4857 s. İK md. 15; toplu sözleşmeyle 4 ay) — hem formda hem sunucuda | -| Koşullu alanlar | Tecil bitişi yalnız "Tecilli"de, sözleşme bitişi yalnız "Belirli Süreli"de, yabancı uyruklu bölümü yalnız TR dışı uyrukta, engellilik oranı/raporu yalnız "Engelli"de **görünür**; gizlenince değer silinmez | -| Ölçekler | Dil seviyesi `Hr_T_SkillLevel` ile, diğer yetenekler sabit 1–5 ile (bkz. [HrOrganization.md](HrOrganization.md)) | -| Saklama biçimleri | Engellilik raporu ve avatar dışındaki dosyalar base64 kolonda; ehliyet sınıfları `|` ile birleştirilmiş metin; medeni durum ve eğitim düzeyi Türkçe anahtar | - ---- - -## 3. Ekranlar ve sekmeler - -| Sekme (TR) | İçerik | Kayıt | -| --- | --- | --- | -| Genel | İletişim (e-posta, ikinci e-posta, ad, soyad, telefon, ikinci telefon, kullanıcı tipi İç/Dış), ek bilgiler (ev adresi, uyruk, cinsiyet), askerlik (durum: Yapıldı/Muaf/Tecilli/Yapılmadı + tecil bitişi), avatar (kırpma, ≤ 2 MB), engellilik (engelli, oran %, rapor PDF/JPG/PNG ≤ 5 MB) | `UpdateUserAsync` (+ avatar `UpdateAvatarAsync`) | -| Kimlik Bilgileri | Nüfus cüzdanı (kimlik no, seri no, veriliş yeri/tarihi, il, ilçe, köy, cilt, aile sıra, sıra no), doğum ve aile (doğum yeri/tarihi, baba/anne adı, medeni durum Bekar/Evli/Boşanmış/Dul, evlenme tarihi), yabancı uyruklu (pasaport no/geçerlilik, çalışma izni no/bitiş) | `UpdateUserAsync` | -| İş | Organizasyon (departman → pozisyon, sicil no, SGK no, vardiya grubu, PDKS kart no — sicil/kart no ve vardiya puantajın kişi eşlemesi ve vardiyasıdır, `HrAttendance.md`), sözleşme (çalışma şekli Tam/Yarı Zamanlı, sözleşme türü Belirsiz/Belirli, işe başlama, sözleşme bitişi, deneme süresi bitişi, kıdem başlangıcı), işten çıkış (tarih, SGK çıkış kodu, açıklama), sürücü belgesi (sınıflar çoklu M…G, no, veriliş, geçerlilik), iletişim kanalları (Rocket, Telegram) + **Daha Önce Çalıştığı Yerler** listesi | `UpdateUserAsync` + `App.IdentityManagement.UserWorkExperience` | -| Eğitim ve Yetenekler | En yüksek eğitim seviyesi + **Eğitim Geçmişi**, **Yabancı Diller**, **Yetenekler**, **Yeterlilik Belgeleri** listeleri | `UpdateUserAsync` + 4 liste | -| Aile / Acil Durum | **Eş ve Çocuklar**, **Acil Durum Kişileri** listeleri | 2 liste | -| Finansal | Banka adı, IBAN; ücret tipi Aylık/Günlük/Saatlik, brüt ücret, para birimi + **Yan Haklar** listesi | `UpdateFinancialAsync` + `App.IdentityManagement.UserBenefit` | -| Sağlık Kartı | Bkz. [HrHealthCard.md](HrHealthCard.md) | — | -| Puantaj | Yılın puantaj kartları + Aylık Puantaj, Günlük Puantaj, Günlük Hareketler listeleri; bkz. [HrAttendance.md](HrAttendance.md) §3.4 | — | -| Eğitimler | Çalışanın eğitim katılımları (`App.Hr.TrainingParticipant`, `UserId` süzgeci); bkz. [HrTrainings.md](HrTrainings.md) | — | -| Performans | Değerlendirmeler (`App.Hr.PerformanceReview`) ve gelişim planları (`App.Hr.DevelopmentPlan`), `EmployeeId` süzgeci; bkz. [HrPerformance.md](HrPerformance.md) | — | -| Disiplin | Disiplin dosyaları (`App.Hr.DisciplinaryCase`, `UserId` süzgeci); bkz. [HrDisciplinaryCase.md](HrDisciplinaryCase.md) | — | - -Gömülü listeler (hepsi menüsüz alt liste, `Adm_T_*`): - -| Liste | Alanlar | Kural | -| --- | --- | --- | -| `UserWorkExperience` | Firma*, iş kolu* (sektör), giriş*, çıkış, yaptığı iş (HTML) | Giriş tarihine göre azalan | -| `UserEducation` | Eğitim düzeyi* (İlkokul…Doktora), okul*, bölüm, başlangıç, mezuniyet, mezun (varsayılan evet) | — | -| `UserLanguage` | Dil* ("Languages" tipi yetenekler), seviye (dilin seviyeleri), not | Kullanıcı × dil tekil | -| `UserSkill` | Yetenek* (dil dışı tipler), seviye* 1–5 (Başlangıç…Uzman, varsayılan 3), not | `CHECK 1–5`; kullanıcı × yetenek tekil | -| `UserCertificate` | Belge* (`Hr_T_Certificate`), belge no, veren kurum, düzenleme, son kullanma, not | Son kullanmaya göre artan | -| `UserFamilyMember` | Yakınlık* (Eş/Çocuk), ad*, soyad, TC kimlik, doğum tarihi, çalışma durumu (Çalışıyor/Çalışmıyor/Öğrenci/Emekli), sigorta kapsamında, yan hak kapsamında | — | -| `UserEmergencyContact` | Ad soyad*, yakınlık* (Eş, Anne/Baba, Kardeş, Çocuk, Akraba, Arkadaş, Diğer), telefon* | — | -| `UserBenefit` | Yan hak türü* (`Hr_T_BenefitType`, **kod** saklanır), tutar, başlangıç, bitiş, not | — | - -Kullanıcı listesi (`AbpIdentity.Users`) popup'ında düzenlenen İK alanları: departman*, pozisyon*, -cinsiyet, ev adresi (+ avatar, e-posta, ad, soyad, tip, telefon, çalışma saati). Diğer özlük alanları -listede gizli kolon olarak durur. - ---- - -## 4. Veri modeli - -| Yer | İçerik | -| --- | --- | -| `AbpUsers` genişletme kolonları | Bütün form sekmesi alanları; sabitler `PlatformConsts.AbpIdentity.User.*`, erişim `AbpIdentityUserExtensions`, kolon tipleri `PlatformEfCoreEntityExtensionMappings` | -| `Adm_T_UserWorkExperience` | `CompanyName`, `SectorId` (FK Sector), `StartDate`, `EndDate`, `JobDescription` | -| `Adm_T_UserEducation` | `EducationLevel`, `SchoolName`, `Department`, `StartDate`, `EndDate`, `IsGraduated` | -| `Adm_T_UserLanguage` | `SkillId` (FK Skill), `SkillLevelId` (FK SkillLevel), `Note` | -| `Adm_T_UserSkill` | `SkillId`, `Level` (1–5), `Note` | -| `Adm_T_UserCertificate` | `CertificateId` (`Hr_T_Certificate`, FK'siz), `CertificateNo`, `IssuedBy`, `IssueDate`, `ExpiryDate`, `Note` | -| `Adm_T_UserFamilyMember` | `Relationship`, `Name`, `Surname`, `IdentityNumber`, `BirthDate`, `EmploymentStatus`, `IsInsuranceCovered`, `IsBenefitCovered` | -| `Adm_T_UserEmergencyContact` | `Name`, `Relationship`, `PhoneNumber` | -| `Adm_T_UserBenefit` | `BenefitType` (kod), `Amount`, `StartDate`, `EndDate`, `Note` | - -Entity'ler `Entities/Tenant/Administration/User*.cs` (`FullAuditedEntity, IMultiTenant`), EF -yapılandırması `PlatformDbContext.cs`. - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Deneme süresi | `HireDate ≤ ProbationEndDate ≤ HireDate + 4 ay`; formda gün bazında, sunucuda (`UpdateUserAsync`) tam zamanla | -| Departman değişimi | Pozisyon temizlenir; pozisyon listesi departmana göre süzülür | -| IBAN | Formda boşluk silinir, büyük harfe çevrilir, `^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$` deseni; sunucu yalnız normalleştirir | -| Engellilik raporu | ≤ 5 MB (yalnız formda), base64 olarak kolonda | -| Avatar | `{userId}.jpg` avatar blob kabına yazılır; boş gönderim siler | -| Deneme süresi hatırlatması | `ProbationReminderWorker` günlük çalışır; aktif, çıkışı olmayan ve deneme bitişi **bugün + 15 gün** olan kullanıcılar için `DenemeSuresiBitiyor` bildirimi üretir (tip yoksa atlar) | -| Doğum günü | `BirthDate` intranet panosundaki "Bugün Doğanlar" kutusunu besler (bkz. [HrIntranet.md](HrIntranet.md)) | - ---- - -## 6. Yetki ve görünürlük - -| İşlem | Yetki | -| --- | --- | -| Detay sayfası (rota), liste "Detay" butonu | `AbpIdentity.Users.Update` | -| Gömülü listeler | okuma `AbpIdentity.Users`; ekle/güncelle/sil `AbpIdentity.Users.Update` (Yan Haklar alanlarında ekleme `Users.Create`) | -| Mali bilgiler, avatar | `AbpIdentity.Users.Update` (sunucuda) | -| Kullanıcı listesi ekle/güncelle | `Users.Create` / `Users.Update` | - -Özlük verisi kişisel veri, sağlık ve engellilik verisi özel nitelikli kişisel veridir (KVKK). Kullanıcı -yönetimi yetkisi yalnız İK ve sistem yöneticilerinde olmalıdır. - -**Kontrol edilmeli — güvenlik (koddan tespit edildi):** -- `PlatformIdentityAppService.GetByIdAsync` ve `UpdateUserAsync` yalnız oturum ister (`[Authorize]`); `Users.Update` yalnız arayüz rotasında denetlenir. Oturum açmış herhangi bir kullanıcı API'yi doğrudan çağırarak başka birinin özlük kaydını (engellilik raporu dahil) okuyup güncelleyebilir. -- Banka, IBAN ve ücret alanları `AbpIdentity.Users` listesinde gizli ama okunabilir/dışa aktarılabilir kolon olarak durur; liste okuma yetkisi olan kullanıcı kolon seçiciyle görebilir. -- Intranet doğum günü listesine giden `UserInfoViewModel` kimlik no, SGK no ve sağlık kartı alanlarını da taşır. - ---- - -## 7. Entegrasyonlar - -| Kullanan | Okuduğu | -| --- | --- | -| Tüm İK modülleri | Çalışan, departman, pozisyon | -| Organizasyon Şeması | Pozisyondaki kullanıcılar | -| Vardiyalar / Olay Günlüğü | `ShiftId` | -| Yeterlilik Belgeleri, Yan Hak Türleri, Sektörler, SGK çıkış kodları, Para Birimleri | Lookup kaynakları | -| Performans Yönetimi | Tamamlanan değerlendirme `Adm_T_UserSkill`'e yazar | -| İşe Alım | İşe alınan adayın kaydı kullanıcıya `UserId` ile bağlanır | -| Intranet | Doğum günleri, kullanıcı kartları | -| Bildirimler | Deneme süresi hatırlatması (`DenemeSuresiBitiyor`) | - ---- - -## 8. Akış örneği - -1. BT kullanıcıyı listeden açar (ad, e-posta, departman, pozisyon). İK **Detay**'a girer. -2. **Kimlik Bilgileri**: nüfus ve aile bilgileri; **Genel**: adres, uyruk, askerlik, avatar. -3. **İş**: sicil/SGK no, vardiya, sözleşme türü Belirsiz, işe başlama 01.10, deneme süresi bitişi 01.12 (4 ayı aşarsa kayıt reddedilir); önceki iş yerleri listesi. -4. **Eğitim ve Yetenekler**: lisans mezuniyeti, İngilizce B2, "Kaynak Uzmanı 4", forklift belgesi. -5. **Aile / Acil Durum**: eş ve çocuk (sigorta kapsamında), acil durum kişisi. -6. **Finansal**: banka/IBAN, aylık brüt ücret TRY; yemek kartı yan hakkı. -7. 15 Kasım'da yöneticilere deneme süresinin bitmek üzere olduğu bildirimi gider. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Detayda e-postayı değiştirdim, kaydolmadı.** `UpdateUserAsync` e-postayı yazmaz; e-posta kullanıcı listesindeki düzenlemeden değişir. - -**Başka sekmede yaptığım değişiklik kayboldu.** Her sekme ayrı kaydedilir; sekme değiştirmeden önce kaydedin. - -**Sözleşmeyi Belirsiz yaptım, bitiş tarihi hâlâ kayıtlı.** Koşullu alanlar yalnız gizlenir, değer silinmez. - -**Pozisyon listede zorunlu, detayda değil.** Doğru; kullanıcı listesi popup'ı zorunlu tutar. - -**Acil durum kişisinde ad kolonu "Doktor Adı Soyadı" görünüyor.** Alan başlığı yanlış dil anahtarını (`App.Listform.ListformField.FullName`) kullanıyor; düzeltilmeli. - -**Aile üyelerindeki sigorta/yan hak işaretleri bir yere gidiyor mu?** Şu an bunları okuyan bir ekran/rapor bulunmadı. - ---- - -## 10. Dosyalar - -| Dosya | İçerik | -| --- | --- | -| `ui/src/views/admin/user-management/Details.tsx`, `EducationSkillsTab.tsx`, `FamilyEmergencyTab.tsx`, `FinancialTab.tsx`, `userFormFields.tsx`, `useUserFieldLookup.ts` | Detay sayfası ve sekmeler | -| `ui/src/views/admin/user-management/HrRecordsTab.tsx`, `hrRecordTabs.ts` | Eğitimler / Performans / Disiplin sekmeleri: İK ekranları çalışana süzülmüş açılır; sekme, ekranlarından birini görme yetkisi varsa çizilir. Yeni bir İK modülü sekmesi `HR_RECORD_TABS`'a satır eklemekle açılır | -| `api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs` | `GetByIdAsync`, `UpdateUserAsync`, `Get/UpdateFinancialAsync`, `UpdateAvatarAsync` | -| `api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs`, `EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs` | Genişletme alanları | -| `api/src/Sozsoft.Platform.Domain/Entities/Tenant/Administration/User*.cs` | Çok kayıtlı entity'ler | -| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` | `AbpIdentity.Users` ve `App.IdentityManagement.*` listeleri | -| `api/src/Sozsoft.Platform.Domain/BackgroundWorkers/ProbationReminderWorker.cs` | Deneme süresi hatırlatması | diff --git a/configs/seeds/docs/modules/HrRecruitment.md b/configs/seeds/docs/modules/HrRecruitment.md deleted file mode 100644 index 12d3e152..00000000 --- a/configs/seeds/docs/modules/HrRecruitment.md +++ /dev/null @@ -1,573 +0,0 @@ - -# İK › İşe Alım (`App.Hr.Recruitment`) - -Kadro talebinden işe alıma kadar uçtan uca süreç: onaylı kadro talebi → iş ilanı → aday havuzu -(CV, KVKK açık rızası) → başvuru (aşama panosu) → mülakat (takvim, kriter ağırlıklı puan) → -teklif (iç onay, teklif mektubu). Tamamı konfigürasyondur (Wizard + SQL + rapor şablonu); entity, -migration ya da React kodu yoktur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Talep eden yönetici | Kadro talebi açar, onaya gönderir | Kadro Talepleri | -| Onaycı | Kadro talebini ve teklifi onaylar / reddeder | Kadro Talepleri · Teklifler (Grid Workflow butonları) | -| İK / işe alım uzmanı | İlan açar, aday ve başvuruları yönetir, mülakat planlar, teklif hazırlar, aday kaydını personele bağlar | İlanlar · Adaylar · Başvurular · Mülakatlar · Teklifler | -| Mülakatçı | Kendisine atanan mülakatta kriter bazlı puan verir | Mülakatlar (+ bildirim) | -| İK yöneticisi | Aday kaynağı, ret sebebi, değerlendirme kriteri tanımlarını yönetir | İK › Tanımlar | - -Kapsam: kiracı (`IsTenant`). Şube, kayıtta veri olarak tutulur (satır süzmesi yoktur). - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Aşağıdaki kararlar üretilen -> artefaktlardan (wizard, SQL, seed, commit `16fd5df0` "İşe Alım modülü") okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Her adım ayrı Wizard ekranı; ilan ve aday ekranlarında başvuru alt formu, başvuruda mülakat ve teklif alt formu | -| Kadro talebi ve teklif onayı | **Grid Workflow** (`WorkflowDto`): Start → Approval (`Onay Bekliyor`) → Inform → End `Onaylandı` / `Reddedildi`. Onaycı **düğümün `Approver` değeridir** (seed'de platform admin e-postası); motor onaycıyı kayıttaki alandan okumaz — ListForm › Workflow sekmesinden değiştirilir | -| İlan kaynağı | İlan yalnızca **onaylı** (`ApprovalStatus = 'Onaylandı'`) kadro talebinden açılır; şube/departman/pozisyon/adet/çalışma şekli talepten `copy` ile dolar | -| Aday kimliği | E-posta kiracı içinde tekildir (filtreli unique index) | -| KVKK | Açık rıza **zorunlu**: formda zorunlu alan + tabloda `CHECK (KvkkConsent = 1)`; rıza tarihi/yöntemi/imzalı belge saklanır; satır butonu **KVKK Açık Rıza Formu** raporunu açar | -| Başvuru | Aday × ilan çifti tekildir; aşama **Todo (kanban)** panosunda yönetilir | -| Aşama ilerlemesi | Mülakat eklenince `Interview`, teklif eklenince `Offer`, teklif `Accepted` olunca `Hired` — SQL ile, **geri gitmez** | -| Mülakat puanı | Kriter başına 1–5; `OverallScore = Σ(puan × kriter ağırlığı) / Σ ağırlık`; başvurunun `AverageScore`'u mülakatların ortalaması | -| Mülakatçı bildirimi | Mülakat eklenince mülakatçıya `IseAlimMulakatAtandi` bildirimi (kanallar `UiActivity` + `Mail`) | -| Belge numaraları | `KT-YYYY-00001` (talep), `ILN-…` (ilan), `TKL-…` (teklif) — insert sonrası SQL, kiracı + yıl bazında | -| Personele dönüşüm | İş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 (otomatik kullanıcı açılmaz) | -| Kanban başlığı | `CandidateName` / `PostingTitle` başvuruya metin olarak kopyalanır (Todo başlığı metin kolon ister) | - ---- - -## 3. Menü ve ekranlar - -`İnsan Kaynakları › İşe Alım` (`App.Hr.Recruitment`, ikon `FcManager`) - -| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Görünümler | Widget'lar | -| --- | --- | --- | --- | --- | --- | -| 1 | Kadro Talepleri / Staff Requests | `App.Hr.StaffRequest` | — | Grid, Card, Pivot, Chart | Toplam · Onay Bekliyor · Onaylanan · Onaylı kadro adedi (Σ Headcount) | -| 2 | İlanlar / Job Postings | `App.Hr.JobPosting` | `JobApplication` (`Id → JobPostingId`) | Grid, Card, Pivot, Chart | Toplam · Yayında · Taslak · Kapalı | -| 3 | Adaylar / Candidates | `App.Hr.Candidate` | `JobApplication` (`Id → CandidateId`) | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif · Personele Dönüşen | -| 4 | Başvurular / Applications | `App.Hr.JobApplication` | `Interview`, `JobOffer` (`Id → ApplicationId`) | Grid, Card, Pivot, Chart, **Todo** | — (alt form olarak da kullanıldığı için yok) | -| 5 | Mülakatlar / Interviews | `App.Hr.Interview` | `InterviewScore` (`Id → InterviewId`, menüsüz) | Grid, Card, Pivot, Chart, **Scheduler** | — | -| 6 | Teklifler / Job Offers | `App.Hr.JobOffer` | — | Grid, Card, Pivot, Chart | — | - -Tanımlar `İnsan Kaynakları › Tanımlar` (`App.Hr.Definitions`) altında, verileri seed dosyasıyla aynalı: - -| Menü | `ListFormCode` | Seed | -| --- | --- | --- | -| Aday Kaynakları | `App.Hr.CandidateSource` | 7 kayıt: LinkedIn, Kariyer.net, Yenibiris, Şirket Web Sitesi, Referans, Kariyer Fuarı, Doğrudan Başvuru | -| Ret Sebepleri | `App.Hr.RejectionReason` | 8 kayıt; `RejectedBy` = Company / Candidate | -| Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | 6 kayıt (ağırlıklı): İletişim 1, Teknik Yetkinlik 2, Problem Çözme 1.5, Takım Çalışması 1, Motivasyon 1, Kurum Kültürüne Uyum 1 | - -Satır butonları (`DynamicReport`, `Raporlar` kategorisi): - -| Ekran | Buton | Rapor şablonu | Görünürlük | -| --- | --- | --- | --- | -| Adaylar | KVKK Açık Rıza Formu | `475c1ab4-4600-5ef2-a43e-1366ed89b0ed` | Her satır | -| Teklifler | Teklif Mektubu | `80d38666-423d-5e1d-8766-01f2c46be768` | `ApprovalStatus === 'Onaylandı'` | - ---- - -## 4. Veri modeli - -``` -Hr_T_StaffRequest ──< Hr_T_JobPosting ──< Hr_T_JobApplication >── Hr_T_Candidate ──> AbpUsers (UserId, personel) - │ - ├──< Hr_T_Interview ──< Hr_T_InterviewScore >── Hr_T_EvaluationCriterion - └──< Hr_T_JobOffer -``` - -| Tablo | Önemli kolonlar | Kural | -| --- | --- | --- | -| `Hr_T_StaffRequest` | `RequestNo`, `RequestDate`, `RequestedById`, `BranchId` → `DepartmentId` → `JobPositionId` (cascade), `Headcount`, `EmploymentType`, `ExpectedStartDate`, `Reason` (NewPosition/Replacement), `ReplacedUserId`, ücret aralığı + `CurrencyId`, `Qualifications` (HTML), onay alanları | `Reason ≠ Replacement` ise `ReplacedUserId` temizlenir (script) | -| `Hr_T_JobPosting` | `PostingNo`, `StaffRequestId`, `Title`, `Status` (Draft/Published/Closed/Cancelled), şube/departman/pozisyon, `Headcount`, `EmploymentType`, `WorkModel` (Office/Hybrid/Remote), `Location`, `PublishDate`, `ClosingDate`, `SourceIds` (yayın kanalları, çok değerli), açıklama/nitelikler (HTML) | Başlık boşsa pozisyon adı kopyalanır | -| `Hr_T_Candidate` | Kişisel bilgiler, fotoğraf, ülke → şehir, eğitim (`EducationLevel`, okul, bölüm, mezuniyet), deneyim, ücret beklentisi, `SourceId`, `SkillIds` (`Hr_T_Skill`, çok değerli), `CvDocument`, `UserId`, KVKK alanları | `UX (TenantId, Email)`; `CHECK (KvkkConsent = 1)` | -| `Hr_T_JobApplication` | `CandidateId`, `JobPostingId`, `CandidateName`, `PostingTitle`, `ApplicationDate`, `SourceId`, `OwnerUserId`, `AverageScore`, `Stage`, `RejectionReasonId`, `RejectionNote`, `SortOrder` | `UX (TenantId, CandidateId, JobPostingId)`; aşama `Rejected` değilse ret sebebi/notu temizlenir | -| `Hr_T_Interview` | `ApplicationId`, `Title`, `InterviewType` (Phone/Video/FaceToFace/Technical/Hr), `InterviewerUserId`, `StartDate`, `EndDate`, `Location`, `MeetingUrl`, `Status` (Planned/Completed/Cancelled/NoShow), `Recommendation` (Hire/Hold/Reject), `OverallScore` | Bitiş boşsa başlangıç + 1 saat (script) | -| `Hr_T_InterviewScore` | `InterviewId`, `CriterionId`, `Score`, `Comment` | `CHECK (Score BETWEEN 1 AND 5)`; `UX (InterviewId, CriterionId)` | -| `Hr_T_JobOffer` | `OfferNo`, `ApplicationId`, `CandidateName`, `OfferDate`, `ValidUntil`, `StartDate`, `GrossSalary` + `CurrencyId`, `Status` (Draft/Sent/Accepted/Declined/Expired), `ResponseDate`, pozisyon bilgileri, `BenefitCodes` (`Hr_T_BenefitType`), onay alanları | `CHECK (GrossSalary >= 0)`; durum Accepted/Declined olunca yanıt tarihi bugün (script) | - ---- - -## 5. İş kuralları ve hesaplar - -### 5.1 Başvuru aşamaları - -``` -Applied → Screening → Interview → Offer → Hired - └──→ Rejected (her aşamadan, elle) -``` - -| Tetik | Etki (after-command SQL) | -| --- | --- | -| Mülakat eklendi | Başvuru `Applied`/`Screening` ise → `Interview` | -| Teklif eklendi | Başvuru `Applied`/`Screening`/`Interview` ise → `Offer`; teklif zaten `Accepted` ise → `Hired` | -| Teklif güncellendi (`Accepted`) | Başvuru henüz `Hired` değilse → `Hired` | -| Elle | Panodan sürükleme ya da formdan her aşama seçilebilir | - -Otomatik ilerleme yalnızca ileri gider; geri almak elle yapılır. - -### 5.2 Puanlar - -- `Interview.OverallScore = Σ(Score × Criterion.Weight) / Σ Weight` (silinmemiş puanlar). -- `JobApplication.AverageScore = AVG(Interview.OverallScore)` (puanı olan mülakatlar). -- Puan eklenince, güncellenince ya da silinince ikisi de yeniden hesaplanır. - -### 5.3 Metin kopyaları - -`CandidateName`, `PostingTitle` (başvuru), `Title` (mülakat = aday – ilan), `CandidateName` -(teklif) after-command ile yazılır. Aday, ilan ya da başvuru güncellendiğinde **tüm** değişmiş -kopyalar topluca düzeltilir (sorgu `@Id` ile değil fark koşuluyla çalışır). - -### 5.4 Numaratörler - -`KT-`, `ILN-`, `TKL-` + yıl + 5 hane; kiracı ve yıl bazında `MAX + 1`. Numara yalnızca boşsa yazılır. - -### 5.5 Onay akışı (Kadro Talebi, Teklif) - -Grid Workflow; durum `ApprovalStatus`, onaylayan `ApprovalUser`, tarih `ApprovalDate`, açıklama -`ApprovalDescription`. Onay/Ret butonlarını akış kendisi çizer. Onaycı düğümde sabittir -(`system@sozsoft.com` seed değeri) — gerçek onaycı ListForm › Workflow'dan girilmelidir. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Recruitment` ara yetkisinin -altında her ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; `App.Hr.InterviewScore` -mülakat yetkisinin altındadır. Tanımlar `App.Hr.Definitions` altındadır. Satır süzmesi yoktur — -ekran yetkisi olan tüm kayıtları görür. Hiçbir yetki role otomatik atanmaz. - -Önerilen dağıtım: - -| Rol | Yetkiler | -| --- | --- | -| Talep eden yöneticiler | `App.Hr.StaffRequest` (+ `.Create/.Update`) | -| Mülakatçılar | `App.Hr.Interview` (+ `.Update`), `App.Hr.InterviewScore` (+ `.Create/.Update/.Delete`) | -| İşe alım uzmanı | `App.Hr.Recruitment` dalının tamamı + üç tanım ekranı | -| Onaycı | Onaylayacağı ekranın kökü + `.Update` | - -KVKK: aday verisi kişisel veridir; Adaylar ekranının yetkisi yalnızca işe alım ekibine verilmelidir. - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `Sas_T_Branch`, `Hr_T_Department`, `Hr_T_JobPosition` | Şube → departman → pozisyon cascade (talep, ilan, teklif) | -| `Sas_H_Currency` | Ücret para birimi (varsayılan TRY) | -| `Sas_H_Country`, `Sas_H_City` | Aday adresi (ülke → şehir cascade) | -| `Hr_T_Skill` / `Hr_T_SkillType` | Aday yetkinlikleri (`SkillIds`) | -| `Hr_T_BenefitType` | Teklifteki yan haklar (`BenefitCodes`) | -| `AbpUsers` | Talep eden, ayrılan personel, sorumlu, mülakatçı, personele dönüşen aday | -| Bildirimler | Tip `IseAlimMulakatAtandi`; kurallar `Custom` + `UiActivity`/`Mail`; metin `App.Hr.Interview.Notification.{Subject,Message}`, yer tutucular `[Candidate]`, `[Posting]`, `[Date]` | -| Raporlar | KVKK Açık Rıza Formu, Teklif Mektubu (`DynamicReport`) | - ---- - -## 8. Akış örneği - -1. Satış müdürü **Kadro Talepleri**'nde "Satış Temsilcisi, 2 kişi, yeni pozisyon" talebini açar → - `KT-2026-00001`; onaya gönderir, onaycı onaylar → `Onaylandı`. -2. İK **İlanlar**'da talebi seçer; şube/departman/pozisyon/adet dolar, başlık pozisyon adı olur; - yayın kanallarını (LinkedIn, Kariyer.net) seçip durumu **Published** yapar → `ILN-2026-00001`. -3. Gelen adaylar **Adaylar**'a CV ve KVKK rızasıyla girilir; KVKK formu satır butonundan basılır. -4. İlanın **Başvurular** sekmesinden aday eklenir (`Applied`); kanban panosunda **Screening**'e çekilir. -5. Başvurunun **Mülakatlar** sekmesinden teknik mülakat planlanır → başvuru `Interview` olur, - mülakatçıya bildirim gider; mülakatçı kriterleri puanlar → genel ve ortalama puan hesaplanır. -6. **Teklifler**'de teklif hazırlanır → başvuru `Offer`; teklif onaya gider, onaylanınca - **Teklif Mektubu** basılır. -7. Aday kabul eder, teklif **Accepted** yapılır → başvuru `Hired`. BT kullanıcıyı açar, İK aday - kaydının **Personel** alanına bağlar ("Personele Dönüşen" kartı artar). - ---- - -## 9. Sık sorulanlar - -**İlan açarken kadro talebi listede yok.** Yalnızca onaylanmış (`ApprovalStatus = 'Onaylandı'`) talepler listelenir. - -**Onay butonu kimde görünüyor?** Akış düğümündeki `Approver`'da (seed'de admin). ListForm › Workflow'dan gerçek onaycıyı yazın. - -**Başvuru aşaması geri gitmedi.** Otomatik ilerleme yalnız ileri gider; geri almayı panodan ya da formdan elle yapın. - -**Ret sebebi alanı temizlendi.** Ret sebebi ve notu yalnızca `Rejected` aşamasında tutulur. - -**Aday kaydı kaydedilmiyor.** KVKK rızası işaretli olmalı (tablo da zorlar) ve e-posta kiracıda tekil olmalı. - -**Aynı aday aynı ilana ikinci kez eklenemiyor.** Aday × ilan tekildir. - -**Mülakat puanı nasıl hesaplanıyor?** Kriter ağırlıklı ortalama (§5.2); ağırlıklar İK › Tanımlar › Değerlendirme Kriterleri'nden. - -**İşe alınan aday otomatik personel olmuyor mu?** Hayır; kullanıcıyı BT açar, İK aday kaydına bağlar. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{StaffRequest,JobPosting,Candidate,JobApplication,Interview,InterviewScore,JobOffer,CandidateSource,RejectionReason,EvaluationCriterion}.sql` | Tablolar, CHECK ve tekil indeksler | -| `configs/seeds/wizard/{StaffRequest,JobPosting,Candidate,JobApplication,Interview,InterviewScore,JobOffer,CandidateSource,RejectionReason,EvaluationCriterion}.json` | 10 wizard | -| `configs/seeds/data/App.Hr.{CandidateSource,RejectionReason,EvaluationCriterion}.json` | Tanım verisi | -| `configs/seeds/data/App.Reports.ReportTemplates.json` | KVKK formu ve teklif mektubu şablonları | -| `configs/seeds/data/App.Notifications.Notification{Types,Rules}.json` | `IseAlimMulakatAtandi` tipi ve 2 kuralı | -| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | - -Kurulum: DB Migrate. Geri alma: Wizard Manager'dan wizard'lar silinir (alt formlar önce: `InterviewScore` -→ `Interview`/`JobOffer` → `JobApplication` → diğerleri); tablolar yalnızca onayda seçilirse düşer. -Rapor şablonları ve bildirim satırları elle kaldırılır. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Kadro Talepleri — `App.Hr.StaffRequest` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/StaffRequest.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.StaffRequest` (sıra 1) | -| Yetki | `App.Hr.StaffRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Kadro Talepleri — bir departmanın yeni ya da boşalan bir pozisyon için personel istemesi ve bu isteğin onay süreci. İşe alım sürecinin ilk adımıdır; ilan yalnızca onaylanmış talepten açılır. | -| Kaynak | `Hr_T_StaffRequest` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Pending`, `App.Hr.StaffRequest.Widget.Approved`, `App.Hr.StaffRequest.Widget.Headcount` | -| Komutlar | InsertAfter: SQL | -| Form varsayılanları | IsActive=true, RequestDate=@DATE, RequestedById=@USERID, Headcount=1, EmploymentType=FullTime, Reason=NewPosition, CurrencyId=TRY | -| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Onay Bekliyor' → Inform 'Onay Bilgisi' → Inform 'Ret Bilgisi' → End 'Onaylandı' → End 'Reddedildi' | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `RequestNo` | Talep No | dxTextBox | | ✓ | | -| `RequestDate` | Talep Tarihi | dxDateBox | ✓ | ✓ | | -| `RequestedById` | Talep Eden | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | -| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | -| `Headcount` | Kadro Adedi | dxNumberBox | ✓ | ✓ | | -| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | -| `ExpectedStartDate` | Beklenen Başlangıç | dxDateBox | | ✓ | | -| `Reason` | Talep Nedeni | dxRadioGroup | ✓ | ✓ | liste: NewPosition, Replacement · script | -| `ReplacedUserId` | Ayrılan Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `MinSalary` | Asgari Ücret | dxNumberBox | | ✓ | | -| `MaxSalary` | Azami Ücret | dxNumberBox | | ✓ | | -| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | -| `Qualifications` | Aranan Nitelikler | dxHtmlEditor | | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | -| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | -| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | -| `ApprovalDescription` | Onay Açıklaması | dxTextArea | | ✓ | | - -### İlanlar — `App.Hr.JobPosting` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/JobPosting.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.JobPosting` (sıra 2) | -| Yetki | `App.Hr.JobPosting` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | İlanlar — onaylanmış kadro taleplerinden açılan iş ilanları ve ilana gelen başvurular. | -| Kaynak | `Hr_T_JobPosting` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.JobApplication` (Id → JobPostingId) | -| Widget'lar | `App.Widget.Total`, `App.Widget.Published`, `App.Widget.Draft`, `App.Hr.JobPosting.Widget.Closed` | -| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | -| Form varsayılanları | IsActive=true, Status=Draft, Headcount=1, EmploymentType=FullTime, WorkModel=Office, PublishDate=@DATE | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `PostingNo` | İlan No | dxTextBox | | ✓ | | -| `StaffRequestId` | Kadro Talebi | dxSelectBox | | ✓ | sorgu: Hr_T_StaffRequest · script | -| `Title` | İlan Başlığı | dxTextBox | ✓ | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Published, Closed, Cancelled | -| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | -| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | -| `Headcount` | Kadro Adedi | dxNumberBox | ✓ | ✓ | | -| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | -| `WorkModel` | Çalışma Modeli | dxSelectBox | ✓ | ✓ | liste: Office, Hybrid, Remote | -| `Location` | Lokasyon | dxTextBox | | ✓ | | -| `PublishDate` | Yayın Tarihi | dxDateBox | | ✓ | | -| `ClosingDate` | Son Başvuru Tarihi | dxDateBox | | ✓ | | -| `SourceIds` | Yayın Kanalları | dxTagBox | | ✓ | sorgu: Hr_T_CandidateSource | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `Description` | Açıklama | dxHtmlEditor | | ✓ | | -| `Requirements` | Aranan Nitelikler | dxHtmlEditor | | ✓ | | - -### Adaylar — `App.Hr.Candidate` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Candidate.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.Candidate` (sıra 3) | -| Yetki | `App.Hr.Candidate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Adaylar — CV ve KVKK açık rızası ile tutulan aday havuzu. Bir aday birden fazla ilana başvurabilir. | -| Kaynak | `Hr_T_Candidate` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.JobApplication` (Id → CandidateId) | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive`, `App.Hr.Candidate.Widget.Converted` | -| Komutlar | UpdateAfter: SQL | -| Form varsayılanları | IsActive=true, KvkkConsentDate=@NOW, KvkkConsentMethod=Written, CurrencyId=TRY | -| Butonlar | `App.Hr.Candidate.KvkkConsentForm` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Photo` | Fotoğraf | dxImageUpload | | ✓ | | -| `FirstName` | Adı | dxTextBox | ✓ | ✓ | | -| `LastName` | Soyadı | dxTextBox | ✓ | ✓ | | -| `Email` | E-posta | dxTextBox | ✓ | ✓ | | -| `PhoneNumber` | Telefon | dxTextBox | | ✓ | | -| `Gender` | Cinsiyet | dxSelectBox | | ✓ | liste: Male, Female | -| `BirthDate` | Doğum Tarihi | dxDateBox | | ✓ | | -| `Country` | Ülke | dxSelectBox | | ✓ | sorgu: Sas_H_Country | -| `City` | Şehir | dxSelectBox | | ✓ | sorgu: Sas_H_City (← Country) | -| `Address` | Adres | dxTextBox | | ✓ | | -| `EducationLevel` | Eğitim Düzeyi | dxSelectBox | | ✓ | liste: Primary, HighSchool, Associate, Bachelor, Master, Doctorate | -| `School` | Okul | dxTextBox | | ✓ | | -| `Major` | Bölüm | dxTextBox | | ✓ | | -| `GraduationYear` | Mezuniyet Yılı | dxNumberBox | | ✓ | | -| `ExperienceYears` | Deneyim (Yıl) | dxNumberBox | | ✓ | | -| `CurrentCompany` | Mevcut Firma | dxTextBox | | ✓ | | -| `CurrentTitle` | Mevcut Ünvan | dxTextBox | | ✓ | | -| `ExpectedSalary` | Ücret Beklentisi | dxNumberBox | | ✓ | | -| `CurrencyId` | Para Birimi | dxSelectBox | | ✓ | sorgu: Sas_H_Currency | -| `SourceId` | Kaynak | dxSelectBox | | ✓ | sorgu: Hr_T_CandidateSource | -| `LinkedInUrl` | LinkedIn | dxTextBox | | ✓ | | -| `UserId` | Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `SkillIds` | Yetkinlikler | dxTagBox | | ✓ | sorgu: Hr_T_Skill | -| `CvDocument` | CV | dxImageUpload | | ✓ | | -| `Notes` | Notlar | dxTextBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `KvkkConsent` | Adayın KVKK kapsamında açık rızası alındı | dxCheckBox | ✓ | ✓ | | -| `KvkkConsentDate` | Rıza Tarihi | dxDateBox | ✓ | ✓ | | -| `KvkkConsentMethod` | Rıza Alma Yöntemi | dxSelectBox | ✓ | ✓ | liste: Written, Electronic, Email | -| `KvkkConsentDocument` | İmzalı Rıza Belgesi | dxImageUpload | | ✓ | | - -### Başvurular — `App.Hr.JobApplication` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/JobApplication.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.JobApplication` (sıra 4) | -| Yetki | `App.Hr.JobApplication` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Başvurular — bir adayın bir ilana başvurusu ve başvurunun aşama takibi (kanban panosu). | -| Kaynak | `Hr_T_JobApplication` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Todo (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.Interview` (Id → ApplicationId), `App.Hr.JobOffer` (Id → ApplicationId) | -| Todo | başlık `CandidateName`, durum `Stage` (Applied,Screening,Interview,Offer,Hired,Rejected) | -| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | -| Form varsayılanları | IsActive=true, ApplicationDate=@DATE, Stage=Applied, OwnerUserId=@USERID | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `CandidateId` | Aday | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Candidate · script | -| `JobPostingId` | İlan | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosting | -| `CandidateName` | Aday | dxTextBox | | | | -| `PostingTitle` | İlan | dxTextBox | | | | -| `ApplicationDate` | Başvuru Tarihi | dxDateBox | ✓ | ✓ | | -| `SourceId` | Kaynak | dxSelectBox | | ✓ | sorgu: Hr_T_CandidateSource | -| `OwnerUserId` | Sorumlu | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `AverageScore` | Ortalama Puan | dxNumberBox | | ✓ | | -| `Stage` | Aşama | dxSelectBox | ✓ | ✓ | liste: Applied, Screening, Interview, Offer, Hired, Rejected · script | -| `RejectionReasonId` | Ret Sebebi | dxSelectBox | | ✓ | sorgu: Hr_T_RejectionReason | -| `RejectionNote` | Ret Açıklaması | dxTextArea | | ✓ | | -| `SortOrder` | Sıralama | dxNumberBox | | | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `Notes` | Notlar | dxTextArea | | ✓ | | - -### Mülakatlar — `App.Hr.Interview` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Interview.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.Interview` (sıra 5) | -| Yetki | `App.Hr.Interview` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Mülakatlar — başvuru için mülakat planlama, mülakatçı ataması ve kriter bazlı puanlama. | -| Kaynak | `Hr_T_Interview` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Scheduler (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.InterviewScore` (Id → InterviewId) | -| Komutlar | InsertAfter: SQL · UpdateAfter: SQL · DeleteAfter: SQL | -| Form varsayılanları | IsActive=true, InterviewType=FaceToFace, Status=Planned, InterviewerUserId=@USERID | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ApplicationId` | Başvuru | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobApplication | -| `Title` | Başlık | dxTextBox | | | | -| `InterviewType` | Mülakat Türü | dxSelectBox | ✓ | ✓ | liste: Phone, Video, FaceToFace, Technical, Hr | -| `InterviewerUserId` | Mülakatçı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `StartDate` | Başlangıç | dxDateBox | ✓ | ✓ | script | -| `EndDate` | Bitiş | dxDateBox | ✓ | ✓ | | -| `Location` | Yer | dxTextBox | | ✓ | | -| `MeetingUrl` | Toplantı Bağlantısı | dxTextBox | | ✓ | | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Planned, Completed, Cancelled, NoShow | -| `Recommendation` | Öneri | dxSelectBox | | ✓ | liste: Hire, Hold, Reject | -| `OverallScore` | Genel Puan | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `Notes` | Notlar | dxTextArea | | ✓ | | - -### Aday Kaynakları — `App.Hr.CandidateSource` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/CandidateSource.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.CandidateSource` (sıra 6) | -| Yetki | `App.Hr.CandidateSource` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Aday Kaynakları — adayların ve ilanların hangi kanaldan geldiğini/yayınlandığını tanımlayan liste (LinkedIn, Kariyer.net, referans, kariyer fuarı…). | -| Kaynak | `Hr_T_CandidateSource` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true | -| Veri aynası | `data/App.Hr.CandidateSource.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Teklifler — `App.Hr.JobOffer` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/JobOffer.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Recruitment` › `App.Hr.JobOffer` (sıra 6) | -| Yetki | `App.Hr.JobOffer` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Teklifler — işe alınması düşünülen adaya yapılan ücret ve şart teklifi, iç onayı ve teklif mektubu. | -| Kaynak | `Hr_T_JobOffer` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: SQL · UpdateAfter: SQL | -| Form varsayılanları | IsActive=true, OfferDate=@DATE, Status=Draft, CurrencyId=TRY, EmploymentType=FullTime, WorkModel=Office | -| Butonlar | `App.Hr.JobOffer.OfferLetter` | -| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Onay Bekliyor' → Inform 'Onay Bilgisi' → Inform 'Ret Bilgisi' → End 'Onaylandı' → End 'Reddedildi' | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `OfferNo` | Teklif No | dxTextBox | | ✓ | | -| `ApplicationId` | Başvuru | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobApplication · script | -| `CandidateName` | Aday | dxTextBox | | | | -| `OfferDate` | Teklif Tarihi | dxDateBox | ✓ | ✓ | | -| `ValidUntil` | Geçerlilik Tarihi | dxDateBox | | ✓ | | -| `StartDate` | İşe Başlama Tarihi | dxDateBox | | ✓ | | -| `GrossSalary` | Brüt Maaş | dxNumberBox | ✓ | ✓ | | -| `CurrencyId` | Para Birimi | dxSelectBox | ✓ | ✓ | sorgu: Sas_H_Currency | -| `Status` | Durum | dxSelectBox | ✓ | ✓ | liste: Draft, Sent, Accepted, Declined, Expired · script | -| `ResponseDate` | Yanıt Tarihi | dxDateBox | | ✓ | | -| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | -| `DepartmentId` | Departman | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Department (← BranchId) | -| `JobPositionId` | İş Pozisyonu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_JobPosition (← DepartmentId) | -| `EmploymentType` | Çalışma Şekli | dxSelectBox | ✓ | ✓ | liste: FullTime, PartTime, Contract, Intern, Seasonal | -| `WorkModel` | Çalışma Modeli | dxSelectBox | ✓ | ✓ | liste: Office, Hybrid, Remote | -| `BenefitCodes` | Yan Haklar | dxTagBox | | ✓ | sorgu: Hr_T_BenefitType | -| `Notes` | Notlar | dxTextBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | -| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | | -| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | | -| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | -| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | - -### Ret Sebepleri — `App.Hr.RejectionReason` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/RejectionReason.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.RejectionReason` (sıra 7) | -| Yetki | `App.Hr.RejectionReason` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ret Sebepleri — bir başvurunun şirket ya da aday tarafından neden kapatıldığını sınıflandıran liste. | -| Kaynak | `Hr_T_RejectionReason` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true, RejectedBy=Company | -| Veri aynası | `data/App.Hr.RejectionReason.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `RejectedBy` | Reddeden | dxRadioGroup | ✓ | ✓ | liste: Company, Candidate | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Değerlendirme Kriterleri — `App.Hr.EvaluationCriterion` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/EvaluationCriterion.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.EvaluationCriterion` (sıra 8) | -| Yetki | `App.Hr.EvaluationCriterion` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Değerlendirme Kriterleri — mülakatlarda puanlanan kriterler ve ağırlıkları (iletişim, teknik yetkinlik, problem çözme…). | -| Kaynak | `Hr_T_EvaluationCriterion` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true, Weight=1 | -| Veri aynası | `data/App.Hr.EvaluationCriterion.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `Weight` | Ağırlık | dxNumberBox | ✓ | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - -### Mülakat Puanları — `App.Hr.InterviewScore` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/InterviewScore.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.InterviewScore` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Mülakat Puanları — mülakatta her değerlendirme kriterine verilen 1–5 puan. | -| Kaynak | `Hr_T_InterviewScore` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: SQL · UpdateAfter: SQL · DeleteAfter: SQL | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `InterviewId` | Mülakat | dxTextBox | | | | -| `CriterionId` | Kriter | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_EvaluationCriterion | -| `Score` | Puan | dxSelectBox | ✓ | ✓ | liste: 1, 2, 3, 4, 5 | -| `Comment` | Yorum | dxTextArea | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrTrainings.md b/configs/seeds/docs/modules/HrTrainings.md deleted file mode 100644 index 3dca1f4c..00000000 --- a/configs/seeds/docs/modules/HrTrainings.md +++ /dev/null @@ -1,319 +0,0 @@ -# İK › Eğitimler (`App.Hr.Trainings`) - -Şirket içi ve dışı eğitimlerin kaydı: eğitim tipi → konu tanımları, eğitim oturumu (tarih/saat, -süre, yer, eğitmen, maliyet, kazandırdığı yetkinlikler), katılımcılar (katılım durumu, puan, -katılım belgesi) ve eğitim dosyaları. Tamamı konfigürasyondur (Wizard + rapor şablonu); entity, -migration ya da React kodu yoktur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK / eğitim sorumlusu | Tip ve konu tanımlar, eğitim açar, katılımcı ekler, katılım/puan girer, dosya yükler, katılım belgesi basar | Eğitim Tipleri · Eğitim Konuları · Eğitimler | -| Yönetim | Eğitim adedi, açık/kapalı durum ve toplam maliyeti izler (widget, Pivot, Chart) | Eğitimler | - -Kapsam: kiracı (`IsTenant`). Eğitim bir şubeye bağlıdır (`BranchId` zorunlu); satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan -> (wizard, SQL, seed, commit `36546d0c` "Human Resources -> Eğitim bilgileri") okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Wizard ekranları; eğitim kaydının altında Katılımcılar ve Dosyalar sekmeleri (menüsüz alt formlar) | -| Tanımlar | Tip ve konu tanımları İK › Tanımlar'da değil **Eğitimler** dalının içindedir; konu bir tipe bağlıdır ve tip seçimine göre süzülür | -| Süre | `Toplam Süre (saat) = gün sayısı (bitiş dahil) × günlük saat (bitiş – başlangıç saati)` — formda hesaplanır | -| Maliyet | Altı kalem (yer, eğitmen, konaklama, ulaşım, ikram, diğer) toplanarak `CostTotal` formda hesaplanır | -| Yetkinlik | Eğitimin kazandırdığı yetkinlikler `SkillIds` (çok değerli, `Hr_T_Skill`) olarak saklanır; çalışan profiline (`Adm_T_UserSkill`) **yazılmaz** | -| Katılımcı | Personel seçilince işe giriş tarihi, departman ve pozisyon kullanıcı kaydından kopyalanır (eğitim anındaki hâli saklanır) | -| Katılım durumu | Attended / NotAttended / Excused; varsayılan **Attended** | -| Katılım belgesi | Yalnızca `Attended` satırda görünen satır butonu → **Katılım Belgesi** raporu (`DynamicReport`) | -| Dosyalar | Belge türü `Hr_T_DocumentType` (ortak İK tanımı); dosya içeriği base64 (`dxImageUpload`) | - ---- - -## 3. Menü ve ekranlar - -`İnsan Kaynakları › Eğitimler` (`App.Hr.Trainings`, ikon `FcGraduationCap`) - -| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Görünümler | Widget'lar | -| --- | --- | --- | --- | --- | --- | -| 1 | Eğitim Tipleri / Training Types | `App.Hr.TrainingType` | — | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | -| 2 | Eğitim Konuları / Training Subjects | `App.Hr.TrainingSubject` | — | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | -| 3 | Eğitimler / Trainings | `App.Hr.Training` | `TrainingParticipant`, `TrainingFile` (`Id → TrainingId`, menüsüz) | Grid, Card, Pivot, Chart | Toplam · Açık · Kapalı · Toplam Maliyet | - -Seed verisi: 8 eğitim tipi (Oryantasyon, İş Başı, Teknik Oryantasyon, Grup, Firma Dışı, Eğitim -İçerikli Sosyal Faaliyet, Akademi, Rotasyon) ve 18 eğitim konusu (`data/App.Hr.{TrainingType,TrainingSubject}.json`). - -Satır butonu: Katılımcılar › **Katılım Belgesi** — rapor `3840a20d-3233-4d17-bc06-ccfd8d87b32a`, -görünürlük `AttendanceStatus === 'Attended'`. - ---- - -## 4. Veri modeli - -``` -Hr_T_TrainingType ──< Hr_T_TrainingSubject - │ │ - └──────< Hr_T_Training >──── Sas_T_Branch - ├──< Hr_T_TrainingParticipant >── AbpUsers (+ Department, JobPosition) - └──< Hr_T_TrainingFile >── Hr_T_DocumentType -``` - -| Tablo | Önemli kolonlar | Kural | -| --- | --- | --- | -| `Hr_T_TrainingType` | `Name`, `IsActive` | — | -| `Hr_T_TrainingSubject` | `TrainingTypeId`, `Name`, `IsEvaluated` (değerlendirilsin mi), `IsActive` | — | -| `Hr_T_Training` | `TrainingTypeId`, `TrainingSubjectId` (tipe göre cascade), `EntryDate`, `BranchId`, `StartDate`, `EndDate`, `StartTime`, `EndTime`, `TotalHours`, `Status` (Open/Closed), `TrainerName`, `TrainingPlace`, `TrainingInstitution`, `Description`, `SkillIds`, `CostPlace`, `CostTrainer`, `CostAccommodation`, `CostTransport`, `CostCatering`, `CostOther`, `CostTotal` | Bitiş başlangıçtan önce olamaz (form) | -| `Hr_T_TrainingParticipant` | `TrainingId`, `UserId`, `HireDate`, `DepartmentId`, `JobPositionId`, `AttendanceStatus`, `EvaluationScore`, `ExamScore`, `LeaveDate`, `Note` | — | -| `Hr_T_TrainingFile` | `TrainingId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` | Dosya zorunlu | - -Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır. - ---- - -## 5. İş kuralları ve hesaplar - -Hesapların tamamı `EditorScript`'tir (sunucu tarafında after-command yoktur): - -| Alan | Kural | -| --- | --- | -| `EntryDate` | Yeni kayıtta bugün | -| `Status` | Yeni kayıtta `Open` | -| `TotalHours` | Başlangıç/bitiş tarihi ya da saatlerinden biri değişince `round(days(StartDate, EndDate) × hours(StartTime, EndTime), 2)`; dört alan dolu olmalı | -| `EndDate` | Başlangıçtan önceyse uyarı + değişiklik geri alınır | -| `CostTotal` | Altı maliyet kaleminden biri değişince toplam | -| Katılımcı `UserId` | Seçilince `HireDate`, `DepartmentId`, `JobPositionId` kopyalanır | -| `AttendanceStatus` | Yeni satırda `Attended` | -| Dosya `FileDate` | Yeni satırda bugün | -| Tip/Konu `IsActive`, `IsEvaluated` | Yeni kayıtta `true` | - -Saat hesabı aynı günlük saat aralığının her gün tekrarlandığını varsayar; gün sayısına bitiş günü dahildir. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Trainings` ara yetkisinin -altında üç ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; `TrainingParticipant` ve -`TrainingFile` `App.Hr.Training` altındadır. Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. - -| Rol | Yetkiler | -| --- | --- | -| Eğitim sorumlusu | `App.Hr.Trainings` dalının tamamı | -| Bölüm yöneticisi (izleme) | `App.Hr.Training` + `App.Hr.TrainingParticipant` (salt okuma) | - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `Sas_T_Branch` | Eğitimin şubesi | -| `AbpUsers` | Katılımcı; işe giriş tarihi, departman, pozisyon kopyası | -| Kullanıcı detayı › Eğitimler | Katılımcılar ekranı çalışana süzülmüş açılır; satır eklemek çalışanı eğitime katılımcı yapar (`HrPersonnel.md`) | -| `Hr_T_Department`, `Hr_T_JobPosition` | Katılımcının o anki birimi (Pivot kırılımı) | -| `Hr_T_Skill` / `Hr_T_SkillType` | Eğitimin kazandırdığı yetkinlikler | -| `Hr_T_DocumentType` | Eğitim dosyası türü | -| Raporlar | Katılım Belgesi (`DynamicReport`, `Raporlar` kategorisi) | -| Performans Yönetimi | Gelişim planı aksiyonu bir eğitime bağlanabilir (`Hr_T_DevelopmentPlan.TrainingId`); çalışan o eğitimde **Attended** ise aksiyon kendiliğinden tamamlanır: plan kaydında ve katılımcı kaydında (`Hr_S_DevelopmentPlanSync`, `Hr_S_TrainingSync`; bkz. `HrPerformance.md`) | -| Puantaj ve Devam Takibi | **Katıldı** işaretli katılımcının başlangıç–bitiş arasındaki iş günleri puantajda `Eğitimde` (vardiya saatleriyle) yazılır, okutması olmadığı için devamsız sayılmaz. Eğitim ya da katılımcı eklenince, değişince, silinince `Hr_S_TrainingSync` günleri hemen yeniden hesaplar (`HrAttendance.md` §7.1) | - ---- - -## 8. Akış örneği - -1. İK **Eğitimler**'de "İş Sağlığı ve Güvenliği" kaydını açar: tip Grup Eğitimi, konu İSG, şube - Merkez, 3–4 Kasım 09:00–17:00 → toplam süre 16 saat; eğitmen ve yer maliyetini girer → toplam - maliyet hesaplanır; kazandırdığı yetkinliği (İSG) seçer. -2. **Katılımcılar** sekmesine personeli ekler; departman/pozisyon kopyalanır, durum Katıldı. -3. Gelmeyen personeli **Katılmadı**, raporlu olanı **Mazeretli** yapar; sınav/değerlendirme puanlarını girer. -4. Katılanların satırından **Katılım Belgesi** basılır; imzalı liste **Dosyalar** sekmesine yüklenir. -5. Eğitim **Kapalı** yapılır; widget'taki toplam maliyete eklenir. - ---- - -## 9. Sık sorulanlar - -**Toplam süre hesaplanmıyor.** Başlangıç/bitiş tarihi ve başlangıç/bitiş saatinin dördü de dolu olmalı. - -**Katılım belgesi butonu görünmüyor.** Yalnızca katılım durumu "Katıldı" olan satırda çıkar. - -**Eğitim konusu listesi boş.** Konu, seçilen eğitim tipine göre süzülür; önce tip seçin. - -**Eğitimdeki yetkinlik çalışan profiline yazılıyor mu?** Hayır; `SkillIds` eğitimin bilgisidir. Profil, Performans Yönetimi'nde tamamlanan değerlendirmeden güncellenir. - -**Katılımcının departmanı sonradan değişti, eğitimde eski görünüyor.** Bilinçli: eğitim anındaki birim saklanır. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{TrainingType,TrainingSubject,Training,TrainingParticipant,TrainingFile}.sql` | Tablolar | -| `configs/seeds/wizard/{TrainingType,TrainingSubject,Training,TrainingParticipant,TrainingFile}.json` | 5 wizard | -| `configs/seeds/data/App.Hr.{TrainingType,TrainingSubject}.json` | Tanım verisi | -| `configs/seeds/data/App.Reports.ReportTemplates.json` | Katılım Belgesi şablonu | -| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | - -Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar (`TrainingParticipant`, `TrainingFile`) -önce, sonra `Training`, `TrainingSubject`, `TrainingType` silinir; tablolar yalnızca onayda seçilirse -düşer. Gelişim planlarındaki `TrainingId` bağları silinmez, boşa düşer. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Eğitim Tipleri — `App.Hr.TrainingType` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TrainingType.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Trainings` › `App.Hr.TrainingType` (sıra 1) | -| Yetki | `App.Hr.TrainingType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Eğitim Tipleri — eğitimlerin türü (oryantasyon, iş başı, grup, firma dışı, akademi, rotasyon…). | -| Geliştirme talebi | Human Resources -> Eğitim | -| Kaynak | `Hr_T_TrainingType` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.TrainingType.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | script | - -### Eğitim Konuları — `App.Hr.TrainingSubject` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TrainingSubject.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Trainings` › `App.Hr.TrainingSubject` (sıra 2) | -| Yetki | `App.Hr.TrainingSubject` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Eğitim Konuları — bir eğitim tipine bağlı konu başlıkları (İSG, siber güvenlik, iş başı eğitimi…). | -| Geliştirme talebi | Human Resources -> Eğitim | -| Kaynak | `Hr_T_TrainingSubject` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Veri aynası | `data/App.Hr.TrainingSubject.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `TrainingTypeId` | Eğitim Tipi | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingType | -| `Name` | Eğitim Konusu | dxTextBox | ✓ | ✓ | | -| `IsEvaluated` | Değerlendirilsin mi? | dxCheckBox | ✓ | ✓ | script | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | script | - -### Eğitimler — `App.Hr.Training` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Training.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Trainings` › `App.Hr.Training` (sıra 3) | -| Yetki | `App.Hr.Training` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Eğitimler — düzenlenen her eğitim oturumu: tarih/saat, süre, yer, eğitmen, maliyet, kazandırdığı yetkinlikler, katılımcılar ve dosyalar. | -| Geliştirme talebi | Human Resources -> Eğitim | -| Kaynak | `Hr_T_Training` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.TrainingParticipant` (Id → TrainingId), `App.Hr.TrainingFile` (Id → TrainingId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Training.Widget.Open`, `App.Hr.Training.Widget.Closed`, `App.Hr.Training.Widget.Cost` | -| Komutlar | UpdateAfter: `Hr_S_TrainingSync` · DeleteAfter: `Hr_S_TrainingSync` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `TrainingTypeId` | Eğitim Tipi | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingType | -| `TrainingSubjectId` | Eğitim Konusu | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_TrainingSubject (← TrainingTypeId) | -| `EntryDate` | Giriş Tarihi | dxDateBox | ✓ | ✓ | script | -| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | -| `StartDate` | Eğitim Baş. Tarihi | dxDateBox | ✓ | ✓ | script | -| `EndDate` | Bit. Tarihi | dxDateBox | ✓ | ✓ | script | -| `StartTime` | Eğitim Baş. Saati | dxDateBox | | ✓ | script | -| `EndTime` | Bit. Saati | dxDateBox | | ✓ | script | -| `TotalHours` | Top. Eğitim Süresi (Saat) | dxNumberBox | | ✓ | | -| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Open, Closed · script | -| `TrainerName` | Eğitim Veren Kişi | dxTextBox | | ✓ | | -| `TrainingPlace` | Eğitim Yeri | dxTextBox | | ✓ | | -| `TrainingInstitution` | Eğitim Veren Kurum | dxTextBox | | ✓ | | -| `Description` | Açıklama | dxTextArea | | ✓ | | -| `SkillIds` | Yetkinlikler | dxTagBox | | ✓ | sorgu: Hr_T_Skill | -| `CostPlace` | Eğitim Yeri Maliyeti | dxNumberBox | | ✓ | script | -| `CostTrainer` | Eğitmen Maliyeti | dxNumberBox | | ✓ | script | -| `CostAccommodation` | Konaklama | dxNumberBox | | ✓ | script | -| `CostTransport` | Ulaşım | dxNumberBox | | ✓ | script | -| `CostCatering` | İkram | dxNumberBox | | ✓ | script | -| `CostOther` | Diğer | dxNumberBox | | ✓ | script | -| `CostTotal` | Toplam Maliyet | dxNumberBox | | ✓ | | - -### Katılımcılar — `App.Hr.TrainingParticipant` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TrainingParticipant.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TrainingParticipant` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Katılımcılar — eğitime katılan personel ve katılım sonucu. | -| Geliştirme talebi | Human Resources -> Eğitim | -| Kaynak | `Hr_T_TrainingParticipant` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Komutlar | InsertAfter: `Hr_S_TrainingSync` · UpdateAfter: `Hr_S_TrainingSync` · DeleteAfter: `Hr_S_TrainingSync` | -| Butonlar | `App.Hr.TrainingParticipant.Certificate` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `TrainingId` | Eğitim | dxSelectBox | | | sorgu: Hr_T_Training | -| `UserId` | Adı Soyadı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script | -| `HireDate` | İşe Giriş Tarihi | dxDateBox | | ✓ | | -| `DepartmentId` | Bölüm | dxSelectBox | | ✓ | sorgu: Hr_T_Department | -| `JobPositionId` | Görevi | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition | -| `AttendanceStatus` | Katılım Durumu | dxSelectBox | ✓ | ✓ | liste: Attended, NotAttended, Excused · script | -| `EvaluationScore` | Değerlendirme Puanı | dxNumberBox | | ✓ | | -| `ExamScore` | Sınav Notu | dxNumberBox | | ✓ | | -| `LeaveDate` | Ayrılma Tarihi | dxDateBox | | ✓ | | -| `Note` | Not | dxTextArea | | ✓ | | - -### Dosyalar — `App.Hr.TrainingFile` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/TrainingFile.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.TrainingFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Eğitim Dosyaları — eğitime ait doküman ve dijital kaynaklar (sunum, imzalı katılım listesi, sertifika örneği…). | -| Geliştirme talebi | Human Resources -> Eğitim | -| Kaynak | `Hr_T_TrainingFile` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `TrainingId` | Eğitim | dxTextBox | | | | -| `DocumentTypeId` | Dosya Türü | dxSelectBox | | ✓ | sorgu: Hr_T_DocumentType | -| `FileDate` | Tarih | dxDateBox | ✓ | ✓ | script | -| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | -| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrVehicles.md b/configs/seeds/docs/modules/HrVehicles.md deleted file mode 100644 index cd1b9b2e..00000000 --- a/configs/seeds/docs/modules/HrVehicles.md +++ /dev/null @@ -1,545 +0,0 @@ -# İK › Araçlar (`App.Hr.Vehicles`) - -Şirket araç filosu yönetimi: araç ve şoför kayıtları, araç/şoför belgeleri (ruhsat, sigorta, -muayene, ehliyet, psikoteknik), trafik cezaları ve kazalar, fatura bazlı araç masrafları ve -güvenlik kulübesinden araç giriş–çıkış takibi (km, süre, gidilen yer). Tamamı konfigürasyondur -(Wizard + SQL); entity, migration ya da React kodu yoktur. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Filo / idari işler sorumlusu | Araç, şoför, belge ve masraf tanımlarını yönetir; araç belgelerini ve masraf faturalarını girer | Araç Belgeleri · Araçlar · Gidilecek Yerler · Şoför Tanımlama · Masraf Tanımlama · Masraf Girişleri | -| Güvenlik personeli | Aracın çıkışını ve dönüşünü (km, saat, kullanan personel) kaydeder | Araç Giriş-Çıkış Takip | -| Yönetim | Dışarıdaki araç sayısı, toplam km ve masrafı izler | Widget'lar, Pivot, Chart | - -Kapsam: kiracı (`IsTenant`). Araç bir şubeye (tesis) bağlıdır; satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan (wizard, -> SQL, seed, commit'ler `7be0b4ed` "Human Resources -> Araçlar" ve `021a8a34` "Araçlar düzenlemesi") -> okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Wizard ekranları; aracın altında Belgeler, şoförün altında Belgeler / Cezalar / Kazalar, masraf girişinin altında Kalemler (menüsüz alt formlar) | -| Belge tanımı | Tek tanım tablosu (`Hr_T_VehicleDocument`) iki eksenle ayrılır: **grup** (Vehicle / Driver) ve **tip** (Insurance, Document, Tax, Toll, Inspection, Maintenance, Penalty, Accident). Her alt form kendi kümesini süzer | -| Araç durumu | `Arrived` (Geldi — şirkette) / `Left` (Gitti — dışarıda); giriş–çıkış kaydından güncellenir | -| Araç km'si | `CurrentKm` giriş–çıkış kaydının giriş km'sinden güncellenir; yeni çıkışta önerilen çıkış km'si budur | -| Zimmet | Şoföre en fazla **5 araç** zimmetlenir (`Vehicle1Id`…`Vehicle5Id` sabit kolonlar) | -| Şoför km'si | Şoförün `TotalKm`'si, kullandığı tüm hareketlerin yapılan km toplamıdır (SQL) | -| Masraf | Fatura başlığı + kalemler; `Net Tutar = Miktar × Tutar × (1 − İskonto% / 100)` formda hesaplanır | -| Muayene/sigorta tarihleri | Araç kaydında başlangıç–bitiş tarihleri olarak tutulur; **hatırlatma/bildirim yoktur** | -| Hareket numarası | `MovementNo` kiracı bazında `MAX + 1` (insert sonrası SQL) | - ---- - -## 3. Menü ve ekranlar - -`İnsan Kaynakları › Araçlar` (`App.Hr.Vehicles`, ikon `FcAutomotive`) - -| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Widget'lar | -| --- | --- | --- | --- | --- | -| 1 | Araç Belgeleri / Vehicle Documents | `App.Hr.VehicleDocument` | — | Toplam · Aktif · Pasif | -| 2 | Masraf Tanımlama / Expense Definitions | `App.Hr.VehicleExpenseDefinition` | — | Toplam · Aktif · Pasif | -| 3 | Gidilecek Yerler / Destinations | `App.Hr.VehicleDestination` | — | Toplam · Aktif · Pasif | -| 4 | Araçlar / Vehicles | `App.Hr.Vehicle` | `VehicleFile` (`Id → VehicleId`) | Toplam · Geldi · Gitti · Pasif | -| 5 | Şoför Tanımlama / Drivers | `App.Hr.Driver` | `DriverDocument`, `DriverPenalty`, `DriverAccident` (`Id → DriverId`) | Toplam · Zimmetli Araçlı · Toplam Km | -| 6 | Araç Giriş-Çıkış Takip / Vehicle Gate Log | `App.Hr.VehicleMovement` | — | Toplam · Gitti · Bugün | -| 7 | Masraf Girişleri / Vehicle Expenses | `App.Hr.VehicleExpense` | `VehicleExpenseLine` (`Id → VehicleExpenseId`) | Toplam · Bugün · Toplam Tutar (net kalemler) | - -Tüm ekranlar Grid, Card, Pivot, Chart görünümleriyle gelir; özel görünüm (Todo, Scheduler) yoktur. - -Seed verisi: -- 17 belge tanımı (`data/App.Hr.VehicleDocument.json`). Örnekler: trafik sigortası, ruhsat, K2, MTV, OGS/HGS, egzoz/genel muayene, takograf (araç); sürücü belgesi, psikoteknik, SRC 4, kırmızı ışık ve hız cezası (şoför). -- 9 masraf tanımı (`data/App.Hr.VehicleExpenseDefinition.json`): sigorta, vergi, bakım, muayene ×2, geçiş ×2, ceza, yakıt. - ---- - -## 4. Veri modeli - -``` -Sas_T_Branch ──< Hr_T_Vehicle ──< Hr_T_VehicleFile >── Hr_T_VehicleDocument (grup Vehicle) - │ ▲ - │ └── Hr_T_Driver.Vehicle1..5Id ── AbpUsers (UserId) - │ ├──< Hr_T_DriverDocument >── VehicleDocument (grup Driver, ceza/kaza hariç) - │ ├──< Hr_T_DriverPenalty >── VehicleDocument (tip Penalty) - │ └──< Hr_T_DriverAccident >── VehicleDocument (tip Accident) - ├──< Hr_T_VehicleExpense ──< Hr_T_VehicleExpenseLine >── Hr_T_VehicleExpenseDefinition - │ └── Hr_T_VehicleDestination (firma) - └──< Hr_T_VehicleMovement >── AbpUsers (gönderen, güvenlik, kullanan), Hr_T_VehicleDestination -``` - -| Tablo | Önemli kolonlar | -| --- | --- | -| `Hr_T_VehicleDocument` | `DocumentGroup` (Vehicle/Driver), `DocumentType` (8 tip), `Name`, `IsActive` | -| `Hr_T_Vehicle` | `BranchId` (tesis), `Name`, `Brand`, `Model`, `BodyType`, `UsagePlace`, `RegistrationDate`, `PlateNumber`, `Status` (Arrived/Left), `CurrentKm`, muayene / sigorta / egzoz / takograf başlangıç–bitiş tarihleri, `IsActive` | -| `Hr_T_VehicleFile` | `VehicleId`, `VehicleDocumentId`, `FileName`, `FileContent` | -| `Hr_T_VehicleDestination` | `Name`, `Distance` (km), `IsActive` | -| `Hr_T_Driver` | `UserId`, `Vehicle1Id`…`Vehicle5Id`, `TotalKm` | -| `Hr_T_DriverDocument` | `DriverId`, `VehicleDocumentId`, `FileName`, `FileContent` | -| `Hr_T_DriverPenalty` | `DriverId`, `PenaltyDate`, `Amount`, `Description`, `VehicleDocumentId`, dosya | -| `Hr_T_DriverAccident` | `DriverId`, `AccidentDate`, `VehicleDocumentId`, `Description`, dosya | -| `Hr_T_VehicleExpenseDefinition` | `ExpenseType`, `Name`, `IsActive` | -| `Hr_T_VehicleExpense` | `VehicleId`, `InvoiceNo`, `InvoiceDate`, `DestinationId` (firma), `VehicleDocumentId`, dosya | -| `Hr_T_VehicleExpenseLine` | `VehicleExpenseId`, `ExpenseDefinitionId`, `DetailName`, `Quantity`, `Amount`, `DiscountRate`, `NetAmount`, `Description` | -| `Hr_T_VehicleMovement` | `MovementNo`, `ExitDate`, `ExitTime` (SS:dd metin), `BranchId`, `ExitKm`, `SenderUserId`, `SecurityUserId`, `DriverUserId`, `VehicleId`, `DestinationId`, `Reason`, `Location`, `EntrySecurityUserId`, `EntryDate`, `EntryBranchId`, `EntryTime`, `EntryKm`, `TravelledKm`, `Status`, `DurationMinutes`, `ExpectedKm` | - -Tablo düzeyinde CHECK ya da tekil indeks yoktur (plaka tekilliği zorlanmaz); kurallar form ve SQL'dedir. - ---- - -## 5. İş kuralları ve hesaplar - -### 5.1 Giriş–çıkış (`App.Hr.VehicleMovement`) - -Form script'leri: - -| Olay | Kural | -| --- | --- | -| Form açılışı | Çıkış tarihi bugün, çıkış saati şimdi, durum `Left` | -| Araç seçimi | `ExpectedKm` = aracın `CurrentKm`'si; çıkış km boşsa aynı değer yazılır | -| Çıkış km | `ExpectedKm`'den küçükse uyarı + `ExpectedKm` yazılır; giriş km varsa yapılan km yeniden hesaplanır | -| Giriş km | Çıkış km'den küçükse uyarı + geri alınır. Doluysa durum `Arrived`, `TravelledKm = EntryKm − ExitKm`, giriş tarihi/saati boşsa şimdi. Boşsa durum `Left`, yapılan km boş | -| Tarih/saat değişimi | `DurationMinutes` = giriş − çıkış (dakika; saat `SS:dd` biçiminde olmalı) | - -Sunucu komutları: - -| Komut | Etki | -| --- | --- | -| Insert sonrası | `MovementNo` atanır; aracın `Status`'u ve (giriş km varsa) `CurrentKm`'si hareketten yazılır; kullanan personelin şoför kaydındaki `TotalKm` yeniden toplanır | -| Delete sonrası | Şoför `TotalKm` yeniden toplanır; aracın `CurrentKm`'si son girişin km'sine, `Status`'u son hareketin durumuna döner (hareket yoksa `Arrived`) | -| Update sonrası | **Yok** — bkz. §9 | - -### 5.2 Masraf - -`NetAmount = round(Quantity × Amount × (1 − DiscountRate / 100), 2)`; miktar, tutar ya da iskonto -değişince formda hesaplanır. Fatura tarihi yeni kayıtta bugündür. "Toplam Tutar" widget'ı -silinmemiş tüm kalemlerin toplamıdır. - -### 5.3 Belge süzmesi - -| Ekran | Listelenen belge tanımları | -| --- | --- | -| Araç › Belgeler, Masraf Girişi | `DocumentGroup = 'Vehicle'` | -| Şoför › Belgeler | `DocumentGroup = 'Driver'` ve tip `Penalty`/`Accident` dışı | -| Şoför › Cezalar | `DocumentType = 'Penalty'` | -| Şoför › Kazalar | `DocumentType = 'Accident'` | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Yetki ağacı menüyü izler: `App.Hr.Vehicles` ara yetkisinin -altında yedi ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`; alt formlar (`VehicleFile`, -`DriverDocument`, `DriverPenalty`, `DriverAccident`, `VehicleExpenseLine`) ana ekranlarının altındadır. -Satır süzmesi yoktur. Hiçbir yetki role otomatik atanmaz. - -| Rol | Yetkiler | -| --- | --- | -| Filo sorumlusu | `App.Hr.Vehicles` dalının tamamı | -| Güvenlik | `App.Hr.VehicleMovement` (+ `.Create/.Update`) | -| Muhasebe (masraf) | `App.Hr.VehicleExpense`, `App.Hr.VehicleExpenseLine` | - ---- - -## 7. Entegrasyonlar - -| Kaynak | Kullanım | -| --- | --- | -| `Sas_T_Branch` | Aracın tesisi; hareketin çıkış/giriş şubesi | -| `AbpUsers` | Şoför, gönderen personel, güvenlik personeli, kullanan personel | - -Bildirim, zamanlanmış iş ya da rapor şablonu yoktur. - ---- - -## 8. Akış örneği - -1. Filo sorumlusu **Araçlar**'a "34 ABC 123"ü girer (şube Merkez, km 45.000, muayene/sigorta bitiş - tarihleri); **Belgeler** sekmesine ruhsat ve trafik sigortasını yükler. -2. **Şoför Tanımlama**'da personeli şoför yapar, aracı zimmet 1'e bağlar; sürücü belgesini yükler. -3. Güvenlik **Araç Giriş-Çıkış Takip**'te yeni kayıt açar: tarih/saat dolar, araç seçilince çıkış - km 45.000 olur; kullanan personel ve gidilen yer seçilir → araç **Dışarıda**. -4. Dönüşte giriş km'si (45.180) girilir → durum Şirkette, yapılan km 180, süre dakika olarak hesaplanır. -5. Yakıt faturası **Masraf Girişleri**'ne başlık + kalem (yakıt, 40 lt × 45 ₺) olarak girilir. -6. Gelen hız cezası şoförün **Cezalar** sekmesine tutar ve belgeyle eklenir. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Plakası aynı iki araç girilebiliyor mu?** Evet; tabloda tekil kısıt yoktur. - -**Muayene/sigorta bitişi yaklaşınca uyarı geliyor mu?** Hayır; tarihler yalnızca kayıttadır. -Hatırlatma için zamanlanmış iş + bildirim tipi eklenmelidir (yok). - -**Bir şoföre 5'ten fazla araç zimmetlenebilir mi?** Hayır; kolonlar sabittir. - -**Masraf girişindeki "Firma Adı" neden Gidilecek Yerler'den geliyor?** Masraf firması ayrı bir -tanım olarak açılmamış, gidilecek yer tanımı kullanılmıştır. - -**Kontrol edilmeli — dönüş güncellemeyle girildiğinde araç/şoför güncellenmiyor.** Giriş–çıkış -ekranında yalnızca insert ve delete sonrası komut vardır. Çıkış kaydı açılıp dönüş **aynı kaydı -düzenleyerek** girildiğinde aracın `Status`/`CurrentKm`'si ve şoförün `TotalKm`'si güncellenmez -(bir sonraki ekleme ya da silmeye kadar). - -**Kontrol edilmeli — yalnız çıkış girilen kayıtta aracın km'si.** Formda `EntryKm` varsayılanı -`0`'dır. Insert sonrası komut `@EntryKm` boş değilse aracın `CurrentKm`'sini ona eşitler. Giriş km -temizlenmeden kaydedilen bir çıkış kaydı aracın km'sini 0'a çekebilir. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{VehicleDocument,Vehicle,VehicleFile,VehicleDestination,Driver,DriverDocument,DriverPenalty,DriverAccident,VehicleExpenseDefinition,VehicleExpense,VehicleExpenseLine,VehicleMovement}.sql` | Tablolar | -| `configs/seeds/wizard/{VehicleDocument,Vehicle,VehicleFile,VehicleDestination,Driver,DriverDocument,DriverPenalty,DriverAccident,VehicleExpenseDefinition,VehicleExpense,VehicleExpenseLine,VehicleMovement}.json` | 12 wizard | -| `configs/seeds/data/App.Hr.{VehicleDocument,VehicleExpenseDefinition}.json` | Tanım verisi | -| `configs/seeds/data/App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json` | Menü, yetki, dil satırları | - -Kurulum: DB Migrate. Geri alma: Wizard Manager'dan alt formlar önce, ana ekranlar sonra silinir; -tablolar yalnızca onayda seçilirse düşer. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Araç Belgeleri — `App.Hr.VehicleDocument` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleDocument.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleDocument` (sıra 1) | -| Yetki | `App.Hr.VehicleDocument` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Araç Belgeleri — araç ve şoför kayıtlarında kullanılan belge tanımları (ruhsat, sigorta, muayene, MTV, OGS/HGS, ehliyet, psikoteknik, ceza ve kaza belgeleri). | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleDocument` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true | -| Veri aynası | `data/App.Hr.VehicleDocument.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `DocumentGroup` | Belge Grubu | dxSelectBox | ✓ | ✓ | liste: Vehicle, Driver | -| `DocumentType` | Belge Tipi | dxSelectBox | ✓ | ✓ | liste: Insurance, Document, Tax, Toll, Inspection, Maintenance, Penalty, Accident | -| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Masraf Tanımlama — `App.Hr.VehicleExpenseDefinition` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleExpenseDefinition.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleExpenseDefinition` (sıra 2) | -| Yetki | `App.Hr.VehicleExpenseDefinition` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Masraf Tanımlama — araç masraf kalemleri (sigorta, vergi, bakım, muayene, geçiş, ceza, yakıt…). | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleExpenseDefinition` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true | -| Veri aynası | `data/App.Hr.VehicleExpenseDefinition.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `ExpenseType` | Masraf Tipi | dxTextBox | ✓ | ✓ | | -| `Name` | Masraf Adı | dxTextBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Gidilecek Yerler — `App.Hr.VehicleDestination` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleDestination.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleDestination` (sıra 3) | -| Yetki | `App.Hr.VehicleDestination` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Gidilecek Yerler — araçlarla gidilen tanımlı yerler ve uzaklıkları. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleDestination` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Gidilecek Yerin Adı | dxTextBox | ✓ | ✓ | | -| `Distance` | Uzaklığı (km) | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Araçlar — `App.Hr.Vehicle` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Vehicle.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.Vehicle` (sıra 4) | -| Yetki | `App.Hr.Vehicle` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Araçlar — şubeye ait şirket araçları, anlık durumu (şirkette/dışarıda), güncel km'si ve muayene/sigorta tarihleri. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_Vehicle` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.VehicleFile` (Id → VehicleId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Vehicle.Widget.Arrived`, `App.Hr.Vehicle.Widget.Left`, `App.Widget.Passive` | -| Form varsayılanları | IsActive=true | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `BranchId` | Tesis Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | -| `Name` | Araç Adı | dxTextBox | ✓ | ✓ | | -| `Brand` | Markası | dxTextBox | | ✓ | | -| `Model` | Modeli | dxTextBox | | ✓ | | -| `BodyType` | Cinsi | dxTextBox | | ✓ | | -| `UsagePlace` | Kullanıldığı Yer | dxTextBox | | ✓ | | -| `RegistrationDate` | Tescil Tarihi | dxDateBox | | ✓ | | -| `PlateNumber` | Plakası | dxTextBox | ✓ | ✓ | | -| `Status` | Durumu | dxSelectBox | | ✓ | liste: Arrived, Left | -| `CurrentKm` | Araç Km'si | dxNumberBox | | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | -| `InspectionStart` | Muayene Başlangıç | dxDateBox | | ✓ | | -| `InspectionEnd` | Muayene Bitiş | dxDateBox | | ✓ | | -| `InsuranceStart` | Sigorta Başlangıç | dxDateBox | | ✓ | | -| `InsuranceEnd` | Sigorta Bitiş | dxDateBox | | ✓ | | -| `EmissionStart` | Egzoz Muayene Başlangıç | dxDateBox | | ✓ | | -| `EmissionEnd` | Egzoz Muayene Bitiş | dxDateBox | | ✓ | | -| `TachographStart` | Takograf Kalib. Başlangıç | dxDateBox | | ✓ | | -| `TachographEnd` | Takograf Kalib. Bitiş | dxDateBox | | ✓ | | - -### Şoför Tanımlama — `App.Hr.Driver` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Driver.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.Driver` (sıra 5) | -| Yetki | `App.Hr.Driver` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Şoför Tanımlama — şirket araçlarını kullanan personel, zimmetli araçları ve sürüş geçmişi. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_Driver` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.DriverDocument` (Id → DriverId), `App.Hr.DriverPenalty` (Id → DriverId), `App.Hr.DriverAccident` (Id → DriverId) | -| Widget'lar | `App.Widget.Total`, `App.Hr.Driver.Widget.WithVehicle`, `App.Hr.Driver.Widget.TotalKm` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `UserId` | Sicil No / Adı Soyadı | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `Vehicle1Id` | Zimmetli Araç 1 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | -| `Vehicle2Id` | Zimmetli Araç 2 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | -| `Vehicle3Id` | Zimmetli Araç 3 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | -| `Vehicle4Id` | Zimmetli Araç 4 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | -| `Vehicle5Id` | Zimmetli Araç 5 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | -| `TotalKm` | Yapılan KM | dxNumberBox | | ✓ | | - -### Araç Giriş-Çıkış Takip — `App.Hr.VehicleMovement` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleMovement.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleMovement` (sıra 6) | -| Yetki | `App.Hr.VehicleMovement` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Araç Giriş-Çıkış Takip — güvenliğin tuttuğu araç hareket defteri: araç şirketten ne zaman, kimle, hangi km ile çıktı, ne zaman döndü. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleMovement` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Hr.Vehicle.Widget.Left`, `App.Widget.Today` | -| Komutlar | InsertAfter: SQL · DeleteAfter: SQL | -| Form varsayılanları | EntryKm=0 | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `MovementNo` | Hareket No | dxNumberBox | | | | -| `ExitDate` | Çıkış Tarihi | dxDateBox | ✓ | ✓ | script | -| `BranchId` | Çıkış Şube | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | -| `ExitTime` | Çıkış Saati | dxTextBox | ✓ | ✓ | script | -| `ExitKm` | Çıkış Km | dxNumberBox | ✓ | ✓ | script | -| `SenderUserId` | Gönderen Personel | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `SecurityUserId` | Güvenlik Personeli | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `DriverUserId` | Kullanan Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `VehicleId` | Araç Adı / Plaka | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Vehicle · script | -| `DestinationId` | Gidilen Yer | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDestination | -| `Reason` | Gidiş Sebebi | dxTextBox | | ✓ | | -| `Location` | Konum | dxTextBox | | ✓ | | -| `EntrySecurityUserId` | Giriş Yapan Güvenlik Per. | dxSelectBox | | ✓ | sorgu: AbpUsers | -| `EntryDate` | Giriş Tarihi | dxDateBox | | ✓ | script | -| `EntryBranchId` | Giriş Şube | dxSelectBox | | ✓ | sorgu: Sas_T_Branch | -| `EntryTime` | Giriş Saati | dxTextBox | | ✓ | script | -| `EntryKm` | Giriş Km | dxNumberBox | | ✓ | script | -| `TravelledKm` | Yapılan Km | dxNumberBox | | ✓ | | -| `Status` | Durum | dxSelectBox | | ✓ | liste: Arrived, Left | -| `DurationMinutes` | Gezinti Süresi / Dk | dxNumberBox | | ✓ | | -| `ExpectedKm` | Olması Gereken Km | dxNumberBox | | ✓ | | - -### Masraf Girişleri — `App.Hr.VehicleExpense` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleExpense.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleExpense` (sıra 7) | -| Yetki | `App.Hr.VehicleExpense` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Masraf Girişleri — araç için gelen her fatura/fiş: başlık bilgileri ve kalemleri. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleExpense` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Alt formlar | `App.Hr.VehicleExpenseLine` (Id → VehicleExpenseId) | -| Widget'lar | `App.Widget.Total`, `App.Widget.Today`, `App.Widget.TotalRevenue` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `VehicleId` | Araç Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_Vehicle | -| `InvoiceNo` | Fatura No | dxTextBox | ✓ | ✓ | | -| `InvoiceDate` | Fatura Tarihi | dxDateBox | ✓ | ✓ | script | -| `DestinationId` | Firma Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDestination | -| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | -| `FileName` | Dosya Adı | dxTextBox | | ✓ | | -| `FileContent` | Dosya | dxImageUpload | | ✓ | | - -### Araç Belgeleri — `App.Hr.VehicleFile` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleFile.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.VehicleFile` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Araç Dosyaları — araca yüklenen belgeler (ruhsat, poliçe, muayene raporu…). | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleFile` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `VehicleId` | Araç | dxSelectBox | | | sorgu: Hr_T_Vehicle | -| `VehicleDocumentId` | Belge Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleDocument | -| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | -| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | - -### Şoför Belgeleri — `App.Hr.DriverDocument` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DriverDocument.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DriverDocument` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Şoför Belgeleri — şoföre ait belgeler (sürücü belgesi, psikoteknik, SRC…). | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_DriverDocument` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | -| `VehicleDocumentId` | Belge Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleDocument | -| `FileName` | Dosya Adı | dxTextBox | ✓ | ✓ | | -| `FileContent` | Dosya | dxImageUpload | ✓ | ✓ | | - -### Ceza Belgeleri — `App.Hr.DriverPenalty` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DriverPenalty.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DriverPenalty` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Şoför Cezaları — şoföre kesilen trafik cezaları. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_DriverPenalty` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | -| `PenaltyDate` | Ceza Tarihi | dxDateBox | ✓ | ✓ | | -| `Amount` | Tutarı | dxNumberBox | | ✓ | | -| `Description` | Ceza Açıklama | dxTextBox | | ✓ | | -| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | -| `FileName` | Dosya Adı | dxTextBox | | ✓ | | -| `FileContent` | Dosya | dxImageUpload | | ✓ | | - -### Kaza Belgeleri — `App.Hr.DriverAccident` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/DriverAccident.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.DriverAccident` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Şoför Kazaları — şoförün karıştığı trafik kazaları ve belgeleri. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_DriverAccident` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `DriverId` | Şoför | dxSelectBox | | | sorgu: Hr_T_Driver | -| `AccidentDate` | Kaza Tarihi | dxDateBox | ✓ | ✓ | | -| `VehicleDocumentId` | Belge Adı | dxSelectBox | | ✓ | sorgu: Hr_T_VehicleDocument | -| `Description` | Kaza Açıklama | dxTextBox | | ✓ | | -| `FileName` | Dosya Adı | dxTextBox | | ✓ | | -| `FileContent` | Dosya | dxImageUpload | | ✓ | | - -### Masraf Kalemleri — `App.Hr.VehicleExpenseLine` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/VehicleExpenseLine.json` | -| Yol | Liste (Wizard) | -| Menü | Menüsüz (alt form) | -| Yetki | `App.Hr.VehicleExpenseLine` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Masraf Kalemleri — bir masraf faturasının satırları. | -| Geliştirme talebi | Human Resources -> Araçlar | -| Kaynak | `Hr_T_VehicleExpenseLine` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `VehicleExpenseId` | Masraf Girişi | dxTextBox | | | | -| `ExpenseDefinitionId` | Masraf Adı | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_VehicleExpenseDefinition | -| `DetailName` | Masraf Detay Adı | dxTextBox | | ✓ | | -| `Quantity` | Miktar | dxNumberBox | ✓ | ✓ | script | -| `Amount` | Tutarı | dxNumberBox | ✓ | ✓ | script | -| `DiscountRate` | İskonto Oranı (%) | dxNumberBox | ✓ | ✓ | script | -| `NetAmount` | Net Tutar | dxNumberBox | ✓ | ✓ | | -| `Description` | Masraf Açıklama | dxTextBox | | ✓ | | - - diff --git a/configs/seeds/docs/modules/HrVisitor.md b/configs/seeds/docs/modules/HrVisitor.md deleted file mode 100644 index 9b80526e..00000000 --- a/configs/seeds/docs/modules/HrVisitor.md +++ /dev/null @@ -1,150 +0,0 @@ -# İK › Ziyaretçiler (`App.Hr.Visitor`) - -Güvenlik/resepsiyon için ziyaretçi giriş–çıkış defteri: kim, hangi firmadan, kimi ziyarete, ne -zaman geldi, hangi kartı aldı, ne zaman çıktı. Tamamı konfigürasyondur (tek Wizard ekranı). - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| Güvenlik / resepsiyon | Ziyaretçiyi girişte kaydeder, kart verir, çıkışta çıkış saatini işler | Ziyaretçiler | -| İK / idari işler | Günlük ziyaretçi sayısını, içeride kalanları ve geçmişi izler | Ziyaretçiler (widget, Pivot) | - -Kapsam: kiracı (`IsTenant`). Her kayıt bir şubeye bağlıdır; satır süzmesi yoktur. - ---- - -## 2. Analiz ve kararlar - -> Modül §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar wizard ve SQL'den okunmuştur. - -| Konu | Karar | -| --- | --- | -| Yol | Tek Wizard liste ekranı | -| Ziyaretçi kimliği | Ziyaretçi ayrı bir kişi kartı değildir; her ziyaret satırında ad soyad serbest metindir (tekrar gelen ziyaretçi yeniden yazılır) | -| Firma | Serbest metin + **otomatik tamamlama** (daha önce girilen firma adlarından) | -| Ziyaretçi tipi | Sabit liste: Ziyaretçi, Müşteri, Tedarikçi, Taşeron, Kurye (değerler Türkçe anahtardır) | -| İçeride mi? | `ExitTime` boşsa ziyaretçi içeride sayılır | -| Bildirim | Ziyaret edilen personele bildirim **gönderilmez** | - ---- - -## 3. Menü ve ekran - -| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar (bugün) | -| --- | --- | --- | --- | --- | -| Ziyaretçiler / Visitors | `App.Hr.Visitor` | `İnsan Kaynakları` (sıra 12, `FcBusinessman`) | Grid, Card, Pivot, Chart | Bugün Gelen · İçeride · Çıkış Yapan | - -Widget'lar yalnız **bugünün** (`VisitDate = bugün`) kayıtlarını sayar. - ---- - -## 4. Veri modeli - -`Hr_T_Visitor` (`sql/object/Hr_T_Visitor.sql`, entity yok): - -| Kolon | Açıklama | -| --- | --- | -| `BranchId` | Şube (zorunlu) | -| `VisitorType` | Ziyaretçi tipi (varsayılan "Ziyaretçi") | -| `VisitDate` | Ziyaret tarihi | -| `EntryTime` / `ExitTime` | Giriş / çıkış zamanı (`datetime`) | -| `CardNo` | Verilen ziyaretçi kartı | -| `VisitorFullName` | Ziyaretçi adı soyadı (zorunlu) | -| `VisitedUserId` | Ziyaret edilen personel (`AbpUsers`, zorunlu) | -| `CompanyName` | Firma | -| `VisitReason` | Ziyaret sebebi | - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Yeni kayıt | Ziyaret tarihi bugün, giriş saati şimdi, tip "Ziyaretçi" | -| Çıkış | Kayıt düzenlenip çıkış saati girilir; otomatik çıkış yoktur | - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`; `App.Hr.Visitor` + `.Create/.Update/.Delete/.Export/.Import/.Note`. -Güvenliğe kök + `.Create/.Update` yeter. Hiçbir yetki role otomatik atanmaz. Ziyaretçi adı kişisel -veridir; saklama süresi için periyodik temizlik yoktur. - ---- - -## 7. Entegrasyonlar - -`Sas_T_Branch` (şube), `AbpUsers` (ziyaret edilen personel). Bildirim, rapor ya da zamanlanmış iş yoktur. - ---- - -## 8. Akış örneği - -1. Tedarikçi temsilcisi gelir; güvenlik yeni kayıt açar (tarih/saat dolu), tip Tedarikçi, ad soyad, - firma (otomatik tamamlamadan), ziyaret edilen satın alma uzmanı, kart no 12. -2. "İçeride" kartı 1 artar. -3. Çıkışta kayıt açılıp çıkış saati girilir; "Çıkış Yapan" kartı artar. - ---- - -## 9. Sık sorulanlar - -**Tekrar gelen ziyaretçinin bilgileri neden dolmuyor?** Ziyaretçi kartı yoktur; yalnız firma adı otomatik tamamlanır. - -**Gün sonunda içeride kalanlar nasıl görülür?** Bugünün "İçeride" kartı ya da `ExitTime` boş filtresi. - -**Ziyaret edilen kişiye haber gidiyor mu?** Hayır. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_Visitor.sql` | Tablo | -| `configs/seeds/wizard/Visitor.json` | Wizard | - -Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Ziyaretçiler — `App.Hr.Visitor` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Visitor.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr` › `App.Hr.Visitor` (sıra 12) | -| Yetki | `App.Hr.Visitor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Ziyaretçiler — güvenlik/resepsiyonun tuttuğu ziyaretçi giriş-çıkış defteri. | -| Geliştirme talebi | Human Resources -> Ziyaretçi Takip Listesi | -| Kaynak | `Hr_T_Visitor` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Hr.Visitor.Widget.Today`, `App.Hr.Visitor.Widget.Inside`, `App.Hr.Visitor.Widget.Exited` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `VisitDate` | Ziyaret Tarihi | dxDateBox | ✓ | ✓ | script | -| `VisitorType` | Ziyaretçi Tipi | dxSelectBox | ✓ | ✓ | liste: Ziyaretçi, Müşteri, Tedarikçi, Taşeron, Kurye · script | -| `EntryTime` | Giriş Saati | dxDateBox | ✓ | ✓ | script | -| `ExitTime` | Çıkış Saati | dxDateBox | | ✓ | | -| `CardNo` | Kart No | dxTextBox | | ✓ | | -| `VisitedUserId` | Ziyaret Edilen Personel | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers | -| `VisitorFullName` | Ziyaretçi Adı Soyadı | dxTextBox | ✓ | ✓ | | -| `CompanyName` | Firma Adı | dxAutocomplete | | ✓ | sorgu: Hr_T_Visitor | -| `VisitReason` | Ziyaret Sebebi | dxTextArea | | ✓ | | -| `BranchId` | Şube Adı | dxSelectBox | ✓ | ✓ | sorgu: Sas_T_Branch | - - diff --git a/configs/seeds/docs/modules/HrWorkCalendar.md b/configs/seeds/docs/modules/HrWorkCalendar.md deleted file mode 100644 index 778a870d..00000000 --- a/configs/seeds/docs/modules/HrWorkCalendar.md +++ /dev/null @@ -1,205 +0,0 @@ - -# İK › Çalışma Takvimi ve Vardiyalar (`App.Hr.WorkCalendar`, `App.Hr.Shift`) - -Çalışma zamanının iki temel tanımı: resmi tatil / yarım gün takvimi (yıllık tekrarlı ya da tek -seferlik) ve vardiya tanımları (saat aralığı, mola, gece vardiyası). Diğer modüller bu tanımları -lookup olarak kullanır. Tamamı konfigürasyondur (Wizard + seed); vardiya ayrıca kullanıcı kaydına -bağlanır. - -> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te -> buraya yansır (`lowcode.instructions.md` §0.13). - ---- - -## 1. Amaç ve kapsam - -| Persona | Ne yapar | Ekran | -| --- | --- | --- | -| İK | Yılın tatil ve yarım günlerini girer, takvim görünümünden kontrol eder | Çalışma Takvimi | -| İK / üretim planlama | Vardiya tanımlarını yönetir, çalışanı vardiyaya bağlar | Vardiyalar · Kimlik › Kullanıcılar | - -Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur — takvim kiracının tamamı için geçerlidir. - ---- - -## 2. Analiz ve kararlar - -> Modüller §0.13 kuralından önce üretildi; keşif turu kaydı yoktur. Kararlar artefaktlardan -> (wizard, seed, commit `130e23bc` "Disiplin Dosyaları, Çalışma Takvimi") okunmuştur. - -| Konu | Karar | -| --- | --- | -| Tatil tekrarı | Sabit tarihli resmi tatiller `RecurrenceRule = FREQ=YEARLY` ile **bir kez** girilir, her yıl tekrarlar; dini bayramlar ay takvimine bağlı olduğu için **her yıl ayrı** satırdır (tekrar kuralı boş) | -| Gün türü | `Holiday` (tam gün tatil) / `HalfDay` (arife, yarım gün) | -| Görünüm | Liste görünümlerine ek olarak **Scheduler** (takvim) görünümü; `AllDay` her zaman `true` | -| Vardiya saatleri | `StartTime` / `EndTime` `SS:dd` metin; çalışma süresi elle girilir (otomatik hesap yok) | -| Gece vardiyası | Bayrak (`IsNightShift`) — sağlık kartındaki "gece çalışabilir" sonucuyla birlikte değerlendirilir, otomatik kontrol yoktur | -| Vardiya bağı | Kullanıcı kaydında `ShiftId` alanı (`LookupQueryValues.TenantShiftValues`: "Ad (başlangıç-bitiş)") | -| Menü yeri | Çalışma Takvimi `İnsan Kaynakları` kökünde; Vardiyalar bir tanım olduğu için `İnsan Kaynakları › Tanımlamalar` altında (yetkisi de `App.Hr.Definitions`'ın altındadır) | - ---- - -## 3. Menü ve ekranlar - -| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | -| --- | --- | --- | --- | --- | -| Çalışma Takvimi / Work Calendar | `App.Hr.WorkCalendar` | `İnsan Kaynakları` (sıra 4, `FcCalendar`) | Grid, Card, Pivot, Chart, **Scheduler** | Toplam · Tatil · Yarım Gün | -| Vardiyalar / Shifts | `App.Hr.Shift` | `İnsan Kaynakları › Tanımlar` (sıra 11, `FcClock`) | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | - -Scheduler eşlemesi: metin `Name`, başlangıç `StartDate`, bitiş `EndDate`, tüm gün `AllDay`, -tekrar `RecurrenceRule`. - -Seed verisi: -- Çalışma takvimi, 16 satır (`data/App.Hr.WorkCalendar.json`): - - Yıllık tekrarlı tatiller: Yılbaşı, 23 Nisan, 1 Mayıs, 19 Mayıs, 15 Temmuz, 30 Ağustos, 29 Ekim. - - Yıllık tekrarlı yarım gün: 28 Ekim arifesi. - - Yıla özel satırlar: 2026 ve 2027 Ramazan/Kurban bayramları ve arifeleri. -- Vardiyalar, 3 satır (`data/App.Hr.Shift.json`): Sabah 08:00–16:00, Akşam 16:00–00:00, Gece 00:00–08:00 (gece vardiyası). - ---- - -## 4. Veri modeli - -| Tablo | Kolonlar | -| --- | --- | -| `Hr_T_WorkCalendar` | `Name`, `StartDate`, `EndDate`, `DayType` (Holiday/HalfDay), `RecurrenceRule` (boş / `FREQ=YEARLY`), `AllDay`, `IsActive` | -| `Hr_T_Shift` | `Name`, `StartTime`, `EndTime`, `BreakMinutes`, `LateToleranceMinutes`, `EarlyLeaveToleranceMinutes`, `WorkingHours`, `IsNightShift`, `IsActive` | -| `AbpUsers.ShiftId` | Çalışanın vardiyası (genişletme kolonu) | - -Entity yoktur (wizard tabloları); `sql/object/Hr_T_{WorkCalendar,Shift}.sql`. - ---- - -## 5. İş kuralları - -| Yer | Kural | -| --- | --- | -| Takvim — yeni kayıt | Gün türü `Holiday`, tekrar `FREQ=YEARLY`, tüm gün, aktif | -| Takvim — çok günlü tatil | Başlangıç–bitiş aralığı olarak tek satırda girilebilir | -| Vardiya — yeni kayıt | Gece vardiyası hayır, aktif | - -| Vardiya — toleranslar | Geç kalma / erken çıkış toleransı (dk); boşsa Ayarlar › İnsan Kaynakları › Puantaj'daki genel değer | - -Takvim İzin Yönetimi'nin gün sayısını (`HrLeave.md`), takvim ve vardiya Puantaj ve Devam Takibi'nin -gün tipini, vardiya saatini, molasını ve toleransını (`HrAttendance.md`) besler. - ---- - -## 6. Yetki ve görünürlük - -İzin grubu `App.Hr`, modül `Sas|Hr`. Her ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`. -Hiçbir yetki role otomatik atanmaz. Takvimin okunması tüm çalışanlara açılabilir; düzenleme İK'da kalmalıdır. - ---- - -## 7. Entegrasyonlar - -| Kullanan | Nasıl | -| --- | --- | -| Kimlik › Kullanıcılar | `ShiftId` alanı vardiya lookup'ı | -| Olay Günlüğü (`App.Hr.EventLog`) | Olay kaydında vardiya seçimi | -| Sağlık Kartları | Vardiyalı / gece çalışabilir sonucu (bilgi; vardiya tanımıyla otomatik eşleşmez) | -| İzin Yönetimi | Takvim tatilleri izin gününden düşülür (`Hr_F_LeaveWorkDays`). Takvim satırı eklenince/değişince/silinince denk gelen izinlerin gün sayısı yeniden hesaplanır (`Hr_S_WorkCalendarAfterSave`) | -| Puantaj ve Devam Takibi | Tatil → Resmî tatil, arife → yarım vardiya (`Hr_F_WorkCalendarDayType`); vardiya saat/mola/tolerans → `Hr_V_AttendanceShift`. Takvim kaydı ilgili günleri hemen yeniden hesaplar (kapalı ay hariç); vardiya değişikliği gece işinde ya da Puantaj Dönemleri kaydında yansır | - ---- - -## 8. Akış örneği - -1. Yıl başında İK **Çalışma Takvimi**'nde o yılın dini bayram satırlarını ekler (sabit tatiller zaten yıllık tekrarlıdır) ve Scheduler görünümünde yılı kontrol eder. -2. Üretim için **Vardiyalar**'a "Hafta Sonu 08:00–20:00, mola 60 dk, çalışma 11 saat" eklenir. -3. Kullanıcı ekranında çalışanların **Vardiya** alanı güncellenir; Olay Günlüğü kayıtlarında da bu vardiyalar seçilir. - ---- - -## 9. Sık sorulanlar ve bilinen sınırlar - -**Ramazan Bayramı gelecek yıl görünmüyor.** Dini bayramlar yıla özeldir; her yıl yeni satır girilir. - -**Çalışma süresi neden hesaplanmıyor?** Vardiya saatleri metindir, süre elle girilir. - -**Takvim izin/puantaj hesabını etkiliyor mu?** Evet: izin gün sayısından tatiller düşülür, puantajda tatil -günü Resmî tatil, arife yarım gün sayılır. Takvim satırı kaydedilince denk gelen günlerin izin gün sayısı ve -puantajı hemen yeniden hesaplanır (yıllık tekrarlı satırda bu yıl ve gelecek yıl; kapalı puantaj ayı yazılmaz). -Bir satırın tarihi değiştirildiğinde eski tarihlerin puantajı gece işinde ya da Puantaj Dönemleri kaydında düzelir. - -**Vardiyalar nerede?** `İnsan Kaynakları › Tanımlamalar` altında (sıra 11); menü satırı, wizard dosyası ve -yetki ağacı aynı yeri gösterir. - ---- - -## 10. Dosyalar ve geri alma - -| Dosya | İçerik | -| --- | --- | -| `configs/seeds/sql/object/Hr_T_{WorkCalendar,Shift}.sql` | Tablolar | -| `configs/seeds/wizard/{WorkCalendar,Shift}.json` | 2 wizard | -| `configs/seeds/data/App.Hr.{WorkCalendar,Shift}.json` | Takvim ve vardiya verisi (ekran kayıtları dosyaya aynalanır) | -| `api/src/Sozsoft.Platform.Application.Contracts/LookUpQueryValues.cs` (`TenantShiftValues`) | Kullanıcı ekranındaki vardiya lookup'ı | - -Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının lookup'ı tarafından okunduğu için düşürülmemelidir. - - -## Ek — Ekran envanteri (otomatik) - -> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. - -### Çalışma Takvimi — `App.Hr.WorkCalendar` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/WorkCalendar.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr` › `App.Hr.WorkCalendar` (sıra 4) | -| Yetki | `App.Hr.WorkCalendar` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Çalışma Takvimi — resmi tatiller, arife (yarım gün) ve çalışılmayan günler. | -| Kaynak | `Hr_T_WorkCalendar` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart, Scheduler (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Hr.WorkCalendar.DayType.Holiday`, `App.Hr.WorkCalendar.DayType.HalfDay` | -| Komutlar | InsertAfter: `Hr_S_WorkCalendarAfterSave` · UpdateAfter: `Hr_S_WorkCalendarAfterSave` · DeleteAfter: `Hr_S_WorkCalendarAfterSave` | -| Form varsayılanları | DayType=Holiday, RecurrenceRule=FREQ=YEARLY, AllDay=true, IsActive=true | -| Veri aynası | `data/App.Hr.WorkCalendar.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Adı | dxTextBox | ✓ | ✓ | | -| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | | -| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | | -| `DayType` | Gün Türü | dxSelectBox | ✓ | ✓ | liste: Holiday, HalfDay | -| `RecurrenceRule` | Tekrarlama Kuralı | dxSelectBox | | ✓ | liste: FREQ=YEARLY | -| `AllDay` | Tüm Gün | dxCheckBox | | | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - -### Vardiyalar — `App.Hr.Shift` - -| Özellik | Değer | -| --- | --- | -| Wizard | `wizard/Shift.json` | -| Yol | Liste (Wizard) | -| Menü | `App.Hr.Definitions` › `App.Hr.Shift` (sıra 11) | -| Yetki | `App.Hr.Shift` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | -| Açıklama | Vardiyalar — çalışma vardiyalarının tanımı (sabah, akşam, gece…). | -| Geliştirme talebi | Human Resources -> Olay Günlüğü | -| Kaynak | `Hr_T_Shift` · filtre `"IsDeleted" = 'false'` | -| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | -| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | -| Kapsam | Kiracı | -| Widget'lar | `App.Widget.Total`, `App.Widget.Active`, `App.Widget.Passive` | -| Form varsayılanları | IsNightShift=false, IsActive=true | -| Veri aynası | `data/App.Hr.Shift.json` | - -| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | -| --- | --- | --- | --- | --- | --- | -| `Name` | Vardiya Adı | dxTextBox | ✓ | ✓ | | -| `StartTime` | Başlangıç Saati | dxTextBox | | ✓ | | -| `EndTime` | Bitiş Saati | dxTextBox | | ✓ | | -| `BreakMinutes` | Mola (dk) | dxNumberBox | | ✓ | | -| `LateToleranceMinutes` | Geç Kalma Toleransı (dk) | dxNumberBox | | ✓ | | -| `EarlyLeaveToleranceMinutes` | Erken Çıkış Toleransı (dk) | dxNumberBox | | ✓ | | -| `WorkingHours` | Çalışma Süresi (Saat) | dxNumberBox | | ✓ | | -| `IsNightShift` | Gece Vardiyası | dxCheckBox | ✓ | ✓ | | -| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | - - diff --git a/configs/seeds/wizard/PerformanceReview.json b/configs/seeds/wizard/PerformanceReview.json index 5d932497..e4216ef5 100644 --- a/configs/seeds/wizard/PerformanceReview.json +++ b/configs/seeds/wizard/PerformanceReview.json @@ -32,8 +32,8 @@ "MenuTr": "Tüm Değerlendirmeler", "TitleEn": "All Reviews", "TitleTr": "Tüm Değerlendirmeler", - "DescEn": "All Reviews — every employee review of every period; HR follows and manages the process end to end here.\nWhere: Human Resources › Performance Management › All Reviews (HR only). The detail has Goals, Competencies, 360 Feedback and Development Plan tabs; the Todo view groups reviews by stage.\nStages: Goal Setting → Self Review → Manager Review → Calibration → Completed.\nFields:\n• Period, employee (department/position copied), manager → HR selects the reviewing manager\n• Scores → goal, competency, 360 average (info), overall, calibrated score and rating; calculated automatically\n• Self, manager and calibration comments; submission and completion dates\nAutomatic: scores are recalculated on every save. HR may make any stage change; leaving Goal Setting requires at least one goal with weights totalling 100. Transitions notify the employee/manager; on Completed manager levels are written to the employee's skill profile.\nRelated: My Reviews (employee), Team Reviews (manager), Calibration, Development Plans. Details: docs/modules/HrPerformance.md.", - "DescTr": "Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir.\nNerede: İnsan Kaynakları › Performans Yönetimi › Tüm Değerlendirmeler (yalnız İK). Detayda Hedefler, Yetkinlikler, 360 Derece ve Gelişim Planı sekmeleri; Todo görünümünde değerlendirmeler aşama sütunlarındadır.\nAşamalar: Hedef Belirleme → Öz Değerlendirme → Yönetici Değerlendirmesi → Kalibrasyon → Tamamlandı.\nAlanlar:\n• Dönem, çalışan (departman/pozisyon çalışandan dolar), yönetici → değerlendiren yöneticiyi İK seçer\n• Puanlar → hedef puanı, yetkinlik puanı, 360 ortalaması (bilgi), genel puan, kalibre puan ve derece; hesaplar otomatiktir\n• Öz değerlendirme, yönetici ve kalibrasyon yorumları; gönderim ve tamamlanma tarihleri\nOtomatik: her kayıtta puanlar yeniden hesaplanır. İK her aşama geçişini yapabilir; Hedef Belirleme'den çıkmak için ağırlık toplamı 100 olan en az bir hedef gerekir. Geçişlerde çalışana/yöneticiye bildirim gider; Tamamlandı'da yönetici seviyeleri çalışanın yetkinlik profiline yazılır.\nİlişkili: Değerlendirmelerim (çalışan), Ekibimin Değerlendirmeleri (yönetici), Kalibrasyon, Gelişim Planları. Ayrıntı: docs/modules/HrPerformance.md.", + "DescEn": "All Reviews — every employee review of every period; HR follows and manages the process end to end here.\nWhere: Human Resources › Performance Management › All Reviews (HR only). The detail has Goals, Competencies, 360 Feedback and Development Plan tabs; the Todo view groups reviews by stage.\nStages: Goal Setting → Self Review → Manager Review → Calibration → Completed.\nFields:\n• Period, employee (department/position copied), manager → HR selects the reviewing manager\n• Scores → goal, competency, 360 average (info), overall, calibrated score and rating; calculated automatically\n• Self, manager and calibration comments; submission and completion dates\nAutomatic: scores are recalculated on every save. HR may make any stage change; leaving Goal Setting requires at least one goal with weights totalling 100. Transitions notify the employee/manager; on Completed manager levels are written to the employee's skill profile.\nRelated: My Reviews (employee), Team Reviews (manager), Calibration, Development Plans. Details: docs/modules/App.Hr.md › Performans Yönetimi.", + "DescTr": "Tüm Değerlendirmeler — bütün dönemlerin bütün çalışan değerlendirmeleri; İK süreci uçtan uca buradan izler ve yönetir.\nNerede: İnsan Kaynakları › Performans Yönetimi › Tüm Değerlendirmeler (yalnız İK). Detayda Hedefler, Yetkinlikler, 360 Derece ve Gelişim Planı sekmeleri; Todo görünümünde değerlendirmeler aşama sütunlarındadır.\nAşamalar: Hedef Belirleme → Öz Değerlendirme → Yönetici Değerlendirmesi → Kalibrasyon → Tamamlandı.\nAlanlar:\n• Dönem, çalışan (departman/pozisyon çalışandan dolar), yönetici → değerlendiren yöneticiyi İK seçer\n• Puanlar → hedef puanı, yetkinlik puanı, 360 ortalaması (bilgi), genel puan, kalibre puan ve derece; hesaplar otomatiktir\n• Öz değerlendirme, yönetici ve kalibrasyon yorumları; gönderim ve tamamlanma tarihleri\nOtomatik: her kayıtta puanlar yeniden hesaplanır. İK her aşama geçişini yapabilir; Hedef Belirleme'den çıkmak için ağırlık toplamı 100 olan en az bir hedef gerekir. Geçişlerde çalışana/yöneticiye bildirim gider; Tamamlandı'da yönetici seviyeleri çalışanın yetkinlik profiline yazılır.\nİlişkili: Değerlendirmelerim (çalışan), Ekibimin Değerlendirmeleri (yönetici), Kalibrasyon, Gelişim Planları. Ayrıntı: docs/modules/App.Hr.md › Performans Yönetimi.", "Texts": [ { "Key": "App.Hr.PerformanceReview.Status.GoalSetting",