Puantaj ve DEvam Takibi

This commit is contained in:
Sedat ÖZTÜRK 2026-10-05 00:18:13 +03:00
parent 98eeea8dae
commit e6db756de3
90 changed files with 24121 additions and 472 deletions

View file

@ -1377,7 +1377,7 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `
| **Definitions › Leave Type** | `App.Hr.LeaveType` | `Hr_T_LeaveType` | tenant | İzin türü: `Code`, `Name`, `Gender` (`All`/`Male`/`Female`), `MaxDaysPerYear`, `IsPaid`, `DeductsFromAnnualLeave`, `RequiresDocument`, `AllowHalfDay`, `BalanceExceedAction` (`Block`/`Warn`), `IsActive`. İzin Yönetimi'nin tür kuralları; `Sick` kodlu tür Sağlık Kartı istirahatiyle eşlenir. Wizard `wizard/LeaveType.json`, tablo `sql/object/Hr_T_LeaveType.sql`, seed `data/App.Hr.LeaveType.json` (Türkiye standart izin türleri). | | **Definitions › Leave Type** | `App.Hr.LeaveType` | `Hr_T_LeaveType` | tenant | İzin türü: `Code`, `Name`, `Gender` (`All`/`Male`/`Female`), `MaxDaysPerYear`, `IsPaid`, `DeductsFromAnnualLeave`, `RequiresDocument`, `AllowHalfDay`, `BalanceExceedAction` (`Block`/`Warn`), `IsActive`. İzin Yönetimi'nin tür kuralları; `Sick` kodlu tür Sağlık Kartı istirahatiyle eşlenir. Wizard `wizard/LeaveType.json`, tablo `sql/object/Hr_T_LeaveType.sql`, seed `data/App.Hr.LeaveType.json` (Türkiye standart izin türleri). |
| **Definitions › Expense Type** | `App.Hr.ExpenseType` | `Hr_T_ExpenseType` | tenant | Masraf türü: `Code`, `Name`, `DefaultAmount`, `CurrencyId` (`Sas_H_Currency` lookup'ı), `IsTaxable`, `IsSgkSubject`, `RequiresReceipt`, `IsActive`. Masraf beyanı ekranlarının lookup'ı. Wizard `wizard/ExpenseType.json`, tablo `sql/object/Hr_T_ExpenseType.sql`, seed `data/App.Hr.ExpenseType.json`. | | **Definitions › Expense Type** | `App.Hr.ExpenseType` | `Hr_T_ExpenseType` | tenant | Masraf türü: `Code`, `Name`, `DefaultAmount`, `CurrencyId` (`Sas_H_Currency` lookup'ı), `IsTaxable`, `IsSgkSubject`, `RequiresReceipt`, `IsActive`. Masraf beyanı ekranlarının lookup'ı. Wizard `wizard/ExpenseType.json`, tablo `sql/object/Hr_T_ExpenseType.sql`, seed `data/App.Hr.ExpenseType.json`. |
| **Definitions › Benefit Type** | `App.Hr.BenefitType` | `Hr_T_BenefitType` | tenant | Yan hak türü: `Code`, `Name`, `DefaultAmount`, `CurrencyId`, `IsTaxable`, `IsSgkSubject`, `IsActive`. Kodu kullanıcının yan hak kaydında (`Adm_T_UserBenefit.BenefitType`, Identity › Users › Benefits) değer olarak saklanır; kod değiştirilirse eski kayıtlar eşleşmez. Wizard `wizard/BenefitType.json`, tablo `sql/object/Hr_T_BenefitType.sql`, seed `data/App.Hr.BenefitType.json`. | | **Definitions › Benefit Type** | `App.Hr.BenefitType` | `Hr_T_BenefitType` | tenant | Yan hak türü: `Code`, `Name`, `DefaultAmount`, `CurrencyId`, `IsTaxable`, `IsSgkSubject`, `IsActive`. Kodu kullanıcının yan hak kaydında (`Adm_T_UserBenefit.BenefitType`, Identity › Users › Benefits) değer olarak saklanır; kod değiştirilirse eski kayıtlar eşleşmez. Wizard `wizard/BenefitType.json`, tablo `sql/object/Hr_T_BenefitType.sql`, seed `data/App.Hr.BenefitType.json`. |
| **Shift** | `App.Hr.Shift` | `Hr_T_Shift` | tenant | Vardiya: `Name`, `StartTime`/`EndTime` (`HH:mm`), `BreakMinutes`, `WorkingHours`, `IsNightShift`, `IsActive`. Seed `data/App.Hr.Shift.json`. | | **Shift** | `App.Hr.Shift` | `Hr_T_Shift` | tenant | Vardiya: `Name`, `StartTime`/`EndTime` (`HH:mm`), `BreakMinutes`, `LateToleranceMinutes`/`EarlyLeaveToleranceMinutes` (boşsa Ayarlar › Puantaj), `WorkingHours`, `IsNightShift`, `IsActive`. Seed `data/App.Hr.Shift.json`. |
| **Event Log** | `App.Hr.EventLog` | `Hr_T_EventLog` | tenant | Olay günlüğü: vardiya amiri / güvenlik odası / gözlem odası gibi kaynakların (`LogSource` statik lookup) gün içi kayıtları — `BranchId`, `UserId` (olayı yaşayan), `EventDate`/`EventTime`, `Importance`, `ShiftId` (`Hr_T_Shift`), `Description`. Wizard `wizard/EventLog.json`, tablo `sql/object/Hr_T_EventLog.sql`. | | **Event Log** | `App.Hr.EventLog` | `Hr_T_EventLog` | tenant | Olay günlüğü: vardiya amiri / güvenlik odası / gözlem odası gibi kaynakların (`LogSource` statik lookup) gün içi kayıtları — `BranchId`, `UserId` (olayı yaşayan), `EventDate`/`EventTime`, `Importance`, `ShiftId` (`Hr_T_Shift`), `Description`. Wizard `wizard/EventLog.json`, tablo `sql/object/Hr_T_EventLog.sql`. |
| **Trainings › Training Type / Subject** | `App.Hr.TrainingType` · `App.Hr.TrainingSubject` | `Hr_T_TrainingType` · `Hr_T_TrainingSubject` | tenant | Eğitim türü (`Name`, `IsActive`) ve konusu (`TrainingTypeId`, `Name`, `IsEvaluated`, `IsActive`). Wizard; seed `data/App.Hr.{TrainingType,TrainingSubject}.json`. | | **Trainings › Training Type / Subject** | `App.Hr.TrainingType` · `App.Hr.TrainingSubject` | `Hr_T_TrainingType` · `Hr_T_TrainingSubject` | tenant | Eğitim türü (`Name`, `IsActive`) ve konusu (`TrainingTypeId`, `Name`, `IsEvaluated`, `IsActive`). Wizard; seed `data/App.Hr.{TrainingType,TrainingSubject}.json`. |
| **Trainings › Training** | `App.Hr.Training` (alt formlar `App.Hr.TrainingParticipant`, `App.Hr.TrainingFile`) | `Hr_T_Training` · `Hr_T_TrainingParticipant` · `Hr_T_TrainingFile` | tenant | Eğitim kaydı: tür → konu cascade (`TrainingSubjectId` ← `TrainingTypeId`), şube, tarih/saat + `TotalHours`, `Status` (`Open`/`Closed`), eğitmen/yer/kurum, kazandırdığı yetkinlikler (`SkillIds` — `dxTagBox`, `Hr_T_Skill`), maliyet kalemleri + `CostTotal`. Katılımcı alt formu kullanıcıyı `AbpUsers`'tan seçer, `HireDate`/`DepartmentId`/`JobPositionId` kopyalanır; `AttendanceStatus`, değerlendirme/sınav puanı. Dosya alt formu `DocumentTypeId` (`Hr_T_DocumentType`) taşır. Katılım belgesi `Raporlar` kategorisindeki "Katılım Belgesi" şablonudur (`App.Hr.TrainingParticipant`). Wizard. | | **Trainings › Training** | `App.Hr.Training` (alt formlar `App.Hr.TrainingParticipant`, `App.Hr.TrainingFile`) | `Hr_T_Training` · `Hr_T_TrainingParticipant` · `Hr_T_TrainingFile` | tenant | Eğitim kaydı: tür → konu cascade (`TrainingSubjectId` ← `TrainingTypeId`), şube, tarih/saat + `TotalHours`, `Status` (`Open`/`Closed`), eğitmen/yer/kurum, kazandırdığı yetkinlikler (`SkillIds` — `dxTagBox`, `Hr_T_Skill`), maliyet kalemleri + `CostTotal`. Katılımcı alt formu kullanıcıyı `AbpUsers`'tan seçer, `HireDate`/`DepartmentId`/`JobPositionId` kopyalanır; `AttendanceStatus`, değerlendirme/sınav puanı. Dosya alt formu `DocumentTypeId` (`Hr_T_DocumentType`) taşır. Katılım belgesi `Raporlar` kategorisindeki "Katılım Belgesi" şablonudur (`App.Hr.TrainingParticipant`). Wizard. |
@ -1397,6 +1397,7 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `
| **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. | | **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 | `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/host/docs/modules/HrPerformance.md`. Wizard + Custom Component (pano kutusu). | | **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 | `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/host/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; 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/host/docs/modules/HrLeave.md`. Wizard + Custom Component + küçük UI/motor eki. | | **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; 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/host/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; 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/host/docs/modules/HrAttendance.md`. 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. | | **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 › 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. | | **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. |
@ -1516,6 +1517,7 @@ alanları da doldurur (`lowcode` §0.9).
| "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 | | "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/host/docs/modules/HrPerformance.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/host/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/host/docs/modules/HrLeave.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/host/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/host/docs/modules/HrAttendance.md`) |
| "yapay zekâ cevaplasın" | Saas › Definitions › AiBot | Bot tanımı; `/admin/ai` bu tanımı kullanır | | "yapay zekâ cevaplasın" | Saas › Definitions › AiBot | Bot tanımı; `/admin/ai` bu tanımı kullanır |
### 12.7 Canlı referans uygulamalar ### 12.7 Canlı referans uygulamalar

View file

@ -949,6 +949,9 @@ custom component ile üretilmiştir: İK menüsü şartları ve takibi taşır,
Intranet panosundaki widget'lardan açılır; çalışma şekli [HrPerformance.md](configs/seeds/host/docs/modules/HrPerformance.md). Intranet panosundaki widget'lardan açılır; çalışma şekli [HrPerformance.md](configs/seeds/host/docs/modules/HrPerformance.md).
**İzin Yönetimi** (`App.Hr.Leave`) aynı kalıptadır (talep, Müdür → İK Grid Workflow onayı, İş Kanunu md.53 bakiyesi, **İ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/host/docs/modules/HrLeave.md). rapor ↔ Sağlık Kartı eşlemesi, kullanıcı detayında İzinler sekmesi); çalışma şekli [HrLeave.md](configs/seeds/host/docs/modules/HrLeave.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/host/docs/modules/HrAttendance.md).
**Yetki kodları** `PlatformConsts.AppCodes` içinde merkezî olarak tanımlıdır ve **Yetki kodları** `PlatformConsts.AppCodes` içinde merkezî olarak tanımlıdır ve
`configs/seeds/host/data/Abp.Identity.Permissions.json` ile seed edilir (gruplar: `configs/seeds/host/data/Abp.Identity.Permissions.json` ile seed edilir (gruplar:
@ -1216,6 +1219,7 @@ başlığındaki ⓘ simgesi ise ekranın kendi ayrıntılı açıklamasını g
| Performans Yönetimi | İK › Performans Yönetimi (`App.Hr.Performance`) | [HrPerformance.md](configs/seeds/host/docs/modules/HrPerformance.md) | | Performans Yönetimi | İK › Performans Yönetimi (`App.Hr.Performance`) | [HrPerformance.md](configs/seeds/host/docs/modules/HrPerformance.md) |
| İşe Alım | İK › İşe Alım (`App.Hr.Recruitment`) | [HrRecruitment.md](configs/seeds/host/docs/modules/HrRecruitment.md) | | İşe Alım | İK › İşe Alım (`App.Hr.Recruitment`) | [HrRecruitment.md](configs/seeds/host/docs/modules/HrRecruitment.md) |
| İzin Yönetimi | İK › İzin Yönetimi (`App.Hr.Leave`) | [HrLeave.md](configs/seeds/host/docs/modules/HrLeave.md) | | İzin Yönetimi | İK › İzin Yönetimi (`App.Hr.Leave`) | [HrLeave.md](configs/seeds/host/docs/modules/HrLeave.md) |
| Puantaj ve Devam Takibi | İK › Puantaj ve Devam Takibi (`App.Hr.Attendance`) | [HrAttendance.md](configs/seeds/host/docs/modules/HrAttendance.md) |
| Eğitimler | İK › Eğitimler (`App.Hr.Trainings`) | [HrTrainings.md](configs/seeds/host/docs/modules/HrTrainings.md) | | Eğitimler | İK › Eğitimler (`App.Hr.Trainings`) | [HrTrainings.md](configs/seeds/host/docs/modules/HrTrainings.md) |
| Araçlar | İK › Araçlar (`App.Hr.Vehicles`) | [HrVehicles.md](configs/seeds/host/docs/modules/HrVehicles.md) | | Araçlar | İK › Araçlar (`App.Hr.Vehicles`) | [HrVehicles.md](configs/seeds/host/docs/modules/HrVehicles.md) |
| Disiplin Dosyaları | İK › Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) | [HrDisciplinaryCase.md](configs/seeds/host/docs/modules/HrDisciplinaryCase.md) | | Disiplin Dosyaları | İK › Disiplin Dosyaları (`App.Hr.DisciplinaryCase`) | [HrDisciplinaryCase.md](configs/seeds/host/docs/modules/HrDisciplinaryCase.md) |

View file

@ -4465,7 +4465,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
}), }),
InsertAfterCommand = "EXEC dbo.Hr_S_LeaveSickLeaveSync @Id, @CreatorId", InsertAfterCommand = "EXEC dbo.Hr_S_LeaveSickLeaveSync @Id, @CreatorId",
UpdateAfterCommand = "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Adm_T_UserSickLeave WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveSickLeaveSync @_id, @LastModifierId", UpdateAfterCommand = "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Adm_T_UserSickLeave WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveSickLeaveSync @_id, @LastModifierId",
DeleteAfterCommand = "UPDATE Hr_T_LeaveRequest SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId WHERE SickLeaveId IN @Id AND IsDeleted = 0", DeleteAfterCommand = "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Adm_T_UserSickLeave WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveSickLeaveSync @_id, @DeleterId; END",
EditingOptionJson = DefaultEditingOptionJson(listFormName, 700, 450, true, true, true, true, false), EditingOptionJson = DefaultEditingOptionJson(listFormName, 700, 450, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto> EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
{ {

View file

@ -4509,7 +4509,7 @@
"Name": "App.Hr.SkillType", "Name": "App.Hr.SkillType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.SkillType", "DisplayName": "App.Hr.SkillType",
"Order": 1, "Order": 3,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 2, "MultiTenancySide": 2,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4579,7 +4579,7 @@
"Name": "App.Hr.SkillLevel", "Name": "App.Hr.SkillLevel",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.SkillLevel", "DisplayName": "App.Hr.SkillLevel",
"Order": 2, "Order": 4,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 2, "MultiTenancySide": 2,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4639,7 +4639,7 @@
"Name": "App.Hr.Skill", "Name": "App.Hr.Skill",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Skill", "DisplayName": "App.Hr.Skill",
"Order": 3, "Order": 5,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 2, "MultiTenancySide": 2,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4699,7 +4699,7 @@
"Name": "App.Hr.Department", "Name": "App.Hr.Department",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Department", "DisplayName": "App.Hr.Department",
"Order": 4, "Order": 1,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4759,7 +4759,7 @@
"Name": "App.Hr.JobPosition", "Name": "App.Hr.JobPosition",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.JobPosition", "DisplayName": "App.Hr.JobPosition",
"Order": 5, "Order": 2,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4819,7 +4819,7 @@
"Name": "App.Hr.OrgChart", "Name": "App.Hr.OrgChart",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.OrgChart", "DisplayName": "App.Hr.OrgChart",
"Order": 3, "Order": 2,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -4829,7 +4829,7 @@
"Name": "App.Hr.Doctor", "Name": "App.Hr.Doctor",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Doctor", "DisplayName": "App.Hr.Doctor",
"Order": 6, "Order": 15,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -4899,7 +4899,7 @@
"Name": "App.Hr.Certificate", "Name": "App.Hr.Certificate",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Certificate", "DisplayName": "App.Hr.Certificate",
"Order": 7, "Order": 6,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -4969,7 +4969,7 @@
"Name": "App.Hr.Hospital", "Name": "App.Hr.Hospital",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Hospital", "DisplayName": "App.Hr.Hospital",
"Order": 8, "Order": 16,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -5039,7 +5039,7 @@
"Name": "App.Hr.HospitalDepartment", "Name": "App.Hr.HospitalDepartment",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.HospitalDepartment", "DisplayName": "App.Hr.HospitalDepartment",
"Order": 9, "Order": 17,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -5109,7 +5109,7 @@
"Name": "App.Hr.DocumentType", "Name": "App.Hr.DocumentType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.DocumentType", "DisplayName": "App.Hr.DocumentType",
"Order": 10, "Order": 7,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -5179,7 +5179,7 @@
"Name": "App.Hr.Visitor", "Name": "App.Hr.Visitor",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Visitor", "DisplayName": "App.Hr.Visitor",
"Order": 4, "Order": 19,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -5739,7 +5739,7 @@
"Name": "App.Hr.HealthCard", "Name": "App.Hr.HealthCard",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.HealthCard", "DisplayName": "App.Hr.HealthCard",
"Order": 12, "Order": 11,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -5809,7 +5809,7 @@
"Name": "App.Hr.Trainings", "Name": "App.Hr.Trainings",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Trainings", "DisplayName": "App.Hr.Trainings",
"Order": 13, "Order": 12,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6169,7 +6169,7 @@
"Name": "App.Hr.Vehicles", "Name": "App.Hr.Vehicles",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Vehicles", "DisplayName": "App.Hr.Vehicles",
"Order": 14, "Order": 18,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6319,7 +6319,7 @@
"Name": "App.Hr.Vehicle", "Name": "App.Hr.Vehicle",
"ParentName": "App.Hr.Vehicles", "ParentName": "App.Hr.Vehicles",
"DisplayName": "App.Hr.Vehicle", "DisplayName": "App.Hr.Vehicle",
"Order": 2, "Order": 4,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6669,7 +6669,7 @@
"Name": "App.Hr.Driver", "Name": "App.Hr.Driver",
"ParentName": "App.Hr.Vehicles", "ParentName": "App.Hr.Vehicles",
"DisplayName": "App.Hr.Driver", "DisplayName": "App.Hr.Driver",
"Order": 4, "Order": 5,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6739,7 +6739,7 @@
"Name": "App.Hr.VehicleExpenseDefinition", "Name": "App.Hr.VehicleExpenseDefinition",
"ParentName": "App.Hr.Vehicles", "ParentName": "App.Hr.Vehicles",
"DisplayName": "App.Hr.VehicleExpenseDefinition", "DisplayName": "App.Hr.VehicleExpenseDefinition",
"Order": 5, "Order": 2,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6879,7 +6879,7 @@
"Name": "App.Hr.VehicleExpense", "Name": "App.Hr.VehicleExpense",
"ParentName": "App.Hr.Vehicles", "ParentName": "App.Hr.Vehicles",
"DisplayName": "App.Hr.VehicleExpense", "DisplayName": "App.Hr.VehicleExpense",
"Order": 6, "Order": 7,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -6949,7 +6949,7 @@
"Name": "App.Hr.VehicleMovement", "Name": "App.Hr.VehicleMovement",
"ParentName": "App.Hr.Vehicles", "ParentName": "App.Hr.Vehicles",
"DisplayName": "App.Hr.VehicleMovement", "DisplayName": "App.Hr.VehicleMovement",
"Order": 7, "Order": 6,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -7019,7 +7019,7 @@
"Name": "App.Hr.Shift", "Name": "App.Hr.Shift",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.Shift", "DisplayName": "App.Hr.Shift",
"Order": 11, "Order": 13,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -7089,7 +7089,7 @@
"Name": "App.Hr.EventLog", "Name": "App.Hr.EventLog",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.EventLog", "DisplayName": "App.Hr.EventLog",
"Order": 15, "Order": 20,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -7159,7 +7159,7 @@
"Name": "App.Hr.Intranet", "Name": "App.Hr.Intranet",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Intranet", "DisplayName": "App.Hr.Intranet",
"Order": 16, "Order": 21,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -7169,7 +7169,7 @@
"Name": "App.Hr.Intranet.Announcement", "Name": "App.Hr.Intranet.Announcement",
"ParentName": "App.Hr.Intranet", "ParentName": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet.Announcement", "DisplayName": "App.Hr.Intranet.Announcement",
"Order": 1, "Order": 3,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -7369,7 +7369,7 @@
"Name": "App.Hr.Intranet.Survey", "Name": "App.Hr.Intranet.Survey",
"ParentName": "App.Hr.Intranet", "ParentName": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet.Survey", "DisplayName": "App.Hr.Intranet.Survey",
"Order": 2, "Order": 4,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -7709,7 +7709,7 @@
"Name": "App.Hr.Intranet.SocialPost", "Name": "App.Hr.Intranet.SocialPost",
"ParentName": "App.Hr.Intranet", "ParentName": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet.SocialPost", "DisplayName": "App.Hr.Intranet.SocialPost",
"Order": 3, "Order": 5,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -8029,7 +8029,7 @@
"Name": "App.Hr.Intranet.Events.EventType", "Name": "App.Hr.Intranet.Events.EventType",
"ParentName": "App.Hr.Intranet", "ParentName": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet.Events.EventType", "DisplayName": "App.Hr.Intranet.Events.EventType",
"Order": 4, "Order": 1,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -8089,7 +8089,7 @@
"Name": "App.Hr.Intranet.Events.EventCategory", "Name": "App.Hr.Intranet.Events.EventCategory",
"ParentName": "App.Hr.Intranet", "ParentName": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet.Events.EventCategory", "DisplayName": "App.Hr.Intranet.Events.EventCategory",
"Order": 5, "Order": 2,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -8389,7 +8389,7 @@
"Name": "App.Hr.LeaveType", "Name": "App.Hr.LeaveType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.LeaveType", "DisplayName": "App.Hr.LeaveType",
"Order": 12, "Order": 14,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -8459,7 +8459,7 @@
"Name": "App.Hr.ExpenseType", "Name": "App.Hr.ExpenseType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.ExpenseType", "DisplayName": "App.Hr.ExpenseType",
"Order": 13, "Order": 11,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -8529,7 +8529,7 @@
"Name": "App.Hr.BenefitType", "Name": "App.Hr.BenefitType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.BenefitType", "DisplayName": "App.Hr.BenefitType",
"Order": 14, "Order": 12,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -8599,7 +8599,7 @@
"Name": "App.Hr.WorkCalendar", "Name": "App.Hr.WorkCalendar",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.WorkCalendar", "DisplayName": "App.Hr.WorkCalendar",
"Order": 2, "Order": 4,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -8669,7 +8669,7 @@
"Name": "App.Hr.DisciplinaryPenaltyType", "Name": "App.Hr.DisciplinaryPenaltyType",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.DisciplinaryPenaltyType", "DisplayName": "App.Hr.DisciplinaryPenaltyType",
"Order": 15, "Order": 19,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Hr" "Modules": "Hr"
@ -9019,7 +9019,7 @@
"Name": "App.Hr.Recruitment", "Name": "App.Hr.Recruitment",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Recruitment", "DisplayName": "App.Hr.Recruitment",
"Order": 18, "Order": 3,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -9029,7 +9029,7 @@
"Name": "App.Hr.CandidateSource", "Name": "App.Hr.CandidateSource",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.CandidateSource", "DisplayName": "App.Hr.CandidateSource",
"Order": 16, "Order": 8,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -9099,7 +9099,7 @@
"Name": "App.Hr.RejectionReason", "Name": "App.Hr.RejectionReason",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.RejectionReason", "DisplayName": "App.Hr.RejectionReason",
"Order": 17, "Order": 9,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -9169,7 +9169,7 @@
"Name": "App.Hr.EvaluationCriterion", "Name": "App.Hr.EvaluationCriterion",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.EvaluationCriterion", "DisplayName": "App.Hr.EvaluationCriterion",
"Order": 18, "Order": 10,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -9729,7 +9729,7 @@
"Name": "App.Hr.PerformanceRating", "Name": "App.Hr.PerformanceRating",
"ParentName": "App.Hr.Definitions", "ParentName": "App.Hr.Definitions",
"DisplayName": "App.Hr.PerformanceRating", "DisplayName": "App.Hr.PerformanceRating",
"Order": 19, "Order": 18,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -9869,7 +9869,7 @@
"Name": "App.Hr.Performance", "Name": "App.Hr.Performance",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Performance", "DisplayName": "App.Hr.Performance",
"Order": 20, "Order": 13,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -10579,7 +10579,7 @@
"Name": "App.Hr.MyPerformanceReview", "Name": "App.Hr.MyPerformanceReview",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.MyPerformanceReview", "DisplayName": "App.Hr.MyPerformanceReview",
"Order": 21, "Order": 14,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -10859,7 +10859,7 @@
"Name": "App.Hr.TeamPerformanceReview", "Name": "App.Hr.TeamPerformanceReview",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.TeamPerformanceReview", "DisplayName": "App.Hr.TeamPerformanceReview",
"Order": 22, "Order": 15,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -10999,7 +10999,7 @@
"Name": "App.Hr.My360Feedback", "Name": "App.Hr.My360Feedback",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.My360Feedback", "DisplayName": "App.Hr.My360Feedback",
"Order": 23, "Order": 16,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -11209,7 +11209,7 @@
"Name": "App.Hr.Leave", "Name": "App.Hr.Leave",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.Leave", "DisplayName": "App.Hr.Leave",
"Order": 24, "Order": 5,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -11499,7 +11499,7 @@
"Name": "App.Hr.MyLeaveRequest", "Name": "App.Hr.MyLeaveRequest",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.MyLeaveRequest", "DisplayName": "App.Hr.MyLeaveRequest",
"Order": 25, "Order": 6,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -11569,7 +11569,7 @@
"Name": "App.Hr.MyLeaveBalance", "Name": "App.Hr.MyLeaveBalance",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.MyLeaveBalance", "DisplayName": "App.Hr.MyLeaveBalance",
"Order": 26, "Order": 7,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -11639,7 +11639,7 @@
"Name": "App.Hr.TeamLeaveRequest", "Name": "App.Hr.TeamLeaveRequest",
"ParentName": null, "ParentName": null,
"DisplayName": "App.Hr.TeamLeaveRequest", "DisplayName": "App.Hr.TeamLeaveRequest",
"Order": 27, "Order": 8,
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
@ -11723,6 +11723,446 @@
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"Modules": "Sas|Hr" "Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Attendance",
"ParentName": null,
"DisplayName": "App.Hr.Attendance",
"Order": 9,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Administration",
"Name": "App.HrSettings.Attendance",
"ParentName": "App.HrSettings",
"DisplayName": "App.HrSettings.Attendance",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog",
"ParentName": "App.Hr.Attendance",
"DisplayName": "App.Hr.AttendanceLog",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Create",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Update",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Delete",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Export",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Import",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.AttendanceLog.Note",
"ParentName": "App.Hr.AttendanceLog",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet",
"ParentName": "App.Hr.Attendance",
"DisplayName": "App.Hr.Timesheet",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Create",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Update",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Delete",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Export",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Import",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.Timesheet.Note",
"ParentName": "App.Hr.Timesheet",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly",
"ParentName": "App.Hr.Attendance",
"DisplayName": "App.Hr.TimesheetMonthly",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Create",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Update",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Delete",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Export",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Import",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetMonthly.Note",
"ParentName": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod",
"ParentName": "App.Hr.Attendance",
"DisplayName": "App.Hr.TimesheetPeriod",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Create",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Update",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Delete",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Export",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Import",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.TimesheetPeriod.Note",
"ParentName": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet",
"ParentName": null,
"DisplayName": "App.Hr.MyTimesheet",
"Order": 10,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Create",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Update",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Delete",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Export",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Import",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheet.Note",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay",
"ParentName": "App.Hr.MyTimesheet",
"DisplayName": "App.Hr.MyTimesheetDay",
"Order": 7,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Create",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Create",
"Order": 1,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Update",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Update",
"Order": 2,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Delete",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Delete",
"Order": 3,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Export",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Export",
"Order": 4,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Import",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Import",
"Order": 5,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
},
{
"GroupName": "App.Hr",
"Name": "App.Hr.MyTimesheetDay.Note",
"ParentName": "App.Hr.MyTimesheetDay",
"DisplayName": "App.Platform.Note",
"Order": 6,
"IsEnabled": true,
"MultiTenancySide": 3,
"Modules": "Sas|Hr"
} }
] ]
} }

View file

@ -52,6 +52,16 @@
"BeforeSp": null, "BeforeSp": null,
"AfterSp": null, "AfterSp": null,
"IsActive": true "IsActive": true
},
{
"Id": "34037693-7614-5ffe-a4ac-42d95bd68faa",
"Name": "Timesheet Nightly",
"Cron": "0 2 * * *",
"WorkerType": 2,
"Scope": 3,
"BeforeSp": "Hr_S_TimesheetNightly",
"AfterSp": null,
"IsActive": true
} }
] ]
} }

File diff suppressed because one or more lines are too long

View file

@ -11,7 +11,7 @@
"Description": "Intranet panosu: departman müdürünün onayını bekleyen izin talepleri ve bugün izinde olanlar", "Description": "Intranet panosu: departman müdürünün onayını bekleyen izin talepleri ve bugün izinde olanlar",
"IsActive": true, "IsActive": true,
"Dependencies": [], "Dependencies": [],
"Code": "// Departman muduru icin ekibin izin ozeti. Satirlar ekranin kendi sorgusundan gelir: liste\n// yalniz muduru oldugu departmanin taleplerini dondurur (ManagerIds suzmesi ListForm'da).\nconst REQUESTS = 'App.Hr.TeamLeaveRequest'\nconst MANAGER_STEP = 'Müdür Onayı'\nconst APPROVED = 'Onaylandı'\n\nconst loadRows = async (listFormCode) => {\n const response = await apiService.fetchData({\n method: 'GET',\n url: '/api/app/list-form-select/select',\n params: { listFormCode, take: 500 },\n })\n return response.data?.data ?? []\n}\n\nconst formatDays = (value) => {\n const number = Number(value ?? 0)\n return Number.isInteger(number) ? String(number) : number.toFixed(1)\n}\n\nconst formatDate = (value) => {\n if (!value) return '-'\n const [year, month, day] = String(value).slice(0, 10).split('-')\n return `${day}.${month}.${year}`\n}\n\nconst Stat = ({ label, value, className }) => (\n <div className=\"rounded-lg border border-gray-200 bg-gray-50 p-2 text-center dark:border-gray-700 dark:bg-gray-900/40\">\n <div className={`text-lg font-semibold ${className}`}>{value}</div>\n <div className=\"truncate text-xs text-gray-500 dark:text-gray-400\">{label}</div>\n </div>\n)\n\nconst TeamLeaveWidget = () => {\n const [rows, setRows] = useState([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n let active = true\n loadRows(REQUESTS)\n .then((result) => active && setRows(result))\n .catch(() => {})\n .finally(() => active && setLoading(false))\n return () => {\n active = false\n }\n }, [])\n\n const today = new Date().toISOString().slice(0, 10)\n const awaiting = rows\n .filter((row) => row.ApprovalStatus === MANAGER_STEP)\n .sort((a, b) => String(a.StartDate).localeCompare(String(b.StartDate)))\n const onLeave = rows.filter(\n (row) =>\n row.ApprovalStatus === APPROVED &&\n String(row.StartDate).slice(0, 10) <= today &&\n String(row.EndDate).slice(0, 10) >= today,\n )\n\n return (\n <div className=\"overflow-hidden rounded-xl border border-gray-200/50 bg-white shadow-lg dark:border-gray-700/50 dark:bg-gray-800\">\n <div className=\"flex items-center gap-2 border-b border-gray-200 p-4 dark:border-gray-700\">\n <PlatformIcon name=\"FaUserCheck\" className=\"h-5 w-5 text-indigo-500\" />\n <h2 className=\"text-base font-semibold text-gray-900 dark:text-white\">\n {translate('::App.DashboardWidget.TeamLeave')}\n </h2>\n </div>\n <div className=\"space-y-3 p-3\">\n {loading ? (\n <div className=\"p-4 text-center text-sm text-gray-500\">...</div>\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-2\">\n <Stat\n label={translate('::App.DashboardWidget.Leave.AwaitingMe')}\n value={awaiting.length}\n className=\"text-orange-500\"\n />\n <Stat\n label={translate('::App.DashboardWidget.Leave.OnLeaveToday')}\n value={onLeave.length}\n className=\"text-indigo-600 dark:text-indigo-400\"\n />\n </div>\n {awaiting.length === 0 ? (\n <div className=\"text-sm text-gray-500 dark:text-gray-400\">\n {translate('::App.DashboardWidget.Leave.NoPending')}\n </div>\n ) : (\n <ul className=\"space-y-1\">\n {awaiting.slice(0, 5).map((row) => (\n <li\n key={row.Id}\n className=\"flex items-center justify-between gap-2 rounded-md bg-gray-50 px-2 py-1 text-xs dark:bg-gray-900/40\"\n >\n <span className=\"truncate font-medium text-gray-800 dark:text-gray-100\">{row.EmployeeName}</span>\n <span className=\"shrink-0 text-gray-600 dark:text-gray-300\">\n {formatDate(row.StartDate)} · {formatDays(row.Days)} {translate('::App.DashboardWidget.Leave.Days')}\n </span>\n </li>\n ))}\n </ul>\n )}\n </>\n )}\n <div className=\"pt-1\">\n <a\n href={'/admin/list/' + REQUESTS}\n className=\"text-sm font-medium text-indigo-600 hover:underline dark:text-indigo-400\"\n >\n {translate('::App.DashboardWidget.Leave.OpenApprovals')} →\n </a>\n </div>\n </div>\n </div>\n )\n}\n\nexport default TeamLeaveWidget\n", "Code": "// Departman muduru icin ekibin izin ozeti. Satirlar ekranin kendi sorgusundan gelir: liste\n// yalniz muduru oldugu departmanin taleplerini dondurur (ManagerIds suzmesi ListForm'da).\nconst REQUESTS = 'App.Hr.TeamLeaveRequest'\nconst MANAGER_STEP = 'Müdür Onayı'\nconst APPROVED = 'Onaylandı'\n\nconst loadRows = async (listFormCode) => {\n const response = await apiService.fetchData({\n method: 'GET',\n url: '/api/app/list-form-select/select',\n params: { listFormCode, take: 500 },\n })\n return response.data?.data ?? []\n}\n\nconst formatDays = (value) => {\n const number = Number(value ?? 0)\n return Number.isInteger(number) ? String(number) : number.toFixed(1)\n}\n\nconst formatDate = (value) => {\n if (!value) return '-'\n const [year, month, day] = String(value).slice(0, 10).split('-')\n return `${day}.${month}.${year}`\n}\n\nconst Stat = ({ label, value, className }) => (\n <div className=\"rounded-lg border border-gray-200 bg-gray-50 p-2 text-center dark:border-gray-700 dark:bg-gray-900/40\">\n <div className={'text-lg font-semibold ' + className}>{value}</div>\n <div className=\"truncate text-xs text-gray-500 dark:text-gray-400\">{label}</div>\n </div>\n)\n\nconst TeamLeaveWidget = () => {\n const [rows, setRows] = useState([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n let active = true\n loadRows(REQUESTS)\n .then((result) => active && setRows(result))\n .catch(() => {})\n .finally(() => active && setLoading(false))\n return () => {\n active = false\n }\n }, [])\n\n const today = new Date().toISOString().slice(0, 10)\n const awaiting = rows\n .filter((row) => row.ApprovalStatus === MANAGER_STEP)\n .sort((a, b) => String(a.StartDate).localeCompare(String(b.StartDate)))\n const onLeave = rows.filter(\n (row) =>\n row.ApprovalStatus === APPROVED &&\n String(row.StartDate).slice(0, 10) <= today &&\n String(row.EndDate).slice(0, 10) >= today,\n )\n\n return (\n <div className=\"overflow-hidden rounded-xl border border-gray-200/50 bg-white shadow-lg dark:border-gray-700/50 dark:bg-gray-800\">\n <div className=\"flex items-center gap-2 border-b border-gray-200 p-4 dark:border-gray-700\">\n <PlatformIcon name=\"FaUserCheck\" className=\"h-5 w-5 text-indigo-500\" />\n <h2 className=\"text-base font-semibold text-gray-900 dark:text-white\">\n {translate('::App.DashboardWidget.TeamLeave')}\n </h2>\n </div>\n <div className=\"space-y-3 p-3\">\n {loading ? (\n <div className=\"p-4 text-center text-sm text-gray-500\">...</div>\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-2\">\n <Stat\n label={translate('::App.DashboardWidget.Leave.AwaitingMe')}\n value={awaiting.length}\n className=\"text-orange-500\"\n />\n <Stat\n label={translate('::App.DashboardWidget.Leave.OnLeaveToday')}\n value={onLeave.length}\n className=\"text-indigo-600 dark:text-indigo-400\"\n />\n </div>\n {awaiting.length === 0 ? (\n <div className=\"text-sm text-gray-500 dark:text-gray-400\">\n {translate('::App.DashboardWidget.Leave.NoPending')}\n </div>\n ) : (\n <ul className=\"space-y-1\">\n {awaiting.slice(0, 5).map((row) => (\n <li\n key={row.Id}\n className=\"flex items-center justify-between gap-2 rounded-md bg-gray-50 px-2 py-1 text-xs dark:bg-gray-900/40\"\n >\n <span className=\"truncate font-medium text-gray-800 dark:text-gray-100\">{row.EmployeeName}</span>\n <span className=\"shrink-0 text-gray-600 dark:text-gray-300\">\n {formatDate(row.StartDate)} · {formatDays(row.Days)} {translate('::App.DashboardWidget.Leave.Days')}\n </span>\n </li>\n ))}\n </ul>\n )}\n </>\n )}\n <div className=\"pt-1\">\n <a\n href={'/admin/list/' + REQUESTS}\n className=\"text-sm font-medium text-indigo-600 hover:underline dark:text-indigo-400\"\n >\n {translate('::App.DashboardWidget.Leave.OpenApprovals')} →\n </a>\n </div>\n </div>\n </div>\n )\n}\n\nexport default TeamLeaveWidget\n",
"Props": null, "Props": null,
"DataSources": [], "DataSources": [],
"SeoTitle": null, "SeoTitle": null,

View file

@ -13,6 +13,17 @@
"Sql": "SELECT * FROM Sas_H_Language WHERE IsEnabled = @IsEnabled AND CultureName = @CultureName", "Sql": "SELECT * FROM Sas_H_Language WHERE IsEnabled = @IsEnabled AND CultureName = @CultureName",
"ParametersJson": "[{\"Type\":\"Path\",\"Name\":\"CultureName\",\"DefaultValue\":\"ar\",\"Path\":\"/dil/:CultureName/\",\"IsRequired\":false},{\"Type\":\"Static\",\"Name\":\"IsEnabled\",\"DefaultValue\":\"true\",\"Path\":null,\"IsRequired\":false}]", "ParametersJson": "[{\"Type\":\"Path\",\"Name\":\"CultureName\",\"DefaultValue\":\"ar\",\"Path\":\"/dil/:CultureName/\",\"IsRequired\":false},{\"Type\":\"Static\",\"Name\":\"IsEnabled\",\"DefaultValue\":\"true\",\"Path\":null,\"IsRequired\":false}]",
"PermissionsJson": "[{\"ResourceType\":\"User\",\"ResourceId\":\"system@sozsoft.com\"}]" "PermissionsJson": "[{\"ResourceType\":\"User\",\"ResourceId\":\"system@sozsoft.com\"}]"
},
{
"Id": "3c8b861f-abfa-5db3-8d93-8c1a08605ac5",
"Name": "HrAttendancePdks",
"Description": "PDKS hareket aktarımı: POST /api/app/custom-endpoint/hr/attendance/ { \"Items\": [{ \"CardNo\", \"UserName\", \"EventTime\", \"Direction\", \"DeviceCode\" }] }",
"Url": "/hr/attendance/",
"Method": "POST",
"DataSourceCode": "Default",
"Sql": "EXEC dbo.Hr_S_AttendanceImport @TenantId, @UserId, @Items",
"ParametersJson": "[{\"Type\":\"Static\",\"Name\":\"TenantId\",\"DefaultValue\":\"@TENANTID\",\"Path\":null,\"IsRequired\":false},{\"Type\":\"Static\",\"Name\":\"UserId\",\"DefaultValue\":\"@USERID\",\"Path\":null,\"IsRequired\":false},{\"Type\":\"Body\",\"Name\":\"Items\",\"DefaultValue\":\"\",\"Path\":null,\"IsRequired\":true}]",
"PermissionsJson": "[{\"ResourceType\":\"Role\",\"ResourceId\":\"PDKS\"}]"
} }
] ]
} }

View file

@ -145,6 +145,19 @@
"Order": 36, "Order": 36,
"Props": "", "Props": "",
"IsActive": true "IsActive": true
},
{
"Id": "23c5bd91-f801-5204-bee4-7fe62118f327",
"Code": "my-timesheet",
"Name": "My Timesheet",
"LabelKey": "App.DashboardWidget.MyTimesheet",
"SourceType": 1,
"ComponentName": "MyTimesheetWidget",
"PermissionName": "App.Hr.MyTimesheet",
"Column": 0,
"Order": 37,
"Props": "",
"IsActive": true
} }
] ]
} }

File diff suppressed because it is too large Load diff

View file

@ -1343,7 +1343,7 @@
"Id": "eb9c8310-8498-4963-ba4d-8e56bcb42b5b", "Id": "eb9c8310-8498-4963-ba4d-8e56bcb42b5b",
"Code": "App.Hr.SkillType", "Code": "App.Hr.SkillType",
"DisplayName": "App.Hr.SkillType", "DisplayName": "App.Hr.SkillType",
"Order": 1, "Order": 3,
"Url": "/admin/list/App.Hr.SkillType", "Url": "/admin/list/App.Hr.SkillType",
"Icon": "FcMindMap", "Icon": "FcMindMap",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1358,7 +1358,7 @@
"Id": "ed7bd2c5-36b0-49d8-a441-8c4426a53a28", "Id": "ed7bd2c5-36b0-49d8-a441-8c4426a53a28",
"Code": "App.Hr.Department", "Code": "App.Hr.Department",
"DisplayName": "App.Hr.Department", "DisplayName": "App.Hr.Department",
"Order": 2, "Order": 1,
"Url": "/admin/list/App.Hr.Department", "Url": "/admin/list/App.Hr.Department",
"Icon": "FcDepartment", "Icon": "FcDepartment",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1373,7 +1373,7 @@
"Id": "f6d15b30-3404-4982-a035-97c986999f1e", "Id": "f6d15b30-3404-4982-a035-97c986999f1e",
"Code": "App.Hr.JobPosition", "Code": "App.Hr.JobPosition",
"DisplayName": "App.Hr.JobPosition", "DisplayName": "App.Hr.JobPosition",
"Order": 3, "Order": 2,
"Url": "/admin/list/App.Hr.JobPosition", "Url": "/admin/list/App.Hr.JobPosition",
"Icon": "FcDebt", "Icon": "FcDebt",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1388,7 +1388,7 @@
"Id": "9b1449bd-d898-43fb-96e0-50ab865b7072", "Id": "9b1449bd-d898-43fb-96e0-50ab865b7072",
"Code": "App.Hr.OrgChart", "Code": "App.Hr.OrgChart",
"DisplayName": "App.Hr.OrgChart", "DisplayName": "App.Hr.OrgChart",
"Order": 4, "Order": 2,
"Url": "/admin/organization", "Url": "/admin/organization",
"Icon": "FaSitemap", "Icon": "FaSitemap",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1403,7 +1403,7 @@
"Id": "a866f244-67b4-4015-80c6-632abfab03ef", "Id": "a866f244-67b4-4015-80c6-632abfab03ef",
"Code": "App.Hr.Doctor", "Code": "App.Hr.Doctor",
"DisplayName": "App.Hr.Doctor", "DisplayName": "App.Hr.Doctor",
"Order": 4, "Order": 13,
"Url": "/admin/list/App.Hr.Doctor", "Url": "/admin/list/App.Hr.Doctor",
"Icon": "FcPortraitMode", "Icon": "FcPortraitMode",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1418,7 +1418,7 @@
"Id": "a6ddfb7b-db3e-4dec-a981-af9b193f9ea5", "Id": "a6ddfb7b-db3e-4dec-a981-af9b193f9ea5",
"Code": "App.Hr.Certificate", "Code": "App.Hr.Certificate",
"DisplayName": "App.Hr.Certificate", "DisplayName": "App.Hr.Certificate",
"Order": 5, "Order": 4,
"Url": "/admin/list/App.Hr.Certificate", "Url": "/admin/list/App.Hr.Certificate",
"Icon": "FcDiploma2", "Icon": "FcDiploma2",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1433,7 +1433,7 @@
"Id": "fc69c8ac-6bec-4ee1-a30d-73f257b43338", "Id": "fc69c8ac-6bec-4ee1-a30d-73f257b43338",
"Code": "App.Hr.Hospital", "Code": "App.Hr.Hospital",
"DisplayName": "App.Hr.Hospital", "DisplayName": "App.Hr.Hospital",
"Order": 6, "Order": 14,
"Url": "/admin/list/App.Hr.Hospital", "Url": "/admin/list/App.Hr.Hospital",
"Icon": "FcOrganization", "Icon": "FcOrganization",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1448,7 +1448,7 @@
"Id": "b3cf12f0-062a-4b1f-ad20-748f9459d8c4", "Id": "b3cf12f0-062a-4b1f-ad20-748f9459d8c4",
"Code": "App.Hr.HospitalDepartment", "Code": "App.Hr.HospitalDepartment",
"DisplayName": "App.Hr.HospitalDepartment", "DisplayName": "App.Hr.HospitalDepartment",
"Order": 7, "Order": 15,
"Url": "/admin/list/App.Hr.HospitalDepartment", "Url": "/admin/list/App.Hr.HospitalDepartment",
"Icon": "FcList", "Icon": "FcList",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1463,7 +1463,7 @@
"Id": "4a83ad06-d841-454e-a9ac-7d83e6bcd7d3", "Id": "4a83ad06-d841-454e-a9ac-7d83e6bcd7d3",
"Code": "App.Hr.DocumentType", "Code": "App.Hr.DocumentType",
"DisplayName": "App.Hr.DocumentType", "DisplayName": "App.Hr.DocumentType",
"Order": 8, "Order": 5,
"Url": "/admin/list/App.Hr.DocumentType", "Url": "/admin/list/App.Hr.DocumentType",
"Icon": "FcDocument", "Icon": "FcDocument",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1478,7 +1478,7 @@
"Id": "ae8c7c61-8b57-4335-bacb-d54bcce3d661", "Id": "ae8c7c61-8b57-4335-bacb-d54bcce3d661",
"Code": "App.Hr.Visitor", "Code": "App.Hr.Visitor",
"DisplayName": "App.Hr.Visitor", "DisplayName": "App.Hr.Visitor",
"Order": 8, "Order": 12,
"Url": "/admin/list/App.Hr.Visitor", "Url": "/admin/list/App.Hr.Visitor",
"Icon": "FcBusinessman", "Icon": "FcBusinessman",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1493,7 +1493,7 @@
"Id": "8803f8c5-e85b-491d-9330-a9dd5a95f1a1", "Id": "8803f8c5-e85b-491d-9330-a9dd5a95f1a1",
"Code": "App.Hr.HealthCard", "Code": "App.Hr.HealthCard",
"DisplayName": "App.Hr.HealthCard", "DisplayName": "App.Hr.HealthCard",
"Order": 5, "Order": 7,
"Url": "/admin/list/App.Hr.HealthCard", "Url": "/admin/list/App.Hr.HealthCard",
"Icon": "FcInspection", "Icon": "FcInspection",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1508,7 +1508,7 @@
"Id": "aa47dc14-483f-41ad-83f5-f304050db135", "Id": "aa47dc14-483f-41ad-83f5-f304050db135",
"Code": "App.Hr.Trainings", "Code": "App.Hr.Trainings",
"DisplayName": "App.Hr.Trainings", "DisplayName": "App.Hr.Trainings",
"Order": 6, "Order": 8,
"Url": null, "Url": null,
"Icon": "FcGraduationCap", "Icon": "FcGraduationCap",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1568,7 +1568,7 @@
"Id": "18146db0-b2aa-49d8-b39c-0165a1d85e53", "Id": "18146db0-b2aa-49d8-b39c-0165a1d85e53",
"Code": "App.Hr.Vehicles", "Code": "App.Hr.Vehicles",
"DisplayName": "App.Hr.Vehicles", "DisplayName": "App.Hr.Vehicles",
"Order": 7, "Order": 11,
"Url": null, "Url": null,
"Icon": "FcAutomotive", "Icon": "FcAutomotive",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1598,7 +1598,7 @@
"Id": "e07191b4-f6b0-42f2-a19a-fd22a41abf39", "Id": "e07191b4-f6b0-42f2-a19a-fd22a41abf39",
"Code": "App.Hr.Vehicle", "Code": "App.Hr.Vehicle",
"DisplayName": "App.Hr.Vehicle", "DisplayName": "App.Hr.Vehicle",
"Order": 2, "Order": 4,
"Url": "/admin/list/App.Hr.Vehicle", "Url": "/admin/list/App.Hr.Vehicle",
"Icon": "FcAutomotive", "Icon": "FcAutomotive",
"ParentCode": "App.Hr.Vehicles", "ParentCode": "App.Hr.Vehicles",
@ -1628,7 +1628,7 @@
"Id": "e61fd31e-265b-410e-9e71-4862aea4bdff", "Id": "e61fd31e-265b-410e-9e71-4862aea4bdff",
"Code": "App.Hr.Driver", "Code": "App.Hr.Driver",
"DisplayName": "App.Hr.Driver", "DisplayName": "App.Hr.Driver",
"Order": 4, "Order": 5,
"Url": "/admin/list/App.Hr.Driver", "Url": "/admin/list/App.Hr.Driver",
"Icon": "FcBusinessman", "Icon": "FcBusinessman",
"ParentCode": "App.Hr.Vehicles", "ParentCode": "App.Hr.Vehicles",
@ -1643,7 +1643,7 @@
"Id": "d2672ea5-55a2-43fc-8832-901cfd3bcf4d", "Id": "d2672ea5-55a2-43fc-8832-901cfd3bcf4d",
"Code": "App.Hr.VehicleExpenseDefinition", "Code": "App.Hr.VehicleExpenseDefinition",
"DisplayName": "App.Hr.VehicleExpenseDefinition", "DisplayName": "App.Hr.VehicleExpenseDefinition",
"Order": 5, "Order": 2,
"Url": "/admin/list/App.Hr.VehicleExpenseDefinition", "Url": "/admin/list/App.Hr.VehicleExpenseDefinition",
"Icon": "FcList", "Icon": "FcList",
"ParentCode": "App.Hr.Vehicles", "ParentCode": "App.Hr.Vehicles",
@ -1658,7 +1658,7 @@
"Id": "be5ca380-4054-4cc5-80f6-67bee385a145", "Id": "be5ca380-4054-4cc5-80f6-67bee385a145",
"Code": "App.Hr.VehicleExpense", "Code": "App.Hr.VehicleExpense",
"DisplayName": "App.Hr.VehicleExpense", "DisplayName": "App.Hr.VehicleExpense",
"Order": 6, "Order": 7,
"Url": "/admin/list/App.Hr.VehicleExpense", "Url": "/admin/list/App.Hr.VehicleExpense",
"Icon": "FcMoneyTransfer", "Icon": "FcMoneyTransfer",
"ParentCode": "App.Hr.Vehicles", "ParentCode": "App.Hr.Vehicles",
@ -1673,7 +1673,7 @@
"Id": "65918815-4fd4-49b7-aed1-477e0acc4e16", "Id": "65918815-4fd4-49b7-aed1-477e0acc4e16",
"Code": "App.Hr.VehicleMovement", "Code": "App.Hr.VehicleMovement",
"DisplayName": "App.Hr.VehicleMovement", "DisplayName": "App.Hr.VehicleMovement",
"Order": 7, "Order": 6,
"Url": "/admin/list/App.Hr.VehicleMovement", "Url": "/admin/list/App.Hr.VehicleMovement",
"Icon": "FcInspection", "Icon": "FcInspection",
"ParentCode": "App.Hr.Vehicles", "ParentCode": "App.Hr.Vehicles",
@ -1688,10 +1688,10 @@
"Id": "0f1b3f0c-f9d8-4f09-9506-59fb19272176", "Id": "0f1b3f0c-f9d8-4f09-9506-59fb19272176",
"Code": "App.Hr.Shift", "Code": "App.Hr.Shift",
"DisplayName": "App.Hr.Shift", "DisplayName": "App.Hr.Shift",
"Order": 3, "Order": 11,
"Url": "/admin/list/App.Hr.Shift", "Url": "/admin/list/App.Hr.Shift",
"Icon": "FcClock", "Icon": "FcClock",
"ParentCode": "App.Hr", "ParentCode": "App.Hr.Definitions",
"RequiredPermissionName": "App.Hr.Shift", "RequiredPermissionName": "App.Hr.Shift",
"CssClass": null, "CssClass": null,
"Target": null, "Target": null,
@ -1703,7 +1703,7 @@
"Id": "5786d92e-0501-4775-bf1b-697a41a90f40", "Id": "5786d92e-0501-4775-bf1b-697a41a90f40",
"Code": "App.Hr.EventLog", "Code": "App.Hr.EventLog",
"DisplayName": "App.Hr.EventLog", "DisplayName": "App.Hr.EventLog",
"Order": 9, "Order": 13,
"Url": "/admin/list/App.Hr.EventLog", "Url": "/admin/list/App.Hr.EventLog",
"Icon": "FcViewDetails", "Icon": "FcViewDetails",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1718,7 +1718,7 @@
"Id": "aaef98c6-ab15-4097-9d32-d611db7de57d", "Id": "aaef98c6-ab15-4097-9d32-d611db7de57d",
"Code": "App.Hr.Intranet", "Code": "App.Hr.Intranet",
"DisplayName": "App.Hr.Intranet", "DisplayName": "App.Hr.Intranet",
"Order": 10, "Order": 14,
"Url": null, "Url": null,
"Icon": "FcConferenceCall", "Icon": "FcConferenceCall",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1733,7 +1733,7 @@
"Id": "5cef6234-ae2d-4963-b7aa-84f58c5d1e8a", "Id": "5cef6234-ae2d-4963-b7aa-84f58c5d1e8a",
"Code": "App.Hr.Intranet.Announcement", "Code": "App.Hr.Intranet.Announcement",
"DisplayName": "App.Hr.Intranet.Announcement", "DisplayName": "App.Hr.Intranet.Announcement",
"Order": 1, "Order": 3,
"Url": "/admin/list/App.Hr.Intranet.Announcement", "Url": "/admin/list/App.Hr.Intranet.Announcement",
"Icon": "FcAdvertising", "Icon": "FcAdvertising",
"ParentCode": "App.Hr.Intranet", "ParentCode": "App.Hr.Intranet",
@ -1748,7 +1748,7 @@
"Id": "8eea0d26-4da7-4def-8228-bd340b518b29", "Id": "8eea0d26-4da7-4def-8228-bd340b518b29",
"Code": "App.Hr.Intranet.Survey", "Code": "App.Hr.Intranet.Survey",
"DisplayName": "App.Hr.Intranet.Survey", "DisplayName": "App.Hr.Intranet.Survey",
"Order": 2, "Order": 4,
"Url": "/admin/list/App.Hr.Intranet.Survey", "Url": "/admin/list/App.Hr.Intranet.Survey",
"Icon": "FcTodoList", "Icon": "FcTodoList",
"ParentCode": "App.Hr.Intranet", "ParentCode": "App.Hr.Intranet",
@ -1763,7 +1763,7 @@
"Id": "216da72b-e243-4f07-afaa-04a7b79dc977", "Id": "216da72b-e243-4f07-afaa-04a7b79dc977",
"Code": "App.Hr.Intranet.SocialPost", "Code": "App.Hr.Intranet.SocialPost",
"DisplayName": "App.Hr.Intranet.SocialPost", "DisplayName": "App.Hr.Intranet.SocialPost",
"Order": 3, "Order": 5,
"Url": "/admin/list/App.Hr.Intranet.SocialPost", "Url": "/admin/list/App.Hr.Intranet.SocialPost",
"Icon": "FcComments", "Icon": "FcComments",
"ParentCode": "App.Hr.Intranet", "ParentCode": "App.Hr.Intranet",
@ -1778,7 +1778,7 @@
"Id": "01246207-7a2e-43cc-82b1-3a475b242926", "Id": "01246207-7a2e-43cc-82b1-3a475b242926",
"Code": "App.Hr.Intranet.Events.EventType", "Code": "App.Hr.Intranet.Events.EventType",
"DisplayName": "App.Hr.Intranet.Events.EventType", "DisplayName": "App.Hr.Intranet.Events.EventType",
"Order": 4, "Order": 1,
"Url": "/admin/list/App.Hr.Intranet.Events.EventType", "Url": "/admin/list/App.Hr.Intranet.Events.EventType",
"Icon": "FcPlanner", "Icon": "FcPlanner",
"ParentCode": "App.Hr.Intranet", "ParentCode": "App.Hr.Intranet",
@ -1793,7 +1793,7 @@
"Id": "319118e2-1a91-44e2-8f4d-45b7327d4975", "Id": "319118e2-1a91-44e2-8f4d-45b7327d4975",
"Code": "App.Hr.Intranet.Events.EventCategory", "Code": "App.Hr.Intranet.Events.EventCategory",
"DisplayName": "App.Hr.Intranet.Events.EventCategory", "DisplayName": "App.Hr.Intranet.Events.EventCategory",
"Order": 5, "Order": 2,
"Url": "/admin/list/App.Hr.Intranet.Events.EventCategory", "Url": "/admin/list/App.Hr.Intranet.Events.EventCategory",
"Icon": "FcTreeStructure", "Icon": "FcTreeStructure",
"ParentCode": "App.Hr.Intranet", "ParentCode": "App.Hr.Intranet",
@ -1838,7 +1838,7 @@
"Id": "ee299353-fc0d-5a4b-b766-fd3729feb196", "Id": "ee299353-fc0d-5a4b-b766-fd3729feb196",
"Code": "App.Hr.LeaveType", "Code": "App.Hr.LeaveType",
"DisplayName": "App.Hr.LeaveType", "DisplayName": "App.Hr.LeaveType",
"Order": 9, "Order": 12,
"Url": "/admin/list/App.Hr.LeaveType", "Url": "/admin/list/App.Hr.LeaveType",
"Icon": "FcPlanner", "Icon": "FcPlanner",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1853,7 +1853,7 @@
"Id": "ef40a47d-2d4a-5f21-b6a2-c70c078a7b0d", "Id": "ef40a47d-2d4a-5f21-b6a2-c70c078a7b0d",
"Code": "App.Hr.ExpenseType", "Code": "App.Hr.ExpenseType",
"DisplayName": "App.Hr.ExpenseType", "DisplayName": "App.Hr.ExpenseType",
"Order": 10, "Order": 9,
"Url": "/admin/list/App.Hr.ExpenseType", "Url": "/admin/list/App.Hr.ExpenseType",
"Icon": "FcMoneyTransfer", "Icon": "FcMoneyTransfer",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1868,7 +1868,7 @@
"Id": "479a8e6f-ffca-56aa-af6d-584b231459ca", "Id": "479a8e6f-ffca-56aa-af6d-584b231459ca",
"Code": "App.Hr.BenefitType", "Code": "App.Hr.BenefitType",
"DisplayName": "App.Hr.BenefitType", "DisplayName": "App.Hr.BenefitType",
"Order": 11, "Order": 10,
"Url": "/admin/list/App.Hr.BenefitType", "Url": "/admin/list/App.Hr.BenefitType",
"Icon": "FcDonate", "Icon": "FcDonate",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1883,7 +1883,7 @@
"Id": "f35eff0e-a0d8-5f4c-8b34-4bd3e6ffb9c5", "Id": "f35eff0e-a0d8-5f4c-8b34-4bd3e6ffb9c5",
"Code": "App.Hr.WorkCalendar", "Code": "App.Hr.WorkCalendar",
"DisplayName": "App.Hr.WorkCalendar", "DisplayName": "App.Hr.WorkCalendar",
"Order": 2, "Order": 4,
"Url": "/admin/list/App.Hr.WorkCalendar", "Url": "/admin/list/App.Hr.WorkCalendar",
"Icon": "FcCalendar", "Icon": "FcCalendar",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1898,7 +1898,7 @@
"Id": "76a5d279-bbc1-564d-9430-fe068da2a396", "Id": "76a5d279-bbc1-564d-9430-fe068da2a396",
"Code": "App.Hr.DisciplinaryPenaltyType", "Code": "App.Hr.DisciplinaryPenaltyType",
"DisplayName": "App.Hr.DisciplinaryPenaltyType", "DisplayName": "App.Hr.DisciplinaryPenaltyType",
"Order": 12, "Order": 17,
"Url": "/admin/list/App.Hr.DisciplinaryPenaltyType", "Url": "/admin/list/App.Hr.DisciplinaryPenaltyType",
"Icon": "FcList", "Icon": "FcList",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1913,7 +1913,7 @@
"Id": "1a81c7be-ef52-5332-8118-0e83b9bb49e1", "Id": "1a81c7be-ef52-5332-8118-0e83b9bb49e1",
"Code": "App.Hr.DisciplinaryCase", "Code": "App.Hr.DisciplinaryCase",
"DisplayName": "App.Hr.DisciplinaryCase", "DisplayName": "App.Hr.DisciplinaryCase",
"Order": 11, "Order": 10,
"Url": "/admin/list/App.Hr.DisciplinaryCase", "Url": "/admin/list/App.Hr.DisciplinaryCase",
"Icon": "FcHighPriority", "Icon": "FcHighPriority",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1928,7 +1928,7 @@
"Id": "3651b5de-4588-4632-9ce1-35352059e2e2", "Id": "3651b5de-4588-4632-9ce1-35352059e2e2",
"Code": "App.Hr.Recruitment", "Code": "App.Hr.Recruitment",
"DisplayName": "App.Hr.Recruitment", "DisplayName": "App.Hr.Recruitment",
"Order": 12, "Order": 3,
"Url": null, "Url": null,
"Icon": "FcManager", "Icon": "FcManager",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -1943,7 +1943,7 @@
"Id": "1b88ddd5-4875-442c-91e6-25f49f4bda05", "Id": "1b88ddd5-4875-442c-91e6-25f49f4bda05",
"Code": "App.Hr.CandidateSource", "Code": "App.Hr.CandidateSource",
"DisplayName": "App.Hr.CandidateSource", "DisplayName": "App.Hr.CandidateSource",
"Order": 13, "Order": 6,
"Url": "/admin/list/App.Hr.CandidateSource", "Url": "/admin/list/App.Hr.CandidateSource",
"Icon": "FcFeedback", "Icon": "FcFeedback",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1958,7 +1958,7 @@
"Id": "f44ad474-e089-4852-b069-98856e791330", "Id": "f44ad474-e089-4852-b069-98856e791330",
"Code": "App.Hr.RejectionReason", "Code": "App.Hr.RejectionReason",
"DisplayName": "App.Hr.RejectionReason", "DisplayName": "App.Hr.RejectionReason",
"Order": 14, "Order": 7,
"Url": "/admin/list/App.Hr.RejectionReason", "Url": "/admin/list/App.Hr.RejectionReason",
"Icon": "FcCancel", "Icon": "FcCancel",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -1973,7 +1973,7 @@
"Id": "b4717d28-e5ee-44ee-8219-472f85450bdf", "Id": "b4717d28-e5ee-44ee-8219-472f85450bdf",
"Code": "App.Hr.EvaluationCriterion", "Code": "App.Hr.EvaluationCriterion",
"DisplayName": "App.Hr.EvaluationCriterion", "DisplayName": "App.Hr.EvaluationCriterion",
"Order": 15, "Order": 8,
"Url": "/admin/list/App.Hr.EvaluationCriterion", "Url": "/admin/list/App.Hr.EvaluationCriterion",
"Icon": "FcRating", "Icon": "FcRating",
"ParentCode": "App.Hr.Definitions", "ParentCode": "App.Hr.Definitions",
@ -2093,7 +2093,7 @@
"Id": "3dc572da-bad3-4fab-991c-0fc7e1d0cded", "Id": "3dc572da-bad3-4fab-991c-0fc7e1d0cded",
"Code": "App.Hr.Performance", "Code": "App.Hr.Performance",
"DisplayName": "App.Hr.Performance", "DisplayName": "App.Hr.Performance",
"Order": 13, "Order": 9,
"Url": null, "Url": null,
"Icon": "FcBullish", "Icon": "FcBullish",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -2123,7 +2123,7 @@
"Id": "fcb6d389-df5a-4f9f-a18c-d91373ae08bb", "Id": "fcb6d389-df5a-4f9f-a18c-d91373ae08bb",
"Code": "App.Hr.PerformanceReview", "Code": "App.Hr.PerformanceReview",
"DisplayName": "App.Hr.PerformanceReview", "DisplayName": "App.Hr.PerformanceReview",
"Order": 4, "Order": 2,
"Url": "/admin/list/App.Hr.PerformanceReview", "Url": "/admin/list/App.Hr.PerformanceReview",
"Icon": "FcInspection", "Icon": "FcInspection",
"ParentCode": "App.Hr.Performance", "ParentCode": "App.Hr.Performance",
@ -2153,7 +2153,7 @@
"Id": "b1e055bd-3373-48ba-a4f4-2b3a0202f843", "Id": "b1e055bd-3373-48ba-a4f4-2b3a0202f843",
"Code": "App.Hr.DevelopmentPlan", "Code": "App.Hr.DevelopmentPlan",
"DisplayName": "App.Hr.DevelopmentPlan", "DisplayName": "App.Hr.DevelopmentPlan",
"Order": 2, "Order": 4,
"Url": "/admin/list/App.Hr.DevelopmentPlan", "Url": "/admin/list/App.Hr.DevelopmentPlan",
"Icon": "FcBullish", "Icon": "FcBullish",
"ParentCode": "App.Hr.Performance", "ParentCode": "App.Hr.Performance",
@ -2168,7 +2168,7 @@
"Id": "c3ac8beb-302f-5285-89a5-9c98d2f19524", "Id": "c3ac8beb-302f-5285-89a5-9c98d2f19524",
"Code": "App.Hr.Leave", "Code": "App.Hr.Leave",
"DisplayName": "App.Hr.Leave", "DisplayName": "App.Hr.Leave",
"Order": 14, "Order": 5,
"Url": null, "Url": null,
"Icon": "FcOvertime", "Icon": "FcOvertime",
"ParentCode": "App.Hr", "ParentCode": "App.Hr",
@ -2208,6 +2208,81 @@
"IsDisabled": false, "IsDisabled": false,
"ElementId": null, "ElementId": null,
"ModuleId": "Hr" "ModuleId": "Hr"
},
{
"Id": "5ccc44eb-7930-5b1e-9ef6-cadae2d2cc4d",
"Code": "App.Hr.Attendance",
"DisplayName": "App.Hr.Attendance",
"Order": 6,
"Url": null,
"Icon": "FcAlarmClock",
"ParentCode": "App.Hr",
"RequiredPermissionName": null,
"CssClass": null,
"Target": null,
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
},
{
"Id": "11b83726-66b6-5d76-9256-3e70a2c8559b",
"Code": "App.Hr.AttendanceLog",
"DisplayName": "App.Hr.AttendanceLog",
"Order": 1,
"Url": "/admin/list/App.Hr.AttendanceLog",
"Icon": "FcTimeline",
"ParentCode": "App.Hr.Attendance",
"RequiredPermissionName": "App.Hr.AttendanceLog",
"CssClass": null,
"Target": null,
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
},
{
"Id": "f762d84c-ac12-5d44-a0fd-cdc25e5dc7f4",
"Code": "App.Hr.Timesheet",
"DisplayName": "App.Hr.Timesheet",
"Order": 2,
"Url": "/admin/list/App.Hr.Timesheet",
"Icon": "FcPlanner",
"ParentCode": "App.Hr.Attendance",
"RequiredPermissionName": "App.Hr.Timesheet",
"CssClass": null,
"Target": null,
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
},
{
"Id": "5b3b092f-f91f-5954-bd43-839c5cc9cfde",
"Code": "App.Hr.TimesheetMonthly",
"DisplayName": "App.Hr.TimesheetMonthly",
"Order": 3,
"Url": "/admin/list/App.Hr.TimesheetMonthly",
"Icon": "FcDataSheet",
"ParentCode": "App.Hr.Attendance",
"RequiredPermissionName": "App.Hr.TimesheetMonthly",
"CssClass": null,
"Target": null,
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
},
{
"Id": "6e96e0fe-bd55-54c1-afbf-e262238ad15b",
"Code": "App.Hr.TimesheetPeriod",
"DisplayName": "App.Hr.TimesheetPeriod",
"Order": 4,
"Url": "/admin/list/App.Hr.TimesheetPeriod",
"Icon": "FcLock",
"ParentCode": "App.Hr.Attendance",
"RequiredPermissionName": "App.Hr.TimesheetPeriod",
"CssClass": null,
"Target": null,
"IsDisabled": false,
"ElementId": null,
"ModuleId": "Hr"
} }
] ]
} }

View file

@ -1413,6 +1413,142 @@
"IsVisibleToClients": false, "IsVisibleToClients": false,
"IsInherited": false, "IsInherited": false,
"IsEncrypted": false "IsEncrypted": false
},
{
"Id": "739c2cf2-4916-52f9-8e98-ba6241886617",
"Code": "App.HrSettings.Attendance.LateToleranceMinutes",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 105,
"NameKey": "App.HrSettings.Attendance.LateToleranceMinutes",
"DescriptionKey": "App.HrSettings.Attendance.LateToleranceMinutes.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "10",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "b2a49a01-b1db-570c-a16c-ef4b0eacd7e8",
"Code": "App.HrSettings.Attendance.EarlyLeaveToleranceMinutes",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 106,
"NameKey": "App.HrSettings.Attendance.EarlyLeaveToleranceMinutes",
"DescriptionKey": "App.HrSettings.Attendance.EarlyLeaveToleranceMinutes.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "10",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "ffb1bda6-0f98-5209-b51f-8a510a3250e7",
"Code": "App.HrSettings.Attendance.WeeklyLimitHours",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 107,
"NameKey": "App.HrSettings.Attendance.WeeklyLimitHours",
"DescriptionKey": "App.HrSettings.Attendance.WeeklyLimitHours.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "45",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "766856a3-2c94-587c-952c-8c9a817eef8a",
"Code": "App.HrSettings.Attendance.OvertimeRate",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 108,
"NameKey": "App.HrSettings.Attendance.OvertimeRate",
"DescriptionKey": "App.HrSettings.Attendance.OvertimeRate.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "1.5",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "94009195-23eb-5e7a-bcf5-80fe468e2baa",
"Code": "App.HrSettings.Attendance.AnnualOvertimeLimitHours",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 109,
"NameKey": "App.HrSettings.Attendance.AnnualOvertimeLimitHours",
"DescriptionKey": "App.HrSettings.Attendance.AnnualOvertimeLimitHours.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "270",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "3ab1284f-ac54-5796-a078-cffb86286f2f",
"Code": "App.HrSettings.Attendance.DefaultShiftStart",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 110,
"NameKey": "App.HrSettings.Attendance.DefaultShiftStart",
"DescriptionKey": "App.HrSettings.Attendance.DefaultShiftStart.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "08:00",
"DataType": "Text",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "3f30406e-7ce0-5805-8765-dddd98cff80a",
"Code": "App.HrSettings.Attendance.DefaultShiftEnd",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 111,
"NameKey": "App.HrSettings.Attendance.DefaultShiftEnd",
"DescriptionKey": "App.HrSettings.Attendance.DefaultShiftEnd.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "18:00",
"DataType": "Text",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
},
{
"Id": "65b21d85-efac-5357-84a7-918f774b70cd",
"Code": "App.HrSettings.Attendance.DefaultBreakMinutes",
"MainGroupKey": "App.HrSettings",
"SubGroupKey": "App.HrSettings.Attendance",
"Order": 112,
"NameKey": "App.HrSettings.Attendance.DefaultBreakMinutes",
"DescriptionKey": "App.HrSettings.Attendance.DefaultBreakMinutes.Description",
"RequiredPermissionName": "App.HrSettings.Attendance",
"Providers": "T|G|D",
"DefaultValue": "60",
"DataType": "Number",
"SelectOptions": "{}",
"IsVisibleToClients": false,
"IsInherited": false,
"IsEncrypted": false
} }
] ]
} }

View file

@ -0,0 +1,552 @@
# İ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 |
| İ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/host/sql/object/Hr_T_{AttendanceLog,Timesheet,TimesheetPeriod}.sql` | Tablolar |
| `configs/seeds/host/sql/object/Hr_T_Shift.sql` | Vardiya toleransı kolonları |
| `configs/seeds/host/sql/object/Hr_V_{AttendanceShift,TimesheetMonthly}.sql` | View'lar |
| `configs/seeds/host/sql/object/Hr_F_{WorkCalendarDayType,TimesheetPeriodClosed,LeaveNetDays}.sql` | Takvim günü türü, kapalı dönem, rapordan arınmış izin günü |
| `configs/seeds/host/sql/object/Hr_S_{TimesheetCalculate,AttendanceProcess,AttendanceImport,TimesheetPeriodAfterSave,TimesheetNightly}.sql` | Hesap ve tetikler |
| `configs/seeds/host/sql/object/Hr_S_{LeaveRequestAfterSave,LeaveRequestGuard,LeaveSickLeaveSync,LeaveDaysRefresh}.sql` | İzin/rapor → puantaj tetiği, kapalı dönem guard'ı, rapor → izin günü |
| `configs/seeds/host/sql/object/Hr_S_{TrainingSync,WorkCalendarAfterSave}.sql` | Eğitim ve takvim → puantaj tetiği |
| `configs/seeds/host/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/host/wizard/{AttendanceLog,Timesheet,TimesheetMonthly,TimesheetPeriod,MyTimesheet,MyTimesheetDay}.json` | 6 wizard |
| `configs/seeds/host/wizard/Shift.json` | Tolerans alanları |
| `configs/seeds/host/data/App.DeveloperKit.CustomComponents/1bca19aa-e144-5e4c-b23b-9eddd4dafd19.json` | `MyTimesheetWidget` |
| `configs/seeds/host/data/App.DeveloperKit.IntranetWidgets.json` | `my-timesheet` |
| `configs/seeds/host/data/App.DeveloperKit.CustomEndpoints.json` | PDKS ucu |
| `configs/seeds/host/data/App.BackgroundWorkers.RecurringJobs.json` | `Timesheet Nightly` |
| `configs/seeds/host/data/App.SettingDefinitions.json` | `App.HrSettings.Attendance.*` |
| `configs/seeds/host/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.
<!-- module-doc:auto:begin -->
## 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 | | | |
<!-- module-doc:auto:end -->

View file

@ -16,26 +16,33 @@ türü, masraf türü, yan hak türü) anlatır.
| Sıra | Menü | `ListFormCode` | Kaynak | Ayrıntı | | Sıra | Menü | `ListFormCode` | Kaynak | Ayrıntı |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| 1 | Yetenek Tipleri | `App.Hr.SkillType` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | | 1 | Departmanlar | `App.Hr.Department` | Entity + seeder | [HrOrganization.md](HrOrganization.md) |
| 2 | Departmanlar | `App.Hr.Department` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | | 2 | Pozisyonlar | `App.Hr.JobPosition` | Entity + seeder | [HrOrganization.md](HrOrganization.md) |
| 3 | Pozisyonlar | `App.Hr.JobPosition` | Entity + seeder | [HrOrganization.md](HrOrganization.md) | | 3 | Yetenek Tipleri | `App.Hr.SkillType` | Entity + seeder | [HrOrganization.md](HrOrganization.md) |
| 4 | Kurum Doktorları | `App.Hr.Doctor` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | | 4 | Yeterlilik Belgeleri | `App.Hr.Certificate` | Wizard | bu doküman |
| 5 | Yeterlilik Belgeleri | `App.Hr.Certificate` | Wizard | bu doküman | | 5 | Evrak Türleri | `App.Hr.DocumentType` | Wizard | bu doküman |
| 6 | Hastaneler | `App.Hr.Hospital` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | | 6 | Aday Kaynakları | `App.Hr.CandidateSource` | Wizard | [HrRecruitment.md](HrRecruitment.md) |
| 7 | Hastane Bölümleri | `App.Hr.HospitalDepartment` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) | | 7 | Ret Sebepleri | `App.Hr.RejectionReason` | Wizard | [HrRecruitment.md](HrRecruitment.md) |
| 8 | Evrak Türleri | `App.Hr.DocumentType` | Wizard | bu doküman | | 8 | Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | Wizard | [HrRecruitment.md](HrRecruitment.md) |
| 9 | İzin Türleri | `App.Hr.LeaveType` | Wizard | bu doküman | | 9 | Masraf Türleri | `App.Hr.ExpenseType` | Wizard | bu doküman |
| 10 | Masraf Türleri | `App.Hr.ExpenseType` | Wizard | bu doküman | | 10 | Yan Hak Türleri | `App.Hr.BenefitType` | Wizard | bu doküman |
| 11 | 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 | Ceza Türleri | `App.Hr.DisciplinaryPenaltyType` | Wizard | [HrDisciplinaryCase.md](HrDisciplinaryCase.md) | | 12 | İzin Türleri | `App.Hr.LeaveType` | Wizard | bu doküman |
| 13 | Aday Kaynakları | `App.Hr.CandidateSource` | Wizard | [HrRecruitment.md](HrRecruitment.md) | | 13 | Kurum Doktorları | `App.Hr.Doctor` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) |
| 14 | Ret Sebepleri | `App.Hr.RejectionReason` | Wizard | [HrRecruitment.md](HrRecruitment.md) | | 14 | Hastaneler | `App.Hr.Hospital` | Wizard | bu doküman · [HrHealthCard.md](HrHealthCard.md) |
| 15 | Değerlendirme Kriterleri | `App.Hr.EvaluationCriterion` | Wizard | [HrRecruitment.md](HrRecruitment.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) | | 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ç Tanımlamalar dışında duran tanımlar: Eğitim tipi/konusu → [HrTrainings.md](HrTrainings.md); araç
belgesi/masrafı/gidilecek yer → [HrVehicles.md](HrVehicles.md); çalışma takvimi ve vardiya → belgesi/masrafı/gidilecek yer → [HrVehicles.md](HrVehicles.md) (her alt menüde tanım ekranları en üstte);
[HrWorkCalendar.md](HrWorkCalendar.md). ç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.
--- ---
@ -139,40 +146,13 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
> Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur. > Wizard dosyalarından üretilir; deploy, silme, tasarımcı kaydı ve import'ta yenilenir. Elle düzenleme bir sonraki yenilemede kaybolur.
### Kurum Doktorları — `App.Hr.Doctor`
| Özellik | Değer |
| --- | --- |
| Wizard | `wizard/Doctor.json` |
| Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.Doctor` (sıra 4) |
| 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 | ✓ | ✓ | |
### Yeterlilik Belgeleri — `App.Hr.Certificate` ### Yeterlilik Belgeleri — `App.Hr.Certificate`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/Certificate.json` | | Wizard | `wizard/Certificate.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.Certificate` (sıra 5) | | Menü | `App.Hr.Definitions` › `App.Hr.Certificate` (sıra 4) |
| Yetki | `App.Hr.Certificate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Yetki | `App.Hr.Certificate` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
| Açıklama | Yeterlilik Belgeleri — personelin sahip olabileceği mesleki yeterlilik ve mezuniyet belgeleri. | | Açıklama | Yeterlilik Belgeleri — personelin sahip olabileceği mesleki yeterlilik ve mezuniyet belgeleri. |
| Geliştirme talebi | Human Resources -> Definitions | | Geliştirme talebi | Human Resources -> Definitions |
@ -188,57 +168,13 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | | `Name` | Belge Adı | dxTextBox | ✓ | ✓ | |
| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | | `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 6) |
| 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 7) |
| 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 | ✓ | ✓ | |
### Evrak Türleri — `App.Hr.DocumentType` ### Evrak Türleri — `App.Hr.DocumentType`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/DocumentType.json` | | Wizard | `wizard/DocumentType.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.DocumentType` (sıra 8) | | Menü | `App.Hr.Definitions` › `App.Hr.DocumentType` (sıra 5) |
| Yetki | `App.Hr.DocumentType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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 | | Geliştirme talebi | Human Resources -> Definitions |
@ -256,43 +192,13 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
| `IsRequired` | Zorunlu | dxCheckBox | ✓ | ✓ | | | `IsRequired` | Zorunlu | dxCheckBox | ✓ | ✓ | |
| `IsActive` | Aktif | 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 9) |
| 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 | ✓ | ✓ | |
### Masraf Türleri — `App.Hr.ExpenseType` ### Masraf Türleri — `App.Hr.ExpenseType`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/ExpenseType.json` | | Wizard | `wizard/ExpenseType.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.ExpenseType` (sıra 10) | | Menü | `App.Hr.Definitions` › `App.Hr.ExpenseType` (sıra 9) |
| Yetki | `App.Hr.ExpenseType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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'` | | Kaynak | `Hr_T_ExpenseType` · filtre `"IsDeleted" = 'false'` |
@ -320,7 +226,7 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
| --- | --- | | --- | --- |
| Wizard | `wizard/BenefitType.json` | | Wizard | `wizard/BenefitType.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.BenefitType` (sıra 11) | | Menü | `App.Hr.Definitions` › `App.Hr.BenefitType` (sıra 10) |
| Yetki | `App.Hr.BenefitType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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ı…). | | 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'` | | Kaynak | `Hr_T_BenefitType` · filtre `"IsDeleted" = 'false'` |
@ -341,4 +247,105 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
| `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | | | `IsSgkSubject` | SGK'ya Tabi | dxCheckBox | ✓ | ✓ | |
| `IsActive` | Aktif | 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 | ✓ | ✓ | |
<!-- module-doc:auto:end --> <!-- module-doc:auto:end -->

View file

@ -45,7 +45,7 @@ Kapsam: kiracı (`IsTenant`). Satır süzmesi yoktur; disiplin kaydı hassas ver
| Menü (TR / EN) | `ListFormCode` | Yer | Alt formlar | Görünümler | Widget'lar | | Menü (TR / EN) | `ListFormCode` | Yer | Alt formlar | Görünümler | Widget'lar |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| Disiplin Dosyaları / Disciplinary Cases | `App.Hr.DisciplinaryCase` | `İnsan Kaynakları` (sıra 11, `FcHighPriority`) | `DisciplinaryDefense`, `DisciplinaryDecision`, `DisciplinaryFile` (`Id → CaseId`) | Grid, Card, Pivot, Chart, **Todo** | Toplam · Açık · Savunma Bekleniyor · Kapanan (Karara Bağlandı + Kapandı) | | 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) | | 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ı Todo panosu: başlık `Subject`, açıklama `IncidentDescription`, tarih `IncidentDate`, sütun sırası
@ -68,8 +68,8 @@ AbpUsers ──< Hr_T_DisciplinaryCase ──< Hr_T_DisciplinaryDefense
| --- | --- | | --- | --- |
| `Hr_T_DisciplinaryPenaltyType` | `Name`, `Severity`, `Description`, `IsActive` | | `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_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` | | `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` | | `Hr_T_DisciplinaryDecision` | `CaseId`, `DecisionDate`, `PenaltyTypeId`, `EffectiveDate`, `NotificationDate`, `DeductionAmount`, `Status` (Draft/Final), `DecisionText` (HTML) |
| `Hr_T_DisciplinaryFile` | `CaseId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` | | `Hr_T_DisciplinaryFile` | `CaseId`, `DocumentTypeId`, `FileDate`, `FileName`, `FileContent` |
Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır. Tablo düzeyinde CHECK ya da tekil indeks yoktur; kurallar formdadır.
@ -113,6 +113,7 @@ Disiplin verisi kişisel ve hassas veridir; okuma yetkisi dar tutulmalıdır.
| Kaynak | Kullanım | | Kaynak | Kullanım |
| --- | --- | | --- | --- |
| `AbpUsers` | Personel, tutanağı tutan, tanıklar | | `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_Department`, `Hr_T_JobPosition` | Olay anındaki birim (Pivot kırılımı) |
| `Hr_T_DocumentType` | Belge türü (ortak İK tanımı) | | `Hr_T_DocumentType` | Belge türü (ortak İK tanımı) |
@ -170,7 +171,7 @@ yalnızca onayda seçilirse düşer.
| --- | --- | | --- | --- |
| Wizard | `wizard/DisciplinaryCase.json` | | Wizard | `wizard/DisciplinaryCase.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr` › `App.Hr.DisciplinaryCase` (sıra 11) | | Menü | `App.Hr` › `App.Hr.DisciplinaryCase` (sıra 10) |
| Yetki | `App.Hr.DisciplinaryCase` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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'` | | Kaynak | `Hr_T_DisciplinaryCase` · filtre `"IsDeleted" = 'false'` |
@ -204,7 +205,7 @@ yalnızca onayda seçilirse düşer.
| --- | --- | | --- | --- |
| Wizard | `wizard/DisciplinaryPenaltyType.json` | | Wizard | `wizard/DisciplinaryPenaltyType.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.DisciplinaryPenaltyType` (sıra 12) | | Menü | `App.Hr.Definitions` › `App.Hr.DisciplinaryPenaltyType` (sıra 17) |
| Yetki | `App.Hr.DisciplinaryPenaltyType` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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). | | 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'` | | Kaynak | `Hr_T_DisciplinaryPenaltyType` · filtre `"IsDeleted" = 'false'` |
@ -243,7 +244,7 @@ yalnızca onayda seçilirse düşer.
| `DueDate` | Son Savunma Tarihi | dxDateBox | ✓ | ✓ | script | | `DueDate` | Son Savunma Tarihi | dxDateBox | ✓ | ✓ | script |
| `ResponseDate` | Savunma Tarihi | dxDateBox | | ✓ | | | `ResponseDate` | Savunma Tarihi | dxDateBox | | ✓ | |
| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Requested, Submitted, NotSubmitted | | `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Requested, Submitted, NotSubmitted |
| `DefenseText` | Savunma Metni | dxTextArea | | ✓ | | | `DefenseText` | Savunma Metni | dxHtmlEditor | | ✓ | |
### Kararlar — `App.Hr.DisciplinaryDecision` ### Kararlar — `App.Hr.DisciplinaryDecision`
@ -269,7 +270,7 @@ yalnızca onayda seçilirse düşer.
| `NotificationDate` | Tebliğ Tarihi | dxDateBox | | ✓ | | | `NotificationDate` | Tebliğ Tarihi | dxDateBox | | ✓ | |
| `DeductionAmount` | Kesinti Tutarı | dxNumberBox | | ✓ | | | `DeductionAmount` | Kesinti Tutarı | dxNumberBox | | ✓ | |
| `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Draft, Final | | `Status` | Durum | dxRadioGroup | ✓ | ✓ | liste: Draft, Final |
| `DecisionText` | Karar Metni | dxTextArea | | ✓ | | | `DecisionText` | Karar Metni | dxHtmlEditor | | ✓ | |
### Belgeler — `App.Hr.DisciplinaryFile` ### Belgeler — `App.Hr.DisciplinaryFile`

View file

@ -39,7 +39,7 @@ Kapsam: kiracı (`IsTenant`). Şube isteğe bağlıdır; satır süzmesi yoktur.
| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | | Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Olay Günlüğü / Event Log | `App.Hr.EventLog` | `İnsan Kaynakları` (sıra 9, `FcViewDetails`) | Grid, Card, Pivot, Chart | Toplam · Bugün · Önemli (önem ≥ 4) | | Olay Günlüğü / Event Log | `App.Hr.EventLog` | `İnsan Kaynakları` (sıra 13, `FcViewDetails`) | Grid, Card, Pivot, Chart | Toplam · Bugün · Önemli (önem ≥ 4) |
--- ---
@ -118,7 +118,7 @@ Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer
| --- | --- | | --- | --- |
| Wizard | `wizard/EventLog.json` | | Wizard | `wizard/EventLog.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr` › `App.Hr.EventLog` (sıra 7) | | Menü | `App.Hr` › `App.Hr.EventLog` (sıra 13) |
| Yetki | `App.Hr.EventLog` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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üğü | | Geliştirme talebi | Human Resources -> Olay Günlüğü |

View file

@ -45,7 +45,7 @@ Kapsam: kiracı. Liste, kiracının **tüm kullanıcılarıdır** (aktif/pasif);
| Menü (TR / EN) | `ListFormCode` | Yer | Kaynak | Alt formlar | | Menü (TR / EN) | `ListFormCode` | Yer | Kaynak | Alt formlar |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Sağlık Kartları / Health Cards | `App.Hr.HealthCard` | `İnsan Kaynakları` (sıra 5, `FcInspection`) | `AbpUsers` | aşağıdaki 7 sekme | | 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 | | Sekme | `ListFormCode` (menüsüz) | Kaynak | İlişki | Düzenleme |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
@ -147,7 +147,7 @@ serbest metindir). Bildirim, periyodik muayene hatırlatması ya da rapor şablo
**Hastane tanımı nerede kullanılıyor?** Şu an hiçbir yerde; ileride istirahat/sevk alanlarına lookup olarak bağlanmak üzere duruyor. **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. **İ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.
--- ---
@ -174,7 +174,7 @@ entity/migration'a bağlı olduğu için kalır.
| --- | --- | | --- | --- |
| Wizard | `wizard/HealthCard.json` | | Wizard | `wizard/HealthCard.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr` › `App.Hr.HealthCard` (sıra 4) | | Menü | `App.Hr` › `App.Hr.HealthCard` (sıra 7) |
| Yetki | `App.Hr.HealthCard` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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 | | Geliştirme talebi | Human Resources -> Health Card |
@ -414,7 +414,7 @@ entity/migration'a bağlı olduğu için kalır.
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Komutlar | InsertAfter: `Hr_S_LeaveSickLeaveSync` · UpdateAfter: `Hr_S_LeaveSickLeaveSync` · DeleteAfter: SQL | | Komutlar | InsertAfter: `Hr_S_LeaveSickLeaveSync` · UpdateAfter: `Hr_S_LeaveSickLeaveSync` · DeleteAfter: `Hr_S_LeaveSickLeaveSync` |
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |

View file

@ -47,15 +47,15 @@ Kapsam: kiracı. Bütün tablolar `IMultiTenant`; satır süzmesi yoktur.
## 3. Menü ve ekranlar ## 3. Menü ve ekranlar
`İnsan Kaynakları › Intranet` (`App.Hr.Intranet`, sıra 10) `İnsan Kaynakları › Intranet` (`App.Hr.Intranet`, sıra 14)
| Sıra | Menü | `ListFormCode` / rota | Alt formlar | Widget'lar | | Sıra | Menü | `ListFormCode` / rota | Alt formlar | Widget'lar |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| 1 | Duyurular | `App.Hr.Intranet.Announcement` | `…Announcement.AnnouncementLike`, `…Announcement.AnnouncementComment` (`Id → AnnouncementId`) | Aktif · Sabitlenmiş · Süresi dolan · Toplam görüntülenme | | 1 | Etkinlik Türleri | `App.Hr.Intranet.Events.EventType` | — | — |
| 2 | Anketler | `App.Hr.Intranet.Survey` | `SurveyQuestion` (→ `SurveyQuestionOption`), `SurveyResponse` (→ `SurveyAnswer`) — iki seviyeli | Aktif · Pasif · Toplam yanıt | | 2 | Etkinlik Kategorisi | `App.Hr.Intranet.Events.EventCategory` | — | — |
| 3 | Sosyal Paylaşımlar | `App.Hr.Intranet.SocialPost` | `SocialComment`, `SocialMedia` (→ `SocialPollOption`), `SocialLike` (`Id → SocialPostId`) | Toplam · Bugün · Toplam beğeni | | 3 | Duyurular | `App.Hr.Intranet.Announcement` | `…Announcement.AnnouncementLike`, `…Announcement.AnnouncementComment` (`Id → AnnouncementId`) | Aktif · Sabitlenmiş · Süresi dolan · Toplam görüntülenme |
| 4 | Etkinlik Türleri | `App.Hr.Intranet.Events.EventType` | — | — | | 4 | Anketler | `App.Hr.Intranet.Survey` | `SurveyQuestion` (→ `SurveyQuestionOption`), `SurveyResponse` (→ `SurveyAnswer`) — iki seviyeli | Aktif · Pasif · Toplam yanıt |
| 5 | Etkinlik Kategorisi | `App.Hr.Intranet.Events.EventCategory` | — | — | | 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 | | 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) | — | — | | 7 | Dokümanlar | `/admin/intranet-documents` (özel sayfa) | — | — |
@ -76,6 +76,7 @@ Pano kutuları (seed):
| `active-surveys` | Sol / 30 | `App.Hr.Intranet.Survey.Widget` | Aktif anketler (kalan gün, soru/yanıt sayısı, doldurdum/doldur) | | `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 | | `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 | | `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ı) | | `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) | | `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 | | `upcoming-events` | Sağ / 60 | `App.Hr.Intranet.Events.Event.Widget` | Bugünden sonraki yayınlanmış ilk 3 etkinlik |
@ -83,7 +84,7 @@ Pano kutuları (seed):
| `team-performance` | Sağ / 80 | `App.Hr.TeamPerformanceReview` | Custom `TeamPerformanceWidget`: yöneticinin ekip değerlendirmeleri → Ekibimin Değerlendirmeleri | | `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 | | `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), son üçü Performans Yönetimi'nin çalışana ait özetleridir: İ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 İ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. kutudaki bağlantıyla açılır. Ayrıntı: `HrPerformance.md` §3.3.

View file

@ -58,7 +58,7 @@ Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur.
| 4 | Bakiye yetersiz | İzin türü bazında İK seçer: `BalanceExceedAction` = Engelle / Uyar ve kaydet | | 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ü) | | 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) | | 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; kayıt anında Sağlık Kartı'nda görünür, reddedilirse kalkar | | 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) | | 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) | | 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) |
@ -228,9 +228,13 @@ Her ekleme/güncellemede (Workflow kararı dahil) çalışır; `THROW` kaydı ge
| 51115 | Aralıkta çalışma günü 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) | | 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 | | 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 istirahat satırı açılır/güncellenir; reddedilen ya da türü değişen talebin istirahati kalkar. 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. Durum bildirim taşıyan bir değere geçtiyse bir kez bildirim gider, `LastNotifiedStatus` güncellenir. 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) ### 5.4 Satır koruması (`Hr_S_LeaveRequestGuard`, before-command)
@ -239,6 +243,7 @@ Her ekleme/güncellemede (Workflow kararı dahil) çalışır; `THROW` kaydı ge
| Çalışan | Yalnız kendi talebi (`51100`); durum `Onaya Gönderildi`/`Müdür Onayı` değilse düzeltme/silme yok (`51101`) | | Ç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`) | | Müdür | Silemez (`51102`); `ManagerIds` içinde olmalı (`51103`); talep `Müdür Onayı`'nda olmalı (`51104`) |
| İK | Serbest | | İ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 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 `App.Hr.LeaveRequest.Create/.Update`'e bağlıdır; sunucu yetkisi olmayan alanı düşürür. Bu yüzden
@ -248,8 +253,9 @@ Alan kilidi: persona ekranlarında çalışanın/müdürün değiştirmemesi ger
| Nereden | Ne olur | | Nereden | Ne olur |
| --- | --- | | --- | --- |
| İzin talebi, tür Rapor | `Adm_T_UserSickLeave` satırı açılır (`SickLeaveId`); talep güncellenince güncellenir, silinince/reddedilince kalkar | | İ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 talep kalkar. Kiracıda `Sick` kodlu tür yoksa eşleme yapılmaz | | 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) ### 5.6 Onay akışı (Grid Workflow)
@ -290,6 +296,7 @@ Widget'lar liste okuma yetkisiyle görünür (İzinlerim `App.Hr.MyLeaveRequest`
| `Hr_T_WorkCalendar` | Tatil ve yarım günler | | `Hr_T_WorkCalendar` | Tatil ve yarım günler |
| `AbpSettings` / `Sas_H_SettingDefinition` | Çalışma günleri ve kademeler | | `AbpSettings` / `Sas_H_SettingDefinition` | Çalışma günleri ve kademeler |
| `Adm_T_UserSickLeave` | Rapor eşlemesi | | `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` | | 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` |
--- ---
@ -372,7 +379,7 @@ nesneleri elle kaldırılır. `BalanceExceedAction` kolonu kalır (kayıpsız ek
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Widget'lar | `App.Hr.Leave.Widget.ManagerApproval`, `App.Hr.Leave.Widget.HrApproval`, `App.Hr.Leave.Widget.Approved`, `App.Hr.Leave.Widget.Rejected` | | 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` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteAfter: SQL | | 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 | | 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' | | 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' |
@ -496,7 +503,7 @@ nesneleri elle kaldırılır. `BalanceExceedAction` kolonu kalır (kayıpsız ek
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: SQL | | 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 | | Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE |
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |

View file

@ -288,6 +288,7 @@ widget yetkisi yoktur — listeyi açamayan kullanıcıya özet de gösterilmez.
| Kaynak | Kullanım | | Kaynak | Kullanım |
| --- | --- | | --- | --- |
| `AbpUsers` | Çalışan, yönetici, değerlendirici, mentor; departman/pozisyon kopyası | | `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_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`) | | `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 | | `Adm_T_UserSkill` | Tamamlanan değerlendirmenin yönetici seviyeleri kullanıcı profiline yazılır |

View file

@ -49,11 +49,15 @@ Kapsam: kiracı. Rota yetkisi `AbpIdentity.Users.Update`.
| --- | --- | --- | | --- | --- | --- |
| 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`) | | 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` | | 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), 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` | | İş | 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 | | 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 | | 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` | | 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) | — | | 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_*`): Gömülü listeler (hepsi menüsüz alt liste, `Adm_T_*`):
@ -174,6 +178,7 @@ yönetimi yetkisi yalnız İK ve sistem yöneticilerinde olmalıdır.
| Dosya | İçerik | | 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/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.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/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.Domain/Entities/Tenant/Administration/User*.cs` | Çok kayıtlı entity'ler |

View file

@ -432,6 +432,29 @@ Rapor şablonları ve bildirim satırları elle kaldırılır.
| `IsActive` | Aktif | dxCheckBox | | ✓ | | | `IsActive` | Aktif | dxCheckBox | | ✓ | |
| `Notes` | Notlar | dxTextArea | | ✓ | | | `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` ### Teklifler — `App.Hr.JobOffer`
| Özellik | Değer | | Özellik | Değer |
@ -475,36 +498,13 @@ Rapor şablonları ve bildirim satırları elle kaldırılır.
| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | | | `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | |
| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | | | `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | |
### Aday Kaynakları — `App.Hr.CandidateSource`
| Özellik | Değer |
| --- | --- |
| Wizard | `wizard/CandidateSource.json` |
| Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.CandidateSource` (sıra 13) |
| 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 | | ✓ | |
### Ret Sebepleri — `App.Hr.RejectionReason` ### Ret Sebepleri — `App.Hr.RejectionReason`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/RejectionReason.json` | | Wizard | `wizard/RejectionReason.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.RejectionReason` (sıra 14) | | Menü | `App.Hr.Definitions` › `App.Hr.RejectionReason` (sıra 7) |
| Yetki | `App.Hr.RejectionReason` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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'` | | Kaynak | `Hr_T_RejectionReason` · filtre `"IsDeleted" = 'false'` |
@ -528,7 +528,7 @@ Rapor şablonları ve bildirim satırları elle kaldırılır.
| --- | --- | | --- | --- |
| Wizard | `wizard/EvaluationCriterion.json` | | Wizard | `wizard/EvaluationCriterion.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.EvaluationCriterion` (sıra 15) | | Menü | `App.Hr.Definitions` › `App.Hr.EvaluationCriterion` (sıra 8) |
| Yetki | `App.Hr.EvaluationCriterion` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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…). | | 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'` | | Kaynak | `Hr_T_EvaluationCriterion` · filtre `"IsDeleted" = 'false'` |

View file

@ -119,11 +119,13 @@ altında üç ekranın kökü + `.Create/.Update/.Delete/.Export/.Import/.Note`;
| --- | --- | | --- | --- |
| `Sas_T_Branch` | Eğitimin şubesi | | `Sas_T_Branch` | Eğitimin şubesi |
| `AbpUsers` | Katılımcı; işe giriş tarihi, departman, pozisyon kopyası | | `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_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_Skill` / `Hr_T_SkillType` | Eğitimin kazandırdığı yetkinlikler |
| `Hr_T_DocumentType` | Eğitim dosyası türü | | `Hr_T_DocumentType` | Eğitim dosyası türü |
| Raporlar | Katılım Belgesi (`DynamicReport`, `Raporlar` kategorisi) | | 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 kayıtta kendiliğinden tamamlanır (`Hr_S_DevelopmentPlanSync`, bkz. `HrPerformance.md`). Eğitimler ekranı bu bağı bilmez | | 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) |
--- ---
@ -234,6 +236,7 @@ düşer. Gelişim planlarındaki `TrainingId` bağları silinmez, boşa düşer.
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Alt formlar | `App.Hr.TrainingParticipant` (Id → TrainingId), `App.Hr.TrainingFile` (Id → TrainingId) | | 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` | | 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 | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
@ -274,6 +277,7 @@ düşer. Gelişim planlarındaki `TrainingId` bağları silinmez, boşa düşer.
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) | | Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Komutlar | InsertAfter: `Hr_S_TrainingSync` · UpdateAfter: `Hr_S_TrainingSync` · DeleteAfter: `Hr_S_TrainingSync` |
| Butonlar | `App.Hr.TrainingParticipant.Certificate` | | Butonlar | `App.Hr.TrainingParticipant.Certificate` |
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak | | Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |

View file

@ -49,12 +49,12 @@ Kapsam: kiracı (`IsTenant`). Araç bir şubeye (tesis) bağlıdır; satır süz
| Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Widget'lar | | Sıra | Menü (TR / EN) | `ListFormCode` | Alt formlar | Widget'lar |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| 1 | Araç Belgeleri / Vehicle Documents | `App.Hr.VehicleDocument` | — | Toplam · Aktif · Pasif | | 1 | Araç Belgeleri / Vehicle Documents | `App.Hr.VehicleDocument` | — | Toplam · Aktif · Pasif |
| 2 | Araçlar / Vehicles | `App.Hr.Vehicle` | `VehicleFile` (`Id → VehicleId`) | Toplam · Geldi · Gitti · Pasif | | 2 | Masraf Tanımlama / Expense Definitions | `App.Hr.VehicleExpenseDefinition` | — | Toplam · Aktif · Pasif |
| 3 | Gidilecek Yerler / Destinations | `App.Hr.VehicleDestination` | — | Toplam · Aktif · Pasif | | 3 | Gidilecek Yerler / Destinations | `App.Hr.VehicleDestination` | — | Toplam · Aktif · Pasif |
| 4 | Şoför Tanımlama / Drivers | `App.Hr.Driver` | `DriverDocument`, `DriverPenalty`, `DriverAccident` (`Id → DriverId`) | Toplam · Zimmetli Araçlı · Toplam Km | | 4 | Araçlar / Vehicles | `App.Hr.Vehicle` | `VehicleFile` (`Id → VehicleId`) | Toplam · Geldi · Gitti · Pasif |
| 5 | Masraf Tanımlama / Expense Definitions | `App.Hr.VehicleExpenseDefinition` | — | Toplam · Aktif · Pasif | | 5 | Şoför Tanımlama / Drivers | `App.Hr.Driver` | `DriverDocument`, `DriverPenalty`, `DriverAccident` (`Id → DriverId`) | Toplam · Zimmetli Araçlı · Toplam Km |
| 6 | Masraf Girişleri / Vehicle Expenses | `App.Hr.VehicleExpense` | `VehicleExpenseLine` (`Id → VehicleExpenseId`) | Toplam · Bugün · Toplam Tutar (net kalemler) | | 6 | Araç Giriş-Çıkış Takip / Vehicle Gate Log | `App.Hr.VehicleMovement` | — | Toplam · Gitti · Bugün |
| 7 | 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. Tüm ekranlar Grid, Card, Pivot, Chart görünümleriyle gelir; özel görünüm (Todo, Scheduler) yoktur.
@ -240,13 +240,60 @@ tablolar yalnızca onayda seçilirse düşer.
| `Name` | Belge Adı | dxTextBox | ✓ | ✓ | | | `Name` | Belge Adı | dxTextBox | ✓ | ✓ | |
| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | | `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` ### Araçlar — `App.Hr.Vehicle`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/Vehicle.json` | | Wizard | `wizard/Vehicle.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Vehicles` › `App.Hr.Vehicle` (sıra 2) | | Menü | `App.Hr.Vehicles` › `App.Hr.Vehicle` (sıra 4) |
| Yetki | `App.Hr.Vehicle` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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 | | Geliştirme talebi | Human Resources -> Araçlar |
@ -280,36 +327,13 @@ tablolar yalnızca onayda seçilirse düşer.
| `TachographStart` | Takograf Kalib. Başlangıç | dxDateBox | | ✓ | | | `TachographStart` | Takograf Kalib. Başlangıç | dxDateBox | | ✓ | |
| `TachographEnd` | Takograf Kalib. Bitiş | dxDateBox | | ✓ | | | `TachographEnd` | Takograf Kalib. Bitiş | dxDateBox | | ✓ | |
### 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 | ✓ | ✓ | |
### Şoför Tanımlama — `App.Hr.Driver` ### Şoför Tanımlama — `App.Hr.Driver`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/Driver.json` | | Wizard | `wizard/Driver.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Vehicles` › `App.Hr.Driver` (sıra 4) | | Menü | `App.Hr.Vehicles` › `App.Hr.Driver` (sıra 5) |
| Yetki | `App.Hr.Driver` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | 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 | | Geliştirme talebi | Human Resources -> Araçlar |
@ -330,64 +354,13 @@ tablolar yalnızca onayda seçilirse düşer.
| `Vehicle5Id` | Zimmetli Araç 5 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle | | `Vehicle5Id` | Zimmetli Araç 5 | dxSelectBox | | ✓ | sorgu: Hr_T_Vehicle |
| `TotalKm` | Yapılan KM | dxNumberBox | | ✓ | | | `TotalKm` | Yapılan KM | dxNumberBox | | ✓ | |
### 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 5) |
| 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 | ✓ | ✓ | |
### 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 6) |
| 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ç Giriş-Çıkış Takip — `App.Hr.VehicleMovement` ### Araç Giriş-Çıkış Takip — `App.Hr.VehicleMovement`
| Özellik | Değer | | Özellik | Değer |
| --- | --- | | --- | --- |
| Wizard | `wizard/VehicleMovement.json` | | Wizard | `wizard/VehicleMovement.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Vehicles` › `App.Hr.VehicleMovement` (sıra 7) | | Menü | `App.Hr.Vehicles` › `App.Hr.VehicleMovement` (sıra 6) |
| Yetki | `App.Hr.VehicleMovement` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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ü. | | 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 | | Geliştirme talebi | Human Resources -> Araçlar |
@ -423,6 +396,33 @@ tablolar yalnızca onayda seçilirse düşer.
| `DurationMinutes` | Gezinti Süresi / Dk | dxNumberBox | | ✓ | | | `DurationMinutes` | Gezinti Süresi / Dk | dxNumberBox | | ✓ | |
| `ExpectedKm` | Olması Gereken Km | 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` ### Araç Belgeleri — `App.Hr.VehicleFile`
| Özellik | Değer | | Özellik | Değer |

View file

@ -38,7 +38,7 @@ Kapsam: kiracı (`IsTenant`). Her kayıt bir şubeye bağlıdır; satır süzmes
| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar (bugün) | | Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar (bugün) |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Ziyaretçiler / Visitors | `App.Hr.Visitor` | `İnsan Kaynakları` (sıra 8, `FcBusinessman`) | Grid, Card, Pivot, Chart | Bugün Gelen · İçeride · Çıkış Yapan | | 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. Widget'lar yalnız **bugünün** (`VisitDate = bugün`) kayıtlarını sayar.
@ -124,7 +124,7 @@ Geri alma: Wizard Manager'dan silinir; tablo yalnızca onayda seçilirse düşer
| --- | --- | | --- | --- |
| Wizard | `wizard/Visitor.json` | | Wizard | `wizard/Visitor.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr` › `App.Hr.Visitor` (sıra 3) | | Menü | `App.Hr` › `App.Hr.Visitor` (sıra 12) |
| Yetki | `App.Hr.Visitor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Yetki | `App.Hr.Visitor` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
| Açıklama | Ziyaretçiler — güvenlik/resepsiyonun tuttuğu ziyaretçi giriş-çıkış defteri. | | Açıklama | Ziyaretçiler — güvenlik/resepsiyonun tuttuğu ziyaretçi giriş-çıkış defteri. |
| Geliştirme talebi | Human Resources -> Ziyaretçi Takip Listesi | | Geliştirme talebi | Human Resources -> Ziyaretçi Takip Listesi |

View file

@ -35,7 +35,7 @@ Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur — takvim kiracının t
| Vardiya saatleri | `StartTime` / `EndTime` `SS:dd` metin; çalışma süresi elle girilir (otomatik hesap yok) | | 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 | | 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ş)") | | Vardiya bağı | Kullanıcı kaydında `ShiftId` alanı (`LookupQueryValues.TenantShiftValues`: "Ad (başlangıç-bitiş)") |
| Menü yeri | Çalışma Takvimi ve Vardiyalar `İnsan Kaynakları` kökündedir. Vardiyalar wizard dosyasında üst menü `App.Hr.Definitions` yazılıdır, menü satırı kökte durur (bkz. §9) | | 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) |
--- ---
@ -43,8 +43,8 @@ Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur — takvim kiracının t
| Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar | | Menü (TR / EN) | `ListFormCode` | Yer | Görünümler | Widget'lar |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Çalışma Takvimi / Work Calendar | `App.Hr.WorkCalendar` | `İnsan Kaynakları` (sıra 2, `FcCalendar`) | Grid, Card, Pivot, Chart, **Scheduler** | Toplam · Tatil · Yarım Gün | | Ç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ı` (sıra 3, `FcClock`) | Grid, Card, Pivot, Chart | Toplam · Aktif · Pasif | | 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`, Scheduler eşlemesi: metin `Name`, başlangıç `StartDate`, bitiş `EndDate`, tüm gün `AllDay`,
tekrar `RecurrenceRule`. tekrar `RecurrenceRule`.
@ -63,7 +63,7 @@ Seed verisi:
| Tablo | Kolonlar | | Tablo | Kolonlar |
| --- | --- | | --- | --- |
| `Hr_T_WorkCalendar` | `Name`, `StartDate`, `EndDate`, `DayType` (Holiday/HalfDay), `RecurrenceRule` (boş / `FREQ=YEARLY`), `AllDay`, `IsActive` | | `Hr_T_WorkCalendar` | `Name`, `StartDate`, `EndDate`, `DayType` (Holiday/HalfDay), `RecurrenceRule` (boş / `FREQ=YEARLY`), `AllDay`, `IsActive` |
| `Hr_T_Shift` | `Name`, `StartTime`, `EndTime`, `BreakMinutes`, `WorkingHours`, `IsNightShift`, `IsActive` | | `Hr_T_Shift` | `Name`, `StartTime`, `EndTime`, `BreakMinutes`, `LateToleranceMinutes`, `EarlyLeaveToleranceMinutes`, `WorkingHours`, `IsNightShift`, `IsActive` |
| `AbpUsers.ShiftId` | Çalışanın vardiyası (genişletme kolonu) | | `AbpUsers.ShiftId` | Çalışanın vardiyası (genişletme kolonu) |
Entity yoktur (wizard tabloları); `sql/object/Hr_T_{WorkCalendar,Shift}.sql`. Entity yoktur (wizard tabloları); `sql/object/Hr_T_{WorkCalendar,Shift}.sql`.
@ -78,7 +78,10 @@ Entity yoktur (wizard tabloları); `sql/object/Hr_T_{WorkCalendar,Shift}.sql`.
| Takvim — çok günlü tatil | Başlangıç–bitiş aralığı olarak tek satırda girilebilir | | Takvim — çok günlü tatil | Başlangıç–bitiş aralığı olarak tek satırda girilebilir |
| Vardiya — yeni kayıt | Gece vardiyası hayır, aktif | | Vardiya — yeni kayıt | Gece vardiyası hayır, aktif |
Takvim ve vardiya başka bir hesaba (izin günü, mesai, puantaj) **bağlı değildir**; platformda puantaj/izin hesaplayan modül yoktur. | 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.
--- ---
@ -96,6 +99,8 @@ Hiçbir yetki role otomatik atanmaz. Takvimin okunması tüm çalışanlara aç
| Kimlik › Kullanıcılar | `ShiftId` alanı vardiya lookup'ı | | Kimlik › Kullanıcılar | `ShiftId` alanı vardiya lookup'ı |
| Olay Günlüğü (`App.Hr.EventLog`) | Olay kaydında vardiya seçimi | | 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) | | 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 |
--- ---
@ -113,11 +118,13 @@ Hiçbir yetki role otomatik atanmaz. Takvimin okunması tüm çalışanlara aç
**Çalışma süresi neden hesaplanmıyor?** Vardiya saatleri metindir, süre elle girilir. **Çalışma süresi neden hesaplanmıyor?** Vardiya saatleri metindir, süre elle girilir.
**Takvim izin/puantaj hesabını etkiliyor mu?** Hayır; bu hesapları yapan bir modül yoktur. **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 menüde Tanımlamalar altında değil.** Menü satırı `İnsan Kaynakları` kökündedir; wizard **Vardiyalar nerede?** `İnsan Kaynakları › Tanımlamalar` altında (sıra 11); menü satırı, wizard dosyası ve
dosyasındaki üst menü (`App.Hr.Definitions`) eski değerdir. Wizard yeniden deploy edilirse menü yetki ağacı aynı yeri gösterir.
Tanımlamalar altına taşınabilir — yeniden deploy etmeden önce wizard'daki üst menü kökle eşitlenmelidir.
--- ---
@ -143,7 +150,7 @@ Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının l
| --- | --- | | --- | --- |
| Wizard | `wizard/WorkCalendar.json` | | Wizard | `wizard/WorkCalendar.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr` › `App.Hr.WorkCalendar` (sıra 2) | | Menü | `App.Hr` › `App.Hr.WorkCalendar` (sıra 4) |
| Yetki | `App.Hr.WorkCalendar` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | 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. | | Açıklama | Çalışma Takvimi — resmi tatiller, arife (yarım gün) ve çalışılmayan günler. |
| Kaynak | `Hr_T_WorkCalendar` · filtre `"IsDeleted" = 'false'` | | Kaynak | `Hr_T_WorkCalendar` · filtre `"IsDeleted" = 'false'` |
@ -151,6 +158,7 @@ Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının l
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup | | Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
| Kapsam | Kiracı | | Kapsam | Kiracı |
| Widget'lar | `App.Widget.Total`, `App.Hr.WorkCalendar.DayType.Holiday`, `App.Hr.WorkCalendar.DayType.HalfDay` | | 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 | | Form varsayılanları | DayType=Holiday, RecurrenceRule=FREQ=YEARLY, AllDay=true, IsActive=true |
| Veri aynası | `data/App.Hr.WorkCalendar.json` | | Veri aynası | `data/App.Hr.WorkCalendar.json` |
@ -170,7 +178,7 @@ Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının l
| --- | --- | | --- | --- |
| Wizard | `wizard/Shift.json` | | Wizard | `wizard/Shift.json` |
| Yol | Liste (Wizard) | | Yol | Liste (Wizard) |
| Menü | `App.Hr.Definitions` › `App.Hr.Shift` (sıra 9) | | Menü | `App.Hr.Definitions` › `App.Hr.Shift` (sıra 11) |
| Yetki | `App.Hr.Shift` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` | | Yetki | `App.Hr.Shift` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
| Açıklama | Vardiyalar — çalışma vardiyalarının tanımı (sabah, akşam, gece…). | | Açıklama | Vardiyalar — çalışma vardiyalarının tanımı (sabah, akşam, gece…). |
| Geliştirme talebi | Human Resources -> Olay Günlüğü | | Geliştirme talebi | Human Resources -> Olay Günlüğü |
@ -188,6 +196,8 @@ Geri alma: Wizard Manager'dan silinir; vardiya tablosu kullanıcı ekranının l
| `StartTime` | Başlangıç Saati | dxTextBox | | ✓ | | | `StartTime` | Başlangıç Saati | dxTextBox | | ✓ | |
| `EndTime` | Bitiş Saati | dxTextBox | | ✓ | | | `EndTime` | Bitiş Saati | dxTextBox | | ✓ | |
| `BreakMinutes` | Mola (dk) | dxNumberBox | | ✓ | | | `BreakMinutes` | Mola (dk) | dxNumberBox | | ✓ | |
| `LateToleranceMinutes` | Geç Kalma Toleransı (dk) | dxNumberBox | | ✓ | |
| `EarlyLeaveToleranceMinutes` | Erken Çıkış Toleransı (dk) | dxNumberBox | | ✓ | |
| `WorkingHours` | Çalışma Süresi (Saat) | dxNumberBox | | ✓ | | | `WorkingHours` | Çalışma Süresi (Saat) | dxNumberBox | | ✓ | |
| `IsNightShift` | Gece Vardiyası | dxCheckBox | ✓ | ✓ | | | `IsNightShift` | Gece Vardiyası | dxCheckBox | ✓ | ✓ | |
| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | | | `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | |

View file

@ -0,0 +1,32 @@
CREATE OR ALTER FUNCTION [dbo].[Hr_F_LeaveNetDays]
(
@TenantId uniqueidentifier,
@EmployeeId uniqueidentifier,
@StartDate date,
@EndDate date
)
RETURNS decimal(9, 1)
AS
BEGIN
-- İzin talebinin düştüğü gün sayısı: çalışma günleri (Hr_F_LeaveWorkDays) eksi çalışanın
-- rapor (istirahat) kapsamındaki günleri. İzin sırasında alınan raporun günleri izinden sayılmaz;
-- puantajda da o günler Raporlu'dur, bakiye ile puantaj aynı günü iki kez kullanmaz.
IF @StartDate IS NULL OR @EndDate IS NULL OR @EndDate < @StartDate
RETURN 0;
DECLARE @Total decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, @StartDate, @EndDate);
DECLARE @Day date = @StartDate;
WHILE @Day <= @EndDate AND @Total > 0
BEGIN
IF EXISTS (SELECT 1 FROM Adm_T_UserSickLeave s
WHERE s.UserId = @EmployeeId AND s.IsDeleted = 0
AND @Day BETWEEN CAST(s.StartDate AS date) AND CAST(s.EndDate AS date))
SET @Total -= dbo.Hr_F_LeaveWorkDays(@TenantId, @Day, @Day);
SET @Day = DATEADD(day, 1, @Day);
END
RETURN CASE WHEN @Total < 0 THEN 0 ELSE @Total END;
END
GO

View file

@ -0,0 +1,25 @@
CREATE OR ALTER FUNCTION [dbo].[Hr_F_TimesheetPeriodClosed]
(
@TenantId uniqueidentifier,
@StartDate date,
@EndDate date
)
RETURNS bit
AS
BEGIN
-- Aralığın değdiği aylardan biri kapalı puantaj dönemiyse 1. Puantajı değiştiren kayıtlar
-- (izin, rapor, puantaj günü) kapalı aya yazılamaz; dönemi İK açar, açılış ayı yeniden hesaplar.
IF @StartDate IS NULL OR @EndDate IS NULL
RETURN 0;
IF EXISTS (
SELECT 1 FROM Hr_T_TimesheetPeriod p
WHERE p.IsDeleted = 0 AND p.[Status] = N'Closed'
AND (p.TenantId = @TenantId OR (p.TenantId IS NULL AND @TenantId IS NULL))
AND p.PeriodYear * 100 + p.PeriodMonth
BETWEEN YEAR(@StartDate) * 100 + MONTH(@StartDate) AND YEAR(@EndDate) * 100 + MONTH(@EndDate))
RETURN 1;
RETURN 0;
END
GO

View file

@ -0,0 +1,25 @@
CREATE OR ALTER FUNCTION [dbo].[Hr_F_WorkCalendarDayType]
(
@TenantId uniqueidentifier,
@Day date
)
RETURNS nvarchar(16)
AS
BEGIN
-- Çalışma Takvimi'nde güne düşen tür: Holiday (tam gün tatil) yarım günü (HalfDay) ezer; yoksa NULL.
-- Yıllık tekrarlı satır eşlemesi Hr_F_LeaveWorkDays ile aynıdır.
RETURN (
SELECT CASE WHEN MAX(CASE WHEN c.DayType = N'Holiday' THEN 1 ELSE 0 END) = 1 THEN N'Holiday' ELSE N'HalfDay' END
FROM Hr_T_WorkCalendar c
WHERE c.IsDeleted = 0 AND c.IsActive = 1
AND (c.TenantId = @TenantId OR (c.TenantId IS NULL AND @TenantId IS NULL))
AND (
((c.RecurrenceRule IS NULL OR c.RecurrenceRule = N'') AND @Day BETWEEN CAST(c.StartDate AS date) AND CAST(c.EndDate AS date))
OR (c.RecurrenceRule = N'FREQ=YEARLY' AND YEAR(@Day) >= YEAR(c.StartDate)
AND @Day BETWEEN CAST(DATEADD(year, YEAR(@Day) - YEAR(c.StartDate), c.StartDate) AS date)
AND CAST(DATEADD(year, YEAR(@Day) - YEAR(c.StartDate), c.EndDate) AS date))
)
HAVING COUNT(*) > 0
);
END
GO

View file

@ -0,0 +1,77 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_AttendanceImport]
@TenantId nvarchar(64),
@UserId nvarchar(64),
@Items nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
-- PDKS ucu (Custom Endpoint POST /hr/attendance/): gövdedeki Items JSON dizisini hareket olarak
-- yazar. Her öğe: CardNo (kullanıcı kartındaki PDKS Kart No), RegistrationNo (Sicil No) ya da UserName;
-- EventTime (yerel saat, ISO 8601), Direction (In/Out/Auto), DeviceCode. Kart/sicil eşlemesini
-- Hr_S_AttendanceProcess yapar. Aynı kişi ve aynı zamanla daha önce gelmiş okutma atlanır; kapalı
-- döneme düşen ve kartı tanımsız okutma hatalı işaretlenir, gönderimi durdurmaz.
DECLARE @Tenant uniqueidentifier = TRY_CONVERT(uniqueidentifier, @TenantId),
@Actor uniqueidentifier = TRY_CONVERT(uniqueidentifier, @UserId);
IF @Items IS NULL OR ISJSON(@Items) <> 1
THROW 51210, N'Items geçerli bir JSON dizisi olmalıdır.', 1;
CREATE TABLE #aiItem
(
CardNo nvarchar(64) NULL, UserName nvarchar(256) NULL, EventTime datetime2 NULL,
Direction nvarchar(8) NULL, DeviceCode nvarchar(64) NULL, EmployeeId uniqueidentifier NULL
);
INSERT INTO #aiItem (CardNo, UserName, EventTime, Direction, DeviceCode)
SELECT COALESCE(NULLIF(LTRIM(RTRIM(CardNo)), N''), NULLIF(LTRIM(RTRIM(RegistrationNo)), N'')),
NULLIF(LTRIM(RTRIM(UserName)), N''),
TRY_CONVERT(datetime2, EventTime),
CASE WHEN Direction IN (N'In', N'Out') THEN Direction ELSE N'Auto' END,
DeviceCode
FROM OPENJSON(@Items)
WITH (
CardNo nvarchar(64) '$.CardNo',
RegistrationNo nvarchar(64) '$.RegistrationNo',
UserName nvarchar(256) '$.UserName',
EventTime nvarchar(40) '$.EventTime',
Direction nvarchar(8) '$.Direction',
DeviceCode nvarchar(64) '$.DeviceCode'
);
DECLARE @Received int = (SELECT COUNT(*) FROM #aiItem);
DELETE FROM #aiItem WHERE EventTime IS NULL OR (CardNo IS NULL AND UserName IS NULL);
UPDATE i
SET EmployeeId = u.Id
FROM #aiItem i
INNER JOIN AbpUsers u ON u.UserName = i.UserName AND u.IsDeleted = 0
AND (u.TenantId = @Tenant OR (u.TenantId IS NULL AND @Tenant IS NULL))
WHERE i.UserName IS NOT NULL;
DECLARE @Inserted TABLE (Id uniqueidentifier);
INSERT INTO Hr_T_AttendanceLog
(Id, TenantId, EmployeeId, CardNo, EventTime, Direction, Source, DeviceCode, IsProcessed, CreationTime, CreatorId, IsDeleted)
OUTPUT inserted.Id INTO @Inserted (Id)
SELECT NEWID(), @Tenant, n.EmployeeId, n.CardNo, n.EventTime, n.Direction, N'Pdks', n.DeviceCode, 0, GETUTCDATE(), @Actor, 0
FROM (
SELECT DISTINCT EmployeeId, CardNo, EventTime, Direction, DeviceCode FROM #aiItem
) n
WHERE NOT EXISTS (
SELECT 1 FROM Hr_T_AttendanceLog l
WHERE l.IsDeleted = 0 AND l.EventTime = n.EventTime
AND (l.TenantId = @Tenant OR (l.TenantId IS NULL AND @Tenant IS NULL))
AND ((n.EmployeeId IS NOT NULL AND l.EmployeeId = n.EmployeeId)
OR (n.EmployeeId IS NULL AND l.CardNo = n.CardNo)));
EXEC dbo.Hr_S_AttendanceProcess 0;
SELECT @Received AS Received,
(SELECT COUNT(*) FROM @Inserted) AS Inserted,
@Received - (SELECT COUNT(*) FROM @Inserted) AS Skipped,
(SELECT COUNT(*) FROM Hr_T_AttendanceLog l INNER JOIN @Inserted i ON i.Id = l.Id
WHERE l.ProcessError IS NOT NULL) AS Errors;
END
GO

View file

@ -0,0 +1,96 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_AttendanceProcess]
@FailOnClosed bit = 1
AS
BEGIN
SET NOCOUNT ON;
-- İşlenmemiş hareketleri (ekran, Excel import, PDKS ucu; silinenler dahil) işler: çalışanı kullanıcı
-- kartındaki PDKS Kart No'dan (yoksa Sicil No'dan) bulur, hareketin iş gününü vardiyaya göre belirler ve etkilenen günlerin puantajını
-- yeniden hesaplar. Ekrandan gelen değişiklik kapalı döneme düşerse kayıt geri alınır
-- (@FailOnClosed = 1); PDKS ve gece işinde satır hatalı işaretlenir.
CREATE TABLE #apLog
(
Id uniqueidentifier PRIMARY KEY, TenantId uniqueidentifier NULL, EmployeeId uniqueidentifier NULL,
CardNo nvarchar(64) NULL, EventTime datetime2, IsDeleted bit, OldWorkDate date NULL,
NewWorkDate date NULL, Error nvarchar(32) NULL
);
INSERT INTO #apLog (Id, TenantId, EmployeeId, CardNo, EventTime, IsDeleted, OldWorkDate)
SELECT Id, TenantId, EmployeeId, CardNo, EventTime, IsDeleted, WorkDate
FROM Hr_T_AttendanceLog
WHERE IsProcessed = 0;
IF NOT EXISTS (SELECT 1 FROM #apLog)
RETURN;
UPDATE a
SET EmployeeId = u.Id
FROM #apLog a
CROSS APPLY (
SELECT TOP 1 x.Id
FROM AbpUsers x
WHERE (x.PdksCardNo = a.CardNo OR x.RegistrationNo = a.CardNo) AND x.IsDeleted = 0
AND (x.TenantId = a.TenantId OR (x.TenantId IS NULL AND a.TenantId IS NULL))
ORDER BY CASE WHEN x.PdksCardNo = a.CardNo THEN 0 ELSE 1 END, x.IsActive DESC
) u
WHERE a.EmployeeId IS NULL AND a.CardNo IS NOT NULL AND a.CardNo <> N'';
UPDATE #apLog SET Error = N'UnknownCard' WHERE EmployeeId IS NULL AND IsDeleted = 0;
UPDATE a
SET NewWorkDate = CAST(DATEADD(minute, -s.DayOffset, a.EventTime) AS date)
FROM #apLog a
INNER JOIN Hr_V_AttendanceShift s ON s.EmployeeId = a.EmployeeId
WHERE a.IsDeleted = 0 AND a.Error IS NULL;
-- Kapalı dönem: hareketin eski ya da yeni günü kapalı aya düşüyorsa.
UPDATE a
SET Error = N'ClosedPeriod'
FROM #apLog a
WHERE EXISTS (
SELECT 1 FROM Hr_T_TimesheetPeriod p
WHERE p.IsDeleted = 0 AND p.Status = N'Closed'
AND (p.TenantId = a.TenantId OR (p.TenantId IS NULL AND a.TenantId IS NULL))
AND ((p.PeriodYear = YEAR(a.OldWorkDate) AND p.PeriodMonth = MONTH(a.OldWorkDate))
OR (p.PeriodYear = YEAR(a.NewWorkDate) AND p.PeriodMonth = MONTH(a.NewWorkDate))));
IF @FailOnClosed = 1 AND EXISTS (SELECT 1 FROM #apLog WHERE Error = N'ClosedPeriod')
THROW 51200, N'Kapalı puantaj dönemine ait hareket eklenemez, değiştirilemez ya da silinemez. Dönemi İnsan Kaynakları açabilir.', 1;
UPDATE l
SET EmployeeId = a.EmployeeId,
WorkDate = CASE WHEN a.Error = N'ClosedPeriod' THEN l.WorkDate ELSE a.NewWorkDate END,
ProcessError = a.Error,
Source = COALESCE(l.Source, N'Import'),
IsProcessed = 1
FROM Hr_T_AttendanceLog l
INNER JOIN #apLog a ON a.Id = l.Id;
-- Etkilenen günler: hareketin eski günü (taşındıysa ya da silindiyse) ve yeni günü.
DECLARE @Keys TABLE (TenantId uniqueidentifier NULL, EmployeeId uniqueidentifier, FromDate date, ToDate date);
INSERT INTO @Keys (TenantId, EmployeeId, FromDate, ToDate)
SELECT TenantId, EmployeeId, MIN(D), MAX(D)
FROM (
SELECT TenantId, EmployeeId, OldWorkDate AS D FROM #apLog
WHERE EmployeeId IS NOT NULL AND OldWorkDate IS NOT NULL AND COALESCE(Error, N'') <> N'ClosedPeriod'
UNION ALL
SELECT TenantId, EmployeeId, NewWorkDate FROM #apLog
WHERE EmployeeId IS NOT NULL AND NewWorkDate IS NOT NULL AND Error IS NULL
) k
GROUP BY TenantId, EmployeeId;
DECLARE @TenantId uniqueidentifier, @EmployeeId uniqueidentifier, @FromDate date, @ToDate date;
DECLARE key_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT TenantId, EmployeeId, FromDate, ToDate FROM @Keys;
OPEN key_cursor;
FETCH NEXT FROM key_cursor INTO @TenantId, @EmployeeId, @FromDate, @ToDate;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, @EmployeeId, @FromDate, @ToDate, NULL;
FETCH NEXT FROM key_cursor INTO @TenantId, @EmployeeId, @FromDate, @ToDate;
END
CLOSE key_cursor;
DEALLOCATE key_cursor;
END
GO

View file

@ -0,0 +1,19 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_LeaveDaysRefresh]
@TenantId uniqueidentifier,
@EmployeeId uniqueidentifier
AS
BEGIN
SET NOCOUNT ON;
-- Rapor eklenince, tarihi değişince ya da silinince çalışanın diğer izin taleplerinin gün sayısı
-- yeniden hesaplanır (Hr_F_LeaveNetDays): rapora denk gelen yıllık izin günü bakiyeye geri döner.
-- Rapor türündeki talep kendi günlerini sayar; onun gün sayısına dokunulmaz.
UPDATE r
SET Days = CASE WHEN r.IsHalfDay = 1 AND n.Days > 0.5 THEN 0.5 ELSE n.Days END
FROM Hr_T_LeaveRequest r
INNER JOIN Hr_T_LeaveType t ON t.Id = r.LeaveTypeId
CROSS APPLY (SELECT dbo.Hr_F_LeaveNetDays(@TenantId, r.EmployeeId, CAST(r.StartDate AS date), CAST(r.EndDate AS date)) AS Days) n
WHERE r.EmployeeId = @EmployeeId AND r.IsDeleted = 0 AND t.Code <> N'Sick'
AND r.Days <> CASE WHEN r.IsHalfDay = 1 AND n.Days > 0.5 THEN 0.5 ELSE n.Days END;
END
GO

View file

@ -6,9 +6,10 @@ AS
BEGIN BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
-- İzin talebinin her kaydından (ekleme, güncelleme, Grid Workflow kararı) sonra çalışır: -- İzin talebinin her kaydından (ekleme, güncelleme, Grid Workflow kararı, silme) sonra çalışır:
-- çalışan bilgisi, talep no, müdür, gün sayısı tamamlanır; kurallar doğrulanır (THROW kaydı -- çalışan bilgisi, talep no, müdür, gün sayısı tamamlanır; kurallar doğrulanır (THROW kaydı
-- geri alır); rapor türü Sağlık Kartı istirahatiyle eşlenir; durum değiştiyse bildirim gider. -- geri alır); onaylı rapor türü Sağlık Kartı istirahatiyle eşlenir; durum değiştiyse bildirim
-- gider; puantaj yeniden hesaplanır.
DECLARE @StatusStart nvarchar(50) = N'Onaya Gönderildi', DECLARE @StatusStart nvarchar(50) = N'Onaya Gönderildi',
@StatusManager nvarchar(50) = N'Müdür Onayı', @StatusManager nvarchar(50) = N'Müdür Onayı',
@StatusHr nvarchar(50) = N'İK Onayı', @StatusHr nvarchar(50) = N'İK Onayı',
@ -18,28 +19,50 @@ BEGIN
DECLARE @TenantId uniqueidentifier, @EmployeeId uniqueidentifier, @LeaveTypeId uniqueidentifier, DECLARE @TenantId uniqueidentifier, @EmployeeId uniqueidentifier, @LeaveTypeId uniqueidentifier,
@StartDate datetime2, @EndDate datetime2, @IsHalfDay bit, @HalfDayPart nvarchar(16), @StartDate datetime2, @EndDate datetime2, @IsHalfDay bit, @HalfDayPart nvarchar(16),
@Document nvarchar(MAX), @SickLeaveId uniqueidentifier, @Status nvarchar(50), @Document nvarchar(MAX), @SickLeaveId uniqueidentifier, @Status nvarchar(50),
@LastStatus nvarchar(50), @Description nvarchar(1024); @LastStatus nvarchar(50), @Description nvarchar(1024), @IsDeleted bit;
SELECT @TenantId = TenantId, @EmployeeId = EmployeeId, @LeaveTypeId = LeaveTypeId, SELECT @TenantId = TenantId, @EmployeeId = EmployeeId, @LeaveTypeId = LeaveTypeId,
@StartDate = StartDate, @EndDate = EndDate, @IsHalfDay = IsHalfDay, @HalfDayPart = HalfDayPart, @StartDate = StartDate, @EndDate = EndDate, @IsHalfDay = IsHalfDay, @HalfDayPart = HalfDayPart,
@Document = DocumentContent, @SickLeaveId = SickLeaveId, @Status = ApprovalStatus, @Document = DocumentContent, @SickLeaveId = SickLeaveId, @Status = ApprovalStatus,
@LastStatus = LastNotifiedStatus, @Description = [Description] @LastStatus = LastNotifiedStatus, @Description = [Description], @IsDeleted = IsDeleted
FROM Hr_T_LeaveRequest FROM Hr_T_LeaveRequest
WHERE Id = @RequestId AND IsDeleted = 0; WHERE Id = @RequestId;
IF @EmployeeId IS NULL IF @EmployeeId IS NULL
RETURN; RETURN;
-- Puantajı kapanmış aya düşen talep eklenemez, değiştirilemez, silinemez (eski tarihleri
-- Hr_S_LeaveRequestGuard denetler).
IF dbo.Hr_F_TimesheetPeriodClosed(@TenantId, CAST(@StartDate AS date), CAST(@EndDate AS date)) = 1
THROW 51118, N'İzin tarihleri kapalı bir puantaj dönemine düşüyor. Önce İnsan Kaynakları dönemi açmalıdır.', 1;
IF @IsDeleted = 1
BEGIN
-- Silinen talebin istirahati de kalkar; rapora denk gelen izin günleri ve puantaj yenilenir.
IF @SickLeaveId IS NOT NULL
BEGIN
UPDATE Adm_T_UserSickLeave
SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId
WHERE Id = @SickLeaveId AND IsDeleted = 0;
EXEC dbo.Hr_S_LeaveDaysRefresh @TenantId, @EmployeeId;
END
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, @EmployeeId, @StartDate, @EndDate, @ActorId;
RETURN;
END
DECLARE @Message nvarchar(1024); DECLARE @Message nvarchar(1024);
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
-- Çalışan ve departman müdürü -- Çalışan ve departman müdürü
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
DECLARE @EmployeeName nvarchar(256), @DepartmentId uniqueidentifier, @JobPositionId uniqueidentifier, DECLARE @EmployeeName nvarchar(256), @DepartmentId uniqueidentifier, @JobPositionId uniqueidentifier,
@Gender nvarchar(16); @Gender nvarchar(16), @HireDate date, @TerminationDate date;
SELECT @EmployeeName = CONCAT(Name, N' ', Surname), @DepartmentId = DepartmentId, SELECT @EmployeeName = CONCAT(Name, N' ', Surname), @DepartmentId = DepartmentId,
@JobPositionId = JobPositionId, @Gender = Gender @JobPositionId = JobPositionId, @Gender = Gender,
@HireDate = CAST(HireDate AS date), @TerminationDate = CAST(TerminationDate AS date)
FROM AbpUsers FROM AbpUsers
WHERE Id = @EmployeeId; WHERE Id = @EmployeeId;
@ -158,16 +181,14 @@ BEGIN
SELECT @TypeCode = Code, @TypeGender = Gender, @MaxDaysPerYear = MaxDaysPerYear, SELECT @TypeCode = Code, @TypeGender = Gender, @MaxDaysPerYear = MaxDaysPerYear,
@Deducts = DeductsFromAnnualLeave, @RequiresDocument = RequiresDocument, @Deducts = DeductsFromAnnualLeave, @RequiresDocument = RequiresDocument,
@AllowHalfDay = AllowHalfDay @AllowHalfDay = AllowHalfDay, @ExceedAction = BalanceExceedAction
FROM Hr_T_LeaveType FROM Hr_T_LeaveType
WHERE Id = @LeaveTypeId; WHERE Id = @LeaveTypeId;
-- Kolon Hr_T_LeaveType.sql'de sonradan eklenir; migrate prosedürleri tablolardan önce -- Rapor türü kendi çalışma günlerini sayar; diğer türlerde rapora denk gelen gün izinden düşmez.
-- derlediği için kurulu bir veritabanında doğrudan başvuru derlemeyi düşürürdü. DECLARE @WorkDays decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, CAST(@StartDate AS date), CAST(@EndDate AS date));
EXEC sp_executesql N'SELECT @Action = BalanceExceedAction FROM Hr_T_LeaveType WHERE Id = @Id', DECLARE @Days decimal(9, 1) = CASE WHEN @TypeCode = N'Sick' THEN @WorkDays
N'@Action nvarchar(16) OUTPUT, @Id uniqueidentifier', @Action = @ExceedAction OUTPUT, @Id = @LeaveTypeId; ELSE dbo.Hr_F_LeaveNetDays(@TenantId, @EmployeeId, CAST(@StartDate AS date), CAST(@EndDate AS date)) END;
DECLARE @Days decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, CAST(@StartDate AS date), CAST(@EndDate AS date));
IF @IsHalfDay = 1 IF @IsHalfDay = 1
SET @Days = CASE WHEN @Days > 0.5 THEN 0.5 ELSE @Days END; SET @Days = CASE WHEN @Days > 0.5 THEN 0.5 ELSE @Days END;
@ -187,9 +208,13 @@ BEGIN
IF @RequiresDocument = 1 AND (@Document IS NULL OR @Document = N'') IF @RequiresDocument = 1 AND (@Document IS NULL OR @Document = N'')
THROW 51114, N'Bu izin türü için belge (rapor vb.) eklenmelidir.', 1; THROW 51114, N'Bu izin türü için belge (rapor vb.) eklenmelidir.', 1;
IF @Days <= 0 IF @WorkDays <= 0
THROW 51115, N'Seçilen tarih aralığında çalışma günü yok.', 1; THROW 51115, N'Seçilen tarih aralığında çalışma günü yok.', 1;
IF (@HireDate IS NOT NULL AND CAST(@StartDate AS date) < @HireDate)
OR (@TerminationDate IS NOT NULL AND CAST(@EndDate AS date) > @TerminationDate)
THROW 51119, N'İzin tarihleri çalışanın işe giriş ve işten çıkış tarihleri arasında olmalıdır.', 1;
-- Çakışma: reddedilmemiş başka bir talep ya da talebe bağlı olmayan bir istirahat aynı -- Çakışma: reddedilmemiş başka bir talep ya da talebe bağlı olmayan bir istirahat aynı
-- güne düşüyorsa. Aynı günün iki farklı yarısı birlikte alınabilir. -- güne düşüyorsa. Aynı günün iki farklı yarısı birlikte alınabilir.
IF EXISTS ( IF EXISTS (
@ -248,9 +273,10 @@ BEGIN
END END
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
-- Rapor türü = Sağlık Kartı › İstirahatler satırı (tek kayıt) -- Rapor türü = Sağlık Kartı › İstirahatler satırı (tek kayıt). İstirahat onayla oluşur: onay
-- bekleyen rapor talebi sağlık kartında ve puantajda görünmez, izin günlerini düşürmez.
--------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------
IF @TypeCode = N'Sick' AND COALESCE(@Status, N'') <> @StatusRejected IF @TypeCode = N'Sick' AND @Status = @StatusApproved
BEGIN BEGIN
IF @SickLeaveId IS NULL OR NOT EXISTS (SELECT 1 FROM Adm_T_UserSickLeave WHERE Id = @SickLeaveId) IF @SickLeaveId IS NULL OR NOT EXISTS (SELECT 1 FROM Adm_T_UserSickLeave WHERE Id = @SickLeaveId)
BEGIN BEGIN
@ -275,7 +301,7 @@ BEGIN
END END
ELSE IF @SickLeaveId IS NOT NULL ELSE IF @SickLeaveId IS NOT NULL
BEGIN BEGIN
-- Reddedilen ya da türü rapordan başka bir türe çevrilen talebin istirahati kalkar. -- Reddedilen, onayı beklemeye dönen ya da türü rapordan başka bir türe çevrilen talebin istirahati kalkar.
UPDATE Adm_T_UserSickLeave UPDATE Adm_T_UserSickLeave
SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId
WHERE Id = @SickLeaveId AND IsDeleted = 0; WHERE Id = @SickLeaveId AND IsDeleted = 0;
@ -323,5 +349,15 @@ BEGIN
UPDATE Hr_T_LeaveRequest SET LastNotifiedStatus = @Status WHERE Id = @RequestId; UPDATE Hr_T_LeaveRequest SET LastNotifiedStatus = @Status WHERE Id = @RequestId;
END END
---------------------------------------------------------------------------------------------
-- Rapor, çalışanın diğer izinlerinin gün sayısını değiştirir. Puantaj: talebin günleri yeniden
-- hesaplanır (onaylı izin İzinli, rapor Raporlu gün olur); tarihi değişen talebin artık
-- karşılıksız kalan eski günlerini hesap kendisi aralığa katar. İleri tarih yazılmaz.
---------------------------------------------------------------------------------------------
IF @TypeCode = N'Sick' OR @SickLeaveId IS NOT NULL
EXEC dbo.Hr_S_LeaveDaysRefresh @TenantId, @EmployeeId;
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, @EmployeeId, @StartDate, @EndDate, @ActorId;
END END
GO GO

View file

@ -8,19 +8,28 @@ BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
-- Persona ekranları satırı DefaultFilter ile süzer; kayıt uçları satırı yalnızca Id ile -- Persona ekranları satırı DefaultFilter ile süzer; kayıt uçları satırı yalnızca Id ile
-- güncellediği için sahiplik ve aşama kuralı yazma tarafında burada uygulanır. -- güncellediği için sahiplik ve aşama kuralı yazma tarafında burada uygulanır. Kayıttan önce
IF @RequestId IS NULL OR @Actor = N'Hr' -- çalıştığı için talebin eski tarihleri de burada kapalı puantaj dönemine karşı denetlenir.
IF @RequestId IS NULL
RETURN; RETURN;
DECLARE @EmployeeId uniqueidentifier, @Status nvarchar(50), @ManagerIds nvarchar(1024); DECLARE @EmployeeId uniqueidentifier, @Status nvarchar(50), @ManagerIds nvarchar(1024),
@TenantId uniqueidentifier, @StartDate date, @EndDate date;
SELECT @EmployeeId = EmployeeId, @Status = ApprovalStatus, @ManagerIds = ManagerIds SELECT @EmployeeId = EmployeeId, @Status = ApprovalStatus, @ManagerIds = ManagerIds,
@TenantId = TenantId, @StartDate = CAST(StartDate AS date), @EndDate = CAST(EndDate AS date)
FROM Hr_T_LeaveRequest FROM Hr_T_LeaveRequest
WHERE Id = @RequestId AND IsDeleted = 0; WHERE Id = @RequestId AND IsDeleted = 0;
IF @EmployeeId IS NULL IF @EmployeeId IS NULL
RETURN; RETURN;
IF dbo.Hr_F_TimesheetPeriodClosed(@TenantId, @StartDate, @EndDate) = 1
THROW 51118, N'İzin tarihleri kapalı bir puantaj dönemine düşüyor. Önce İnsan Kaynakları dönemi açmalıdır.', 1;
IF @Actor = N'Hr'
RETURN;
IF @Actor = N'Employee' IF @Actor = N'Employee'
BEGIN BEGIN
IF @EmployeeId <> @ActorId IF @EmployeeId <> @ActorId

View file

@ -22,15 +22,22 @@ BEGIN
IF @UserId IS NULL IF @UserId IS NULL
RETURN; RETURN;
DECLARE @RequestId uniqueidentifier = -- Eşlenen talep istirahatin önceki tarihlerini taşır; kapalı aya düşen eski ya da yeni gün varsa
(SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE SickLeaveId = @SickLeaveId ORDER BY IsDeleted, CreationTime); -- kayıt geri alınır (puantaj ve bordro kapanmış aydır).
DECLARE @RequestId uniqueidentifier, @OldStart date, @OldEnd date;
SELECT TOP 1 @RequestId = Id, @OldStart = CAST(StartDate AS date), @OldEnd = CAST(EndDate AS date)
FROM Hr_T_LeaveRequest WHERE SickLeaveId = @SickLeaveId ORDER BY IsDeleted, CreationTime;
IF dbo.Hr_F_TimesheetPeriodClosed(@TenantId, @StartDate, @EndDate) = 1
OR dbo.Hr_F_TimesheetPeriodClosed(@TenantId, @OldStart, @OldEnd) = 1
THROW 51120, N'Rapor kapalı bir puantaj dönemine düşüyor. Önce İnsan Kaynakları dönemi açmalıdır.', 1;
IF @IsDeleted = 1 IF @IsDeleted = 1
BEGIN BEGIN
UPDATE Hr_T_LeaveRequest UPDATE Hr_T_LeaveRequest
SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId
WHERE SickLeaveId = @SickLeaveId AND IsDeleted = 0; WHERE SickLeaveId = @SickLeaveId AND IsDeleted = 0;
RETURN; GOTO Recalc;
END END
DECLARE @Days decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, @StartDate, @EndDate); DECLARE @Days decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, @StartDate, @EndDate);
@ -42,7 +49,7 @@ BEGIN
IsDeleted = 0, DeletionTime = NULL, DeleterId = NULL, IsDeleted = 0, DeletionTime = NULL, DeleterId = NULL,
LastModificationTime = GETUTCDATE(), LastModifierId = @ActorId LastModificationTime = GETUTCDATE(), LastModifierId = @ActorId
WHERE Id = @RequestId; WHERE Id = @RequestId;
RETURN; GOTO Recalc;
END END
-- Kiracıda rapor türü tanımlı değilse eşlenecek talep yoktur. -- Kiracıda rapor türü tanımlı değilse eşlenecek talep yoktur.
@ -52,7 +59,7 @@ BEGIN
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL))); AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)));
IF @LeaveTypeId IS NULL IF @LeaveTypeId IS NULL
RETURN; GOTO Recalc;
DECLARE @ActorName nvarchar(256) = (SELECT UserName FROM AbpUsers WHERE Id = @ActorId); DECLARE @ActorName nvarchar(256) = (SELECT UserName FROM AbpUsers WHERE Id = @ActorId);
DECLARE @Year nvarchar(4) = CAST(YEAR(GETUTCDATE()) AS nvarchar(4)); DECLARE @Year nvarchar(4) = CAST(YEAR(GETUTCDATE()) AS nvarchar(4));
@ -73,5 +80,14 @@ BEGIN
N'Onaylandı', @ActorName, GETUTCDATE(), N'Onaylandı', 1, GETUTCDATE(), @ActorId, 0 N'Onaylandı', @ActorName, GETUTCDATE(), N'Onaylandı', 1, GETUTCDATE(), @ActorId, 0
FROM AbpUsers u FROM AbpUsers u
WHERE u.Id = @UserId; WHERE u.Id = @UserId;
Recalc:
-- Rapora denk gelen izin günleri bakiyeye döner; puantajda raporlu günler (ve tarihi değiştiyse
-- eski günler) yeniden hesaplanır.
EXEC dbo.Hr_S_LeaveDaysRefresh @TenantId, @UserId;
IF @OldStart IS NOT NULL AND @OldStart < @StartDate SET @StartDate = @OldStart;
IF @OldEnd IS NOT NULL AND @OldEnd > @EndDate SET @EndDate = @OldEnd;
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, @UserId, @StartDate, @EndDate, @ActorId;
END END
GO GO

View file

@ -0,0 +1,426 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_TimesheetCalculate]
@TenantId uniqueidentifier,
@EmployeeId uniqueidentifier = NULL,
@From date,
@To date,
@ActorId uniqueidentifier = NULL
AS
BEGIN
SET NOCOUNT ON;
-- Günlük puantajı hareketlerden, izin/rapor/eğitim kayıtlarından ve Çalışma Takvimi'nden kurar.
-- @EmployeeId boşsa kiracının bütün çalışanları. Kapalı dönemin günleri yazılmaz (yalnız haftalık
-- birikime girer); elle düzeltilmiş gün (IsManual) girdilerini korur, yalnız süreleri yeniden hesaplanır.
-- İzin/rapor kaydını yazan prosedürler de bunu çağırdığı için hata fırlatmaz.
-- Devam takibi çalışana göre iki türlüdür: PDKS Kart No'su olan ve okutması gelmeye başlamış çalışanda
-- okutmasız iş günü devamsızdır; diğer (elle takip edilen) çalışanda kayıtsız iş günü vardiya saatleriyle "geldi" sayılır
-- (IsAssumed), İK yalnız gelinmeyen günü işaretler.
IF @From IS NULL OR @To IS NULL OR @To < @From
RETURN;
DECLARE @Today date = CAST(GETDATE() AS date);
-- Tek çalışanlık hesapta, kaynağı artık olmayan izin/rapor/eğitim günü (talebin tarihi değişti,
-- rapor ya da katılım silindi) aralığa katılır; böylece eski günler aynı işlemde düzelir.
IF @EmployeeId IS NOT NULL
BEGIN
DECLARE @OrphanFrom date, @OrphanTo date;
SELECT @OrphanFrom = MIN(t.WorkDate), @OrphanTo = MAX(t.WorkDate)
FROM Hr_T_Timesheet t
WHERE t.EmployeeId = @EmployeeId AND t.IsDeleted = 0 AND t.IsManual = 0
AND t.DayType IN (N'Leave', N'Sick', N'Training')
AND (t.WorkDate < @From OR t.WorkDate > @To)
AND NOT EXISTS (SELECT 1 FROM Adm_T_UserSickLeave s
WHERE s.UserId = t.EmployeeId AND s.IsDeleted = 0
AND t.WorkDate BETWEEN CAST(s.StartDate AS date) AND CAST(s.EndDate AS date))
AND NOT EXISTS (SELECT 1 FROM Hr_T_LeaveRequest q
WHERE q.EmployeeId = t.EmployeeId AND q.IsDeleted = 0 AND q.ApprovalStatus = N'Onaylandı'
AND t.WorkDate BETWEEN CAST(q.StartDate AS date) AND CAST(q.EndDate AS date))
AND NOT EXISTS (SELECT 1 FROM Hr_T_TrainingParticipant p
INNER JOIN Hr_T_Training g ON g.Id = p.TrainingId AND g.IsDeleted = 0
WHERE p.UserId = t.EmployeeId AND p.IsDeleted = 0 AND p.AttendanceStatus = N'Attended'
AND t.WorkDate BETWEEN g.StartDate AND g.EndDate);
IF @OrphanFrom < @From SET @From = @OrphanFrom;
IF @OrphanTo > @To SET @To = @OrphanTo;
END
-- Fazla mesai haftalık birikimle hesaplandığı için aralık tam haftalara (Pzt–Paz) genişler.
-- 1900-01-01 Pazartesidir; gün sırası DATEFIRST ayarından bağımsızdır.
SET @From = DATEADD(day, -(DATEDIFF(day, '19000101', @From) % 7), @From);
SET @To = DATEADD(day, 6 - (DATEDIFF(day, '19000101', @To) % 7), @To);
DECLARE @Last date = CASE WHEN @To > @Today THEN @Today ELSE @To END;
IF @Last < @From
RETURN;
DECLARE @WeeklyLimit int = CAST(60 * COALESCE(
TRY_CONVERT(decimal(9, 2), REPLACE(dbo.Hr_F_HrSetting(@TenantId, N'App.HrSettings.Attendance.WeeklyLimitHours'), N',', N'.')), 45) AS int);
-- Hafta tatili İzin Yönetimi'nin çalışma günü ayarlarıdır (tek kaynak); tanım yoksa Pzt–Cum.
DECLARE @Work TABLE (DayIndex int PRIMARY KEY, IsWork bit);
INSERT INTO @Work (DayIndex, IsWork)
SELECT d.DayIndex,
CASE
WHEN s.Value IS NULL THEN CASE WHEN d.DayIndex < 5 THEN 1 ELSE 0 END
WHEN LOWER(s.Value) = N'true' THEN 1
ELSE 0
END
FROM (VALUES
(0, N'App.HrSettings.Leave.WorkMonday'),
(1, N'App.HrSettings.Leave.WorkTuesday'),
(2, N'App.HrSettings.Leave.WorkWednesday'),
(3, N'App.HrSettings.Leave.WorkThursday'),
(4, N'App.HrSettings.Leave.WorkFriday'),
(5, N'App.HrSettings.Leave.WorkSaturday'),
(6, N'App.HrSettings.Leave.WorkSunday')) d (DayIndex, SettingName)
CROSS APPLY (SELECT dbo.Hr_F_HrSetting(@TenantId, d.SettingName) AS Value) s;
---------------------------------------------------------------------------------------------
-- Çalışanlar: aralıkta istihdam edilen aktif kullanıcılar + hareketi ya da puantajı olanlar
---------------------------------------------------------------------------------------------
CREATE TABLE #tcEmp
(
EmployeeId uniqueidentifier PRIMARY KEY, HireDate date NULL, TerminationDate date NULL,
ShiftId uniqueidentifier NULL, StartMin int, EndMin int, BreakMin int, LateTol int, EarlyTol int,
CardSince date NULL
);
-- Kartlı takip: kullanıcı kartında PDKS Kart No varsa ilk PDKS/aktarım okutmasının gününden başlar;
-- öncesi (kart yeni verildiyse) ve elle girilen hareketler elle takibi değiştirmez.
INSERT INTO #tcEmp (EmployeeId, HireDate, TerminationDate, ShiftId, StartMin, EndMin, BreakMin, LateTol, EarlyTol, CardSince)
SELECT u.Id, CAST(u.HireDate AS date), CAST(u.TerminationDate AS date),
s.ShiftId, s.StartMin, s.EndMin, s.BreakMin, s.LateTol, s.EarlyTol,
CASE WHEN NULLIF(LTRIM(RTRIM(u.PdksCardNo)), N'') IS NOT NULL THEN
(SELECT MIN(l.WorkDate) FROM Hr_T_AttendanceLog l
WHERE l.EmployeeId = u.Id AND l.IsDeleted = 0 AND l.ProcessError IS NULL AND l.Source <> N'Manual')
END
FROM AbpUsers u
INNER JOIN Hr_V_AttendanceShift s ON s.EmployeeId = u.Id
WHERE u.IsDeleted = 0
AND (u.TenantId = @TenantId OR (u.TenantId IS NULL AND @TenantId IS NULL))
AND (@EmployeeId IS NULL OR u.Id = @EmployeeId)
AND (
(u.IsActive = 1 AND u.HireDate IS NOT NULL AND CAST(u.HireDate AS date) <= @Last
AND (u.TerminationDate IS NULL OR CAST(u.TerminationDate AS date) >= @From))
OR EXISTS (SELECT 1 FROM Hr_T_AttendanceLog l
WHERE l.EmployeeId = u.Id AND l.IsDeleted = 0 AND l.WorkDate BETWEEN @From AND @Last)
OR EXISTS (SELECT 1 FROM Hr_T_Timesheet x
WHERE x.EmployeeId = u.Id AND x.IsDeleted = 0 AND x.WorkDate BETWEEN @From AND @Last)
);
IF NOT EXISTS (SELECT 1 FROM #tcEmp)
RETURN;
---------------------------------------------------------------------------------------------
-- Günler: hafta tatili, takvim türü, kapalı dönem
---------------------------------------------------------------------------------------------
CREATE TABLE #tcDay (WorkDate date PRIMARY KEY, IsWorkDay bit, CalendarType nvarchar(16) NULL, IsClosed bit);
WITH d AS (
SELECT @From AS WorkDate
UNION ALL
SELECT DATEADD(day, 1, WorkDate) FROM d WHERE WorkDate < @Last
)
INSERT INTO #tcDay (WorkDate, IsWorkDay, CalendarType, IsClosed)
SELECT d.WorkDate,
COALESCE(w.IsWork, 0),
dbo.Hr_F_WorkCalendarDayType(@TenantId, d.WorkDate),
CASE WHEN EXISTS (
SELECT 1 FROM Hr_T_TimesheetPeriod p
WHERE p.IsDeleted = 0 AND p.Status = N'Closed'
AND (p.TenantId = @TenantId OR (p.TenantId IS NULL AND @TenantId IS NULL))
AND p.PeriodYear = YEAR(d.WorkDate) AND p.PeriodMonth = MONTH(d.WorkDate)) THEN 1 ELSE 0 END
FROM d
LEFT JOIN @Work w ON w.DayIndex = DATEDIFF(day, '19000101', d.WorkDate) % 7
OPTION (MAXRECURSION 0);
---------------------------------------------------------------------------------------------
-- Çalışan × gün satırları
---------------------------------------------------------------------------------------------
CREATE TABLE #tcRow
(
EmployeeId uniqueidentifier NOT NULL, WorkDate date NOT NULL,
ShiftId uniqueidentifier NULL, StartMin int, EndMin int, ShiftBreak int, LateTol int, EarlyTol int,
IsEmployed bit NOT NULL DEFAULT 1, HasCard bit NOT NULL DEFAULT 0, IsAssumed bit NOT NULL DEFAULT 0,
IsWorkDay bit, CalendarType nvarchar(16) NULL, IsClosed bit,
ExistingId uniqueidentifier NULL, IsManual bit NOT NULL DEFAULT 0, HalfDayLeave bit NOT NULL DEFAULT 0,
LeaveTypeId uniqueidentifier NULL, TrainingId uniqueidentifier NULL,
DayType nvarchar(16) NULL, FirstIn datetime2 NULL, LastOut datetime2 NULL, HasEvents bit NOT NULL DEFAULT 0,
ScanBreak int NOT NULL DEFAULT 0, BreakMinutes int NOT NULL DEFAULT 0, NetMinutes int NOT NULL DEFAULT 0,
LateMinutes int NOT NULL DEFAULT 0, EarlyLeaveMinutes int NOT NULL DEFAULT 0, OvertimeMinutes int NOT NULL DEFAULT 0,
IsIncomplete bit NOT NULL DEFAULT 0,
PRIMARY KEY (EmployeeId, WorkDate)
);
INSERT INTO #tcRow (EmployeeId, WorkDate, ShiftId, StartMin, EndMin, ShiftBreak, LateTol, EarlyTol,
IsEmployed, HasCard, IsWorkDay, CalendarType, IsClosed)
SELECT e.EmployeeId, d.WorkDate, e.ShiftId, e.StartMin, e.EndMin, e.BreakMin, e.LateTol, e.EarlyTol,
CASE WHEN e.HireDate IS NOT NULL AND e.HireDate <= d.WorkDate
AND (e.TerminationDate IS NULL OR e.TerminationDate >= d.WorkDate) THEN 1 ELSE 0 END,
CASE WHEN e.CardSince <= d.WorkDate THEN 1 ELSE 0 END, d.IsWorkDay, d.CalendarType, d.IsClosed
FROM #tcEmp e
CROSS JOIN #tcDay d;
UPDATE r
SET ExistingId = t.Id, IsManual = t.IsManual
FROM #tcRow r
CROSS APPLY (
SELECT TOP 1 x.Id, x.IsManual
FROM Hr_T_Timesheet x
WHERE x.EmployeeId = r.EmployeeId AND x.WorkDate = r.WorkDate AND x.IsDeleted = 0
AND (x.TenantId = @TenantId OR (x.TenantId IS NULL AND @TenantId IS NULL))
ORDER BY x.IsManual DESC, x.CreationTime
) t;
-- Kapalı dönemin günü olduğu gibi kalır; elle düzeltilmiş günün girdileri korunur.
UPDATE r
SET DayType = t.DayType, LeaveTypeId = t.LeaveTypeId, TrainingId = t.TrainingId, FirstIn = t.FirstIn, LastOut = t.LastOut, BreakMinutes = t.BreakMinutes,
NetMinutes = CASE WHEN r.IsClosed = 1 THEN t.NetMinutes ELSE 0 END,
LateMinutes = CASE WHEN r.IsClosed = 1 THEN t.LateMinutes ELSE 0 END,
EarlyLeaveMinutes = CASE WHEN r.IsClosed = 1 THEN t.EarlyLeaveMinutes ELSE 0 END,
OvertimeMinutes = CASE WHEN r.IsClosed = 1 THEN CAST(ROUND(t.OvertimeHours * 60, 0) AS int) ELSE 0 END,
IsIncomplete = t.IsIncomplete,
IsAssumed = CASE WHEN r.IsClosed = 1 THEN t.IsAssumed ELSE 0 END
FROM #tcRow r
INNER JOIN Hr_T_Timesheet t ON t.Id = r.ExistingId
WHERE r.IsClosed = 1 OR r.IsManual = 1;
-- Elle devamsız/izinli/raporlu işaretlenen günde saat tutulmaz.
UPDATE #tcRow
SET FirstIn = NULL, LastOut = NULL, BreakMinutes = 0
WHERE IsManual = 1 AND IsClosed = 0 AND DayType IN (N'Absent', N'Leave', N'Sick');
---------------------------------------------------------------------------------------------
-- Hareketler: ilk giriş, son çıkış, okutulan mola. Yönü "Auto" olan okutma sıraya göre
-- giriş/çıkış sayılır (tek sıra giriş, çift sıra çıkış).
---------------------------------------------------------------------------------------------
CREATE TABLE #tcEvent (EmployeeId uniqueidentifier, WorkDate date, EventTime datetime2, Dir nvarchar(8),
NextTime datetime2 NULL, NextDir nvarchar(8) NULL);
WITH ev AS (
SELECT l.EmployeeId, l.WorkDate, l.EventTime, MIN(l.Direction) AS Direction
FROM Hr_T_AttendanceLog l
WHERE l.IsDeleted = 0 AND l.ProcessError IS NULL AND l.WorkDate BETWEEN @From AND @Last
AND (l.TenantId = @TenantId OR (l.TenantId IS NULL AND @TenantId IS NULL))
AND l.EmployeeId IN (SELECT EmployeeId FROM #tcEmp)
GROUP BY l.EmployeeId, l.WorkDate, l.EventTime
), numbered AS (
SELECT ev.*, ROW_NUMBER() OVER (PARTITION BY EmployeeId, WorkDate ORDER BY EventTime) AS Rn
FROM ev
), dir AS (
SELECT EmployeeId, WorkDate, EventTime,
CASE WHEN Direction IN (N'In', N'Out') THEN Direction WHEN Rn % 2 = 1 THEN N'In' ELSE N'Out' END AS Dir
FROM numbered
)
INSERT INTO #tcEvent (EmployeeId, WorkDate, EventTime, Dir, NextTime, NextDir)
SELECT EmployeeId, WorkDate, EventTime, Dir,
LEAD(EventTime) OVER (PARTITION BY EmployeeId, WorkDate ORDER BY EventTime),
LEAD(Dir) OVER (PARTITION BY EmployeeId, WorkDate ORDER BY EventTime)
FROM dir;
UPDATE r
SET HasEvents = 1,
FirstIn = COALESCE(s.FirstIn, s.FirstAny),
LastOut = CASE WHEN s.LastOut > COALESCE(s.FirstIn, s.FirstAny) THEN s.LastOut END
FROM #tcRow r
INNER JOIN (
SELECT EmployeeId, WorkDate,
MIN(CASE WHEN Dir = N'In' THEN EventTime END) AS FirstIn,
MIN(EventTime) AS FirstAny,
MAX(CASE WHEN Dir = N'Out' THEN EventTime END) AS LastOut
FROM #tcEvent
GROUP BY EmployeeId, WorkDate
) s ON s.EmployeeId = r.EmployeeId AND s.WorkDate = r.WorkDate
WHERE r.IsClosed = 0 AND r.IsManual = 0;
-- Okutulan mola: ilk giriş ile son çıkış arasındaki çıkış → giriş aralıkları.
UPDATE r
SET ScanBreak = COALESCE((
SELECT SUM(DATEDIFF(minute, e.EventTime, e.NextTime))
FROM #tcEvent e
WHERE e.EmployeeId = r.EmployeeId AND e.WorkDate = r.WorkDate
AND e.Dir = N'Out' AND e.NextDir = N'In'
AND e.EventTime >= r.FirstIn AND e.NextTime <= r.LastOut), 0)
FROM #tcRow r
WHERE r.IsClosed = 0 AND r.IsManual = 0 AND r.FirstIn IS NOT NULL AND r.LastOut IS NOT NULL;
---------------------------------------------------------------------------------------------
-- Gün tipi (öncelik sırasıyla):
-- Raporlu: takvim günü; SGK istirahati hafta sonunu da kapsar.
-- Ücretsiz izin (IsPaid = 0; doğum izni dahil): takvim günü; hafta tatili ve genel tatil ücreti doğmaz.
-- Resmî tatil, Hafta tatili: ücretli izne denk gelen tatil izinden sayılmaz (4857 md. 56);
-- İzin Yönetimi'nin gün sayısıyla aynı kural.
-- Ücretli izin > okutmalı Çalışma > Eğitim (katılımcı "Katıldı") > Çalışma / Devamsız.
-- Okutması olmayan iş günü: kartlı çalışanda devamsız (bugün henüz değil), kartsız çalışanda
-- (bugün dahil) vardiya saatleriyle çalışılmış sayılır.
---------------------------------------------------------------------------------------------
UPDATE r
SET HalfDayLeave = CASE WHEN lv.IsHalfDay = 1 THEN 1 ELSE 0 END,
LeaveTypeId = lv.LeaveTypeId,
TrainingId = tr.TrainingId,
DayType = CASE
WHEN sk.Id IS NOT NULL THEN N'Sick'
WHEN lv.Id IS NOT NULL AND lv.IsPaid = 0 AND (lv.IsHalfDay = 0 OR r.FirstIn IS NULL) THEN N'Leave'
WHEN r.CalendarType = N'Holiday' THEN N'Holiday'
WHEN r.IsWorkDay = 0 THEN N'WeeklyOff'
WHEN lv.Id IS NOT NULL AND (lv.IsHalfDay = 0 OR r.FirstIn IS NULL) THEN N'Leave'
WHEN r.FirstIn IS NOT NULL THEN N'Work'
WHEN tr.TrainingId IS NOT NULL THEN N'Training'
WHEN r.HasCard = 0 THEN N'Work'
WHEN r.WorkDate < @Today THEN N'Absent'
END
FROM #tcRow r
OUTER APPLY (
SELECT TOP 1 s.Id
FROM Adm_T_UserSickLeave s
WHERE s.UserId = r.EmployeeId AND s.IsDeleted = 0
AND r.WorkDate BETWEEN CAST(s.StartDate AS date) AND CAST(s.EndDate AS date)
) sk
OUTER APPLY (
SELECT TOP 1 q.Id, q.IsHalfDay, q.LeaveTypeId, lt.IsPaid
FROM Hr_T_LeaveRequest q
INNER JOIN Hr_T_LeaveType lt ON lt.Id = q.LeaveTypeId
WHERE q.EmployeeId = r.EmployeeId AND q.IsDeleted = 0 AND q.ApprovalStatus = N'Onaylandı'
AND r.WorkDate BETWEEN CAST(q.StartDate AS date) AND CAST(q.EndDate AS date)
ORDER BY q.IsHalfDay
) lv
OUTER APPLY (
SELECT TOP 1 p.TrainingId
FROM Hr_T_TrainingParticipant p
INNER JOIN Hr_T_Training g ON g.Id = p.TrainingId AND g.IsDeleted = 0
WHERE p.UserId = r.EmployeeId AND p.IsDeleted = 0 AND p.AttendanceStatus = N'Attended'
AND r.WorkDate BETWEEN g.StartDate AND g.EndDate
ORDER BY g.StartDate
) tr
WHERE r.IsClosed = 0 AND r.IsManual = 0;
-- İstihdam dışındaki hareketsiz gün yazılmaz (işe girişten önce, çıkıştan sonra).
UPDATE #tcRow
SET DayType = NULL
WHERE IsClosed = 0 AND IsManual = 0 AND IsEmployed = 0 AND HasEvents = 0;
-- Elle takip edilen çalışanın kayıtsız iş günü ve okutmasız eğitim günü: vardiya saatleri
-- (arifede yarım gün). Eğitim günü haftalık birikime çalışma gibi girer.
UPDATE #tcRow
SET IsAssumed = 1,
FirstIn = DATEADD(minute, StartMin, CAST(WorkDate AS datetime2)),
LastOut = DATEADD(minute, StartMin + CASE WHEN CalendarType = N'HalfDay'
THEN ((EndMin - StartMin + 1440) % 1440) / 2
ELSE (EndMin - StartMin + 1440) % 1440 END,
CAST(WorkDate AS datetime2))
WHERE IsClosed = 0 AND IsManual = 0 AND DayType IN (N'Work', N'Training') AND HasEvents = 0;
---------------------------------------------------------------------------------------------
-- Süreler: mola = MAX(vardiya molası, okutulan mola); net = son çıkış − ilk giriş − mola.
-- Geç kalma / erken çıkış toleransı aşılırsa dakikanın tamamı yazılır. Yarım gün (arife)
-- vardiya süresinin yarısında biter; yarım gün izinli günde geç/erken yazılmaz.
---------------------------------------------------------------------------------------------
UPDATE r
SET BreakMinutes = CASE
WHEN g.Gross <= 0 THEN 0
WHEN r.IsManual = 1 THEN CASE WHEN r.BreakMinutes > g.Gross THEN g.Gross ELSE r.BreakMinutes END
WHEN (CASE WHEN r.ScanBreak > r.ShiftBreak THEN r.ScanBreak ELSE r.ShiftBreak END) > g.Gross THEN g.Gross
ELSE CASE WHEN r.ScanBreak > r.ShiftBreak THEN r.ScanBreak ELSE r.ShiftBreak END
END,
IsIncomplete = CASE WHEN r.FirstIn IS NOT NULL AND r.LastOut IS NULL THEN 1 ELSE 0 END,
LateMinutes = CASE
WHEN r.DayType = N'Work' AND r.HalfDayLeave = 0 AND r.FirstIn IS NOT NULL
AND DATEDIFF(minute, DATEADD(minute, r.StartMin, CAST(r.WorkDate AS datetime2)), r.FirstIn) > r.LateTol
THEN DATEDIFF(minute, DATEADD(minute, r.StartMin, CAST(r.WorkDate AS datetime2)), r.FirstIn)
ELSE 0 END,
EarlyLeaveMinutes = CASE
WHEN r.DayType = N'Work' AND r.HalfDayLeave = 0 AND r.LastOut IS NOT NULL
AND DATEDIFF(minute, r.LastOut, DATEADD(minute, sh.ExpectedEnd, CAST(r.WorkDate AS datetime2))) > r.EarlyTol
THEN DATEDIFF(minute, r.LastOut, DATEADD(minute, sh.ExpectedEnd, CAST(r.WorkDate AS datetime2)))
ELSE 0 END
FROM #tcRow r
CROSS APPLY (
SELECT CASE WHEN r.FirstIn IS NOT NULL AND r.LastOut IS NOT NULL
THEN DATEDIFF(minute, r.FirstIn, r.LastOut) ELSE 0 END AS Gross
) g
CROSS APPLY (
SELECT r.StartMin + CASE WHEN r.CalendarType = N'HalfDay'
THEN ((r.EndMin - r.StartMin + 1440) % 1440) / 2
ELSE (r.EndMin - r.StartMin + 1440) % 1440 END AS ExpectedEnd
) sh
WHERE r.IsClosed = 0 AND r.DayType IS NOT NULL;
UPDATE #tcRow
SET NetMinutes = CASE
WHEN FirstIn IS NOT NULL AND LastOut IS NOT NULL AND DATEDIFF(minute, FirstIn, LastOut) > BreakMinutes
THEN DATEDIFF(minute, FirstIn, LastOut) - BreakMinutes
ELSE 0 END
WHERE IsClosed = 0 AND DayType IS NOT NULL;
-- Negatif çıkmasın: tolerans içindeki erken giriş geç kalma değildir.
UPDATE #tcRow SET LateMinutes = 0 WHERE LateMinutes < 0;
UPDATE #tcRow SET EarlyLeaveMinutes = 0 WHERE EarlyLeaveMinutes < 0;
---------------------------------------------------------------------------------------------
-- Fazla mesai (4857 md. 41): hafta tatili ve resmî tatilde çalışılan sürenin tamamı; diğer
-- günlerde haftanın kümülatif net süresi haftalık sınırı aştığı günden itibaren aşan kısım.
---------------------------------------------------------------------------------------------
WITH w AS (
SELECT r.IsClosed, r.DayType, r.NetMinutes, r.OvertimeMinutes,
SUM(CASE WHEN r.DayType IN (N'WeeklyOff', N'Holiday') THEN 0 ELSE r.NetMinutes END)
OVER (PARTITION BY r.EmployeeId, DATEDIFF(day, '19000101', r.WorkDate) / 7
ORDER BY r.WorkDate ROWS UNBOUNDED PRECEDING) AS Cumulative
FROM #tcRow r
WHERE r.DayType IS NOT NULL
)
UPDATE w
SET OvertimeMinutes = CASE
WHEN DayType IN (N'WeeklyOff', N'Holiday') THEN NetMinutes
ELSE (CASE WHEN Cumulative > @WeeklyLimit THEN Cumulative - @WeeklyLimit ELSE 0 END)
- (CASE WHEN Cumulative - NetMinutes > @WeeklyLimit THEN Cumulative - NetMinutes - @WeeklyLimit ELSE 0 END)
END
WHERE IsClosed = 0;
---------------------------------------------------------------------------------------------
-- Yazma
---------------------------------------------------------------------------------------------
DECLARE @Now datetime2 = GETUTCDATE();
UPDATE t
SET ShiftId = r.ShiftId,
DayType = r.DayType,
LeaveTypeId = r.LeaveTypeId,
TrainingId = r.TrainingId,
FirstIn = r.FirstIn,
LastOut = r.LastOut,
BreakMinutes = r.BreakMinutes,
NetMinutes = r.NetMinutes,
NetHours = CAST(r.NetMinutes / 60.0 AS decimal(6, 2)),
LateMinutes = r.LateMinutes,
EarlyLeaveMinutes = r.EarlyLeaveMinutes,
OvertimeHours = CAST(r.OvertimeMinutes / 60.0 AS decimal(6, 2)),
IsIncomplete = r.IsIncomplete,
IsAssumed = r.IsAssumed,
CalculatedAt = @Now,
LastModificationTime = @Now,
LastModifierId = COALESCE(@ActorId, t.LastModifierId)
FROM Hr_T_Timesheet t
INNER JOIN #tcRow r ON r.ExistingId = t.Id
WHERE r.IsClosed = 0 AND r.DayType IS NOT NULL;
-- Artık karşılığı olmayan otomatik gün (ör. geriye dönük işten çıkış) kalkar.
UPDATE t
SET IsDeleted = 1, DeletionTime = @Now, DeleterId = @ActorId
FROM Hr_T_Timesheet t
INNER JOIN #tcRow r ON r.ExistingId = t.Id
WHERE r.IsClosed = 0 AND r.IsManual = 0 AND r.DayType IS NULL;
INSERT INTO Hr_T_Timesheet
(Id, TenantId, EmployeeId, WorkDate, PeriodYear, PeriodMonth, PeriodKey, ShiftId, DayType, LeaveTypeId, TrainingId,
FirstIn, LastOut, BreakMinutes, NetMinutes, NetHours, LateMinutes, EarlyLeaveMinutes, OvertimeHours,
IsManual, IsIncomplete, IsAssumed, CalculatedAt, CreationTime, CreatorId, IsDeleted)
SELECT NEWID(), @TenantId, r.EmployeeId, r.WorkDate, YEAR(r.WorkDate), MONTH(r.WorkDate),
CONVERT(nvarchar(36), r.EmployeeId) + N'-' + CONVERT(nvarchar(6), YEAR(r.WorkDate) * 100 + MONTH(r.WorkDate)),
r.ShiftId, r.DayType, r.LeaveTypeId, r.TrainingId, r.FirstIn, r.LastOut, r.BreakMinutes, r.NetMinutes,
CAST(r.NetMinutes / 60.0 AS decimal(6, 2)), r.LateMinutes, r.EarlyLeaveMinutes,
CAST(r.OvertimeMinutes / 60.0 AS decimal(6, 2)), 0, r.IsIncomplete, r.IsAssumed, @Now, @Now, @ActorId, 0
FROM #tcRow r
WHERE r.IsClosed = 0 AND r.ExistingId IS NULL AND r.DayType IS NOT NULL;
END
GO

View file

@ -0,0 +1,72 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_TimesheetNightly]
AS
BEGIN
SET NOCOUNT ON;
-- Zamanlanmış iş (Timesheet Nightly, her gece 02:00). Hareketi olmayan günleri (devamsız, hafta
-- tatili, resmî tatil, izinli, raporlu) kurar ve geriye dönük onaylanan izin/rapor, takvim ya da
-- vardiya değişikliğini yansıtır: dünün ayı ve kapanmamışsa bir önceki ay, işlenmemiş ve kartı sonradan
-- tanımlanan hareketler.
-- İş host ve her kiracı için çağrılır, prosedür parametre almaz; bu yüzden veritabanındaki bütün
-- kiracıları işler ve aynı gün işlenmiş kiracıyı (dönemin NightlyAt değeri) atlar.
DECLARE @Today date = CAST(GETDATE() AS date);
DECLARE @Yesterday date = DATEADD(day, -1, @Today);
DECLARE @MonthStart date = DATEFROMPARTS(YEAR(@Yesterday), MONTH(@Yesterday), 1);
DECLARE @PrevStart date = DATEADD(month, -1, @MonthStart);
-- Kart numarası kullanıcı kartına sonradan girilen okutmalar yeniden işlenir.
UPDATE l
SET IsProcessed = 0, ProcessError = NULL
FROM Hr_T_AttendanceLog l
WHERE l.IsDeleted = 0 AND l.ProcessError = N'UnknownCard'
AND EXISTS (SELECT 1 FROM AbpUsers u
WHERE (u.PdksCardNo = l.CardNo OR u.RegistrationNo = l.CardNo) AND u.IsDeleted = 0
AND (u.TenantId = l.TenantId OR (u.TenantId IS NULL AND l.TenantId IS NULL)));
EXEC dbo.Hr_S_AttendanceProcess 0;
DECLARE @Tenants TABLE (TenantId uniqueidentifier NULL);
INSERT INTO @Tenants (TenantId)
SELECT DISTINCT TenantId FROM AbpUsers WHERE IsDeleted = 0 AND HireDate IS NOT NULL;
DECLARE @TenantId uniqueidentifier, @PeriodId uniqueidentifier, @From date;
DECLARE tenant_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT TenantId FROM @Tenants;
OPEN tenant_cursor;
FETCH NEXT FROM tenant_cursor INTO @TenantId;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @PeriodId = (SELECT TOP 1 Id FROM Hr_T_TimesheetPeriod
WHERE IsDeleted = 0 AND PeriodYear = YEAR(@Yesterday) AND PeriodMonth = MONTH(@Yesterday)
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)));
-- Ay dönemi gece işinde kendiliğinden açılır.
IF @PeriodId IS NULL
BEGIN
SET @PeriodId = NEWID();
INSERT INTO Hr_T_TimesheetPeriod (Id, TenantId, PeriodYear, PeriodMonth, [Status], CreationTime, IsDeleted)
VALUES (@PeriodId, @TenantId, YEAR(@Yesterday), MONTH(@Yesterday), N'Open', GETUTCDATE(), 0);
END
IF NOT EXISTS (SELECT 1 FROM Hr_T_TimesheetPeriod WHERE Id = @PeriodId AND NightlyAt >= CAST(@Today AS datetime2))
BEGIN
SET @From = CASE WHEN EXISTS (
SELECT 1 FROM Hr_T_TimesheetPeriod
WHERE IsDeleted = 0 AND [Status] = N'Closed'
AND PeriodYear = YEAR(@PrevStart) AND PeriodMonth = MONTH(@PrevStart)
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)))
THEN @MonthStart ELSE @PrevStart END;
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, NULL, @From, @Yesterday, NULL;
UPDATE Hr_T_TimesheetPeriod
SET NightlyAt = GETDATE(), CalculatedAt = GETUTCDATE()
WHERE Id = @PeriodId;
END
FETCH NEXT FROM tenant_cursor INTO @TenantId;
END
CLOSE tenant_cursor;
DEALLOCATE tenant_cursor;
END
GO

View file

@ -0,0 +1,55 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_TimesheetPeriodAfterSave]
@PeriodId uniqueidentifier,
@ActorId uniqueidentifier
AS
BEGIN
SET NOCOUNT ON;
-- Puantaj Dönemleri kaydı: açık dönemin her kaydı ayı bütün çalışanlar için yeniden hesaplar;
-- kapatma son kez hesaplayıp ayı kilitler. Kapalı ayın hareketleri ve günleri değiştirilemez.
DECLARE @TenantId uniqueidentifier, @Year int, @Month int, @Status nvarchar(16), @ClosedAt datetime2;
SELECT @TenantId = TenantId, @Year = PeriodYear, @Month = PeriodMonth, @Status = [Status], @ClosedAt = ClosedAt
FROM Hr_T_TimesheetPeriod
WHERE Id = @PeriodId AND IsDeleted = 0;
IF @Year IS NULL
RETURN;
IF @Month NOT BETWEEN 1 AND 12 OR @Year NOT BETWEEN 2000 AND 2100
THROW 51220, N'Dönem yılı 2000–2100, ayı 1–12 arasında olmalıdır.', 1;
IF EXISTS (SELECT 1 FROM Hr_T_TimesheetPeriod
WHERE Id <> @PeriodId AND IsDeleted = 0 AND PeriodYear = @Year AND PeriodMonth = @Month
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)))
THROW 51221, N'Bu yıl ve ay için puantaj dönemi zaten var.', 1;
DECLARE @From date = DATEFROMPARTS(@Year, @Month, 1);
DECLARE @To date = EOMONTH(@From);
IF @Status = N'Closed' AND @ClosedAt IS NOT NULL
RETURN;
-- Kapalı aya izin yazılamadığı için ayda onay bekleyen talep varken dönem kapanmaz; aksi hâlde
-- sonradan onaylanan izin puantaja hiç yansımazdı.
IF @Status = N'Closed' AND EXISTS (
SELECT 1 FROM Hr_T_LeaveRequest q
WHERE q.IsDeleted = 0
AND (q.TenantId = @TenantId OR (q.TenantId IS NULL AND @TenantId IS NULL))
AND (q.ApprovalStatus IS NULL OR q.ApprovalStatus IN (N'Onaya Gönderildi', N'Müdür Onayı', N'İK Onayı'))
AND CAST(q.StartDate AS date) <= @To AND CAST(q.EndDate AS date) >= @From)
THROW 51223, N'Bu ayda onay bekleyen izin talebi var. Talepler sonuçlanmadan dönem kapatılamaz.', 1;
-- Kapatma anında da son hesap yapılır; hesap kapalı ayı yazmadığı için önce açık sayılır.
UPDATE Hr_T_TimesheetPeriod SET [Status] = N'Open' WHERE Id = @PeriodId;
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, NULL, @From, @To, @ActorId;
UPDATE Hr_T_TimesheetPeriod
SET [Status] = COALESCE(@Status, N'Open'),
CalculatedAt = GETUTCDATE(),
ClosedAt = CASE WHEN @Status = N'Closed' THEN GETUTCDATE() END,
ClosedById = CASE WHEN @Status = N'Closed' THEN @ActorId END
WHERE Id = @PeriodId;
END
GO

View file

@ -0,0 +1,50 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_TrainingSync]
@TrainingId uniqueidentifier,
@UserId uniqueidentifier = NULL,
@ActorId uniqueidentifier = NULL
AS
BEGIN
SET NOCOUNT ON;
-- Eğitim ya da katılımcı kaydından sonra çalışır (@UserId boşsa eğitimin bütün katılımcıları):
-- "Katıldı" işaretli katılımcının eğitim günleri puantajda Eğitim olur (devamsız yazılmaz), bağlı
-- gelişim aksiyonu tamamlanır. Silinen katılımcı/eğitim ve değişen tarih için eski günleri
-- puantaj hesabı kendisi düzeltir.
DECLARE @TenantId uniqueidentifier, @StartDate date, @EndDate date;
SELECT @TenantId = TenantId, @StartDate = StartDate, @EndDate = EndDate
FROM Hr_T_Training
WHERE Id = @TrainingId;
IF @StartDate IS NULL
RETURN;
DECLARE @Participant uniqueidentifier, @PlanId uniqueidentifier;
DECLARE participant_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT DISTINCT UserId FROM Hr_T_TrainingParticipant
WHERE TrainingId = @TrainingId AND (@UserId IS NULL OR UserId = @UserId);
OPEN participant_cursor;
FETCH NEXT FROM participant_cursor INTO @Participant;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, @Participant, @StartDate, @EndDate, @ActorId;
FETCH NEXT FROM participant_cursor INTO @Participant;
END
CLOSE participant_cursor;
DEALLOCATE participant_cursor;
DECLARE plan_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT Id FROM Hr_T_DevelopmentPlan
WHERE TrainingId = @TrainingId AND IsDeleted = 0 AND (@UserId IS NULL OR EmployeeId = @UserId);
OPEN plan_cursor;
FETCH NEXT FROM plan_cursor INTO @PlanId;
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC dbo.Hr_S_DevelopmentPlanSync @PlanId;
FETCH NEXT FROM plan_cursor INTO @PlanId;
END
CLOSE plan_cursor;
DEALLOCATE plan_cursor;
END
GO

View file

@ -0,0 +1,50 @@
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_WorkCalendarAfterSave]
@CalendarId uniqueidentifier,
@ActorId uniqueidentifier = NULL
AS
BEGIN
SET NOCOUNT ON;
-- Çalışma Takvimi satırı eklenince, değişince ya da silinince tatile denk gelen izin taleplerinin
-- gün sayısı ve puantaj yeniden hesaplanır; aksi hâlde sonradan girilen bayram izinden düşmeye,
-- puantajda çalışma günü görünmeye devam ederdi. Yıllık tekrarlı satırın bu yılki ve gelecek
-- yılki karşılığı işlenir; kapalı puantaj ayı yazılmaz.
DECLARE @TenantId uniqueidentifier, @StartDate date, @EndDate date, @Recurrence nvarchar(256);
SELECT @TenantId = TenantId, @StartDate = CAST(StartDate AS date), @EndDate = CAST(EndDate AS date),
@Recurrence = RecurrenceRule
FROM Hr_T_WorkCalendar
WHERE Id = @CalendarId;
IF @StartDate IS NULL
RETURN;
IF @Recurrence = N'FREQ=YEARLY'
BEGIN
DECLARE @Shift int = YEAR(GETDATE()) - YEAR(@StartDate);
IF @Shift > 0
BEGIN
SET @StartDate = DATEADD(year, @Shift, @StartDate);
SET @EndDate = DATEADD(year, @Shift + 1, @EndDate);
END
ELSE
SET @EndDate = DATEADD(year, 1, @EndDate);
END
UPDATE r
SET Days = CASE WHEN r.IsHalfDay = 1 AND n.Days > 0.5 THEN 0.5 ELSE n.Days END
FROM Hr_T_LeaveRequest r
INNER JOIN Hr_T_LeaveType t ON t.Id = r.LeaveTypeId
CROSS APPLY (
SELECT CASE WHEN t.Code = N'Sick'
THEN dbo.Hr_F_LeaveWorkDays(r.TenantId, CAST(r.StartDate AS date), CAST(r.EndDate AS date))
ELSE dbo.Hr_F_LeaveNetDays(r.TenantId, r.EmployeeId, CAST(r.StartDate AS date), CAST(r.EndDate AS date))
END AS Days
) n
WHERE r.IsDeleted = 0
AND (r.TenantId = @TenantId OR (r.TenantId IS NULL AND @TenantId IS NULL))
AND CAST(r.StartDate AS date) <= @EndDate AND CAST(r.EndDate AS date) >= @StartDate;
EXEC dbo.Hr_S_TimesheetCalculate @TenantId, NULL, @StartDate, @EndDate, @ActorId;
END
GO

View file

@ -0,0 +1,38 @@
IF OBJECT_ID(N'[dbo].[Hr_T_AttendanceLog]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_AttendanceLog]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[EmployeeId] uniqueidentifier NULL,
[CardNo] nvarchar(64) NULL,
[EventTime] datetime2 NOT NULL,
[Direction] nvarchar(8) NOT NULL DEFAULT N'Auto',
[Source] nvarchar(16) NULL,
[DeviceCode] nvarchar(64) NULL,
[Note] nvarchar(512) NULL,
[WorkDate] date NULL,
[IsProcessed] bit NOT NULL DEFAULT 0,
[ProcessError] nvarchar(32) NULL,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_AttendanceLog] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_AttendanceLog_Employee' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_AttendanceLog]'))
CREATE INDEX [IX_Hr_T_AttendanceLog_Employee] ON [dbo].[Hr_T_AttendanceLog] ([EmployeeId], [WorkDate]) INCLUDE ([EventTime], [Direction], [IsDeleted], [ProcessError])
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_AttendanceLog_Pending' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_AttendanceLog]'))
CREATE INDEX [IX_Hr_T_AttendanceLog_Pending] ON [dbo].[Hr_T_AttendanceLog] ([IsProcessed]) WHERE [IsProcessed] = 0
GO

View file

@ -44,10 +44,6 @@ BEGIN
END END
GO GO
IF COL_LENGTH(N'dbo.Hr_T_LeaveRequest', N'RequiresManagerApproval') IS NULL
ALTER TABLE [dbo].[Hr_T_LeaveRequest] ADD [RequiresManagerApproval] int NOT NULL DEFAULT 1
GO
IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveRequest_Dates]', 'C') IS NULL IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveRequest_Dates]', 'C') IS NULL
ALTER TABLE [dbo].[Hr_T_LeaveRequest] ADD CONSTRAINT [CK_Hr_T_LeaveRequest_Dates] CHECK ([EndDate] >= [StartDate]) ALTER TABLE [dbo].[Hr_T_LeaveRequest] ADD CONSTRAINT [CK_Hr_T_LeaveRequest_Dates] CHECK ([EndDate] >= [StartDate])
GO GO

View file

@ -29,11 +29,6 @@ BEGIN
END END
GO GO
-- Bakiye kuralı izin talebi ekranıyla geldi; daha önce kurulmuş tabloya kayıpsız eklenir.
IF COL_LENGTH(N'dbo.Hr_T_LeaveType', N'BalanceExceedAction') IS NULL
ALTER TABLE [dbo].[Hr_T_LeaveType] ADD [BalanceExceedAction] nvarchar(16) NOT NULL DEFAULT 'Block'
GO
IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveType_BalanceExceedAction]', 'C') IS NULL IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveType_BalanceExceedAction]', 'C') IS NULL
ALTER TABLE [dbo].[Hr_T_LeaveType] ADD CONSTRAINT [CK_Hr_T_LeaveType_BalanceExceedAction] CHECK ([BalanceExceedAction] IN ('Block', 'Warn')) ALTER TABLE [dbo].[Hr_T_LeaveType] ADD CONSTRAINT [CK_Hr_T_LeaveType_BalanceExceedAction] CHECK ([BalanceExceedAction] IN ('Block', 'Warn'))
GO GO

View file

@ -10,6 +10,8 @@ BEGIN
[BreakMinutes] int NULL, [BreakMinutes] int NULL,
[WorkingHours] decimal(5,2) NULL, [WorkingHours] decimal(5,2) NULL,
[IsNightShift] bit NOT NULL DEFAULT 0, [IsNightShift] bit NOT NULL DEFAULT 0,
[LateToleranceMinutes] int NULL,
[EarlyLeaveToleranceMinutes] int NULL,
[IsActive] bit NOT NULL DEFAULT 1, [IsActive] bit NOT NULL DEFAULT 1,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(), [CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL, [CreatorId] uniqueidentifier NULL,

View file

@ -0,0 +1,50 @@
IF OBJECT_ID(N'[dbo].[Hr_T_Timesheet]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_Timesheet]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[EmployeeId] uniqueidentifier NOT NULL,
[WorkDate] date NOT NULL,
[PeriodYear] int NOT NULL,
[PeriodMonth] int NOT NULL,
[PeriodKey] nvarchar(48) NOT NULL,
[ShiftId] uniqueidentifier NULL,
[DayType] nvarchar(16) NOT NULL DEFAULT N'Work',
[LeaveTypeId] uniqueidentifier NULL,
[TrainingId] uniqueidentifier NULL,
[FirstIn] datetime2 NULL,
[LastOut] datetime2 NULL,
[BreakMinutes] int NOT NULL DEFAULT 0,
[NetMinutes] int NOT NULL DEFAULT 0,
[NetHours] decimal(6, 2) NOT NULL DEFAULT 0,
[LateMinutes] int NOT NULL DEFAULT 0,
[EarlyLeaveMinutes] int NOT NULL DEFAULT 0,
[OvertimeHours] decimal(6, 2) NOT NULL DEFAULT 0,
[IsManual] bit NOT NULL DEFAULT 0,
[IsIncomplete] bit NOT NULL DEFAULT 0,
[IsAssumed] bit NOT NULL DEFAULT 0,
[Note] nvarchar(512) NULL,
[CalculatedAt] datetime2 NULL,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_Timesheet] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_Timesheet_EmployeeDate' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_Timesheet]'))
CREATE INDEX [IX_Hr_T_Timesheet_EmployeeDate] ON [dbo].[Hr_T_Timesheet] ([EmployeeId], [WorkDate]) INCLUDE ([IsDeleted], [IsManual])
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_Timesheet_Period' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_Timesheet]'))
CREATE INDEX [IX_Hr_T_Timesheet_Period] ON [dbo].[Hr_T_Timesheet] ([TenantId], [PeriodYear], [PeriodMonth]) INCLUDE ([EmployeeId], [DayType], [IsDeleted])
GO

View file

@ -0,0 +1,28 @@
IF OBJECT_ID(N'[dbo].[Hr_T_TimesheetPeriod]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Hr_T_TimesheetPeriod]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[TenantId] uniqueidentifier NULL,
[PeriodYear] int NOT NULL,
[PeriodMonth] int NOT NULL,
[Status] nvarchar(16) NOT NULL DEFAULT N'Open',
[CalculatedAt] datetime2 NULL,
[ClosedAt] datetime2 NULL,
[ClosedById] uniqueidentifier NULL,
[NightlyAt] datetime2 NULL,
[Note] nvarchar(512) NULL,
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
CONSTRAINT [PK_Hr_T_TimesheetPeriod] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -0,0 +1,32 @@
CREATE OR ALTER VIEW [dbo].[Hr_V_AttendanceShift]
AS
-- Çalışanın puantajda kullanılan vardiyası (dakika cinsinden). Kullanıcı kartında vardiya yoksa ya da
-- vardiyanın alanı boşsa Ayarlar › İnsan Kaynakları › Puantaj'daki varsayılan geçerlidir.
-- DayOffset: hareketin hangi iş gününe yazılacağı. Vardiya bitişi ile bir sonraki başlangıç arasındaki
-- boşluğun ortası gün sınırıdır; gece vardiyasındaki 23:50 okutması vardiyanın başladığı ertesi günün
-- hareketidir. İş günü = CAST(DATEADD(minute, -DayOffset, Zaman) AS date).
SELECT x.EmployeeId, x.TenantId, x.ShiftId, x.StartMin, x.EndMin, x.BreakMin, x.LateTol, x.EarlyTol,
x.StartMin - ((x.StartMin - ((x.EndMin + ((x.StartMin - x.EndMin + 1440) % 1440) / 2) % 1440) + 1440) % 1440) AS DayOffset
FROM AbpUsers u
LEFT JOIN Hr_T_Shift s ON s.Id = u.ShiftId AND s.IsDeleted = 0
CROSS APPLY (
SELECT TRY_CONVERT(time, s.StartTime) AS ShiftStart,
TRY_CONVERT(time, s.EndTime) AS ShiftEnd,
TRY_CONVERT(time, dbo.Hr_F_HrSetting(u.TenantId, N'App.HrSettings.Attendance.DefaultShiftStart')) AS DefaultStart,
TRY_CONVERT(time, dbo.Hr_F_HrSetting(u.TenantId, N'App.HrSettings.Attendance.DefaultShiftEnd')) AS DefaultEnd
) t
CROSS APPLY (
SELECT u.Id AS EmployeeId, u.TenantId, s.Id AS ShiftId,
COALESCE(DATEPART(hour, t.ShiftStart) * 60 + DATEPART(minute, t.ShiftStart),
DATEPART(hour, t.DefaultStart) * 60 + DATEPART(minute, t.DefaultStart), 480) AS StartMin,
COALESCE(DATEPART(hour, t.ShiftEnd) * 60 + DATEPART(minute, t.ShiftEnd),
DATEPART(hour, t.DefaultEnd) * 60 + DATEPART(minute, t.DefaultEnd), 1080) AS EndMin,
COALESCE(s.BreakMinutes,
TRY_CONVERT(int, dbo.Hr_F_HrSetting(u.TenantId, N'App.HrSettings.Attendance.DefaultBreakMinutes')), 60) AS BreakMin,
COALESCE(s.LateToleranceMinutes,
TRY_CONVERT(int, dbo.Hr_F_HrSetting(u.TenantId, N'App.HrSettings.Attendance.LateToleranceMinutes')), 10) AS LateTol,
COALESCE(s.EarlyLeaveToleranceMinutes,
TRY_CONVERT(int, dbo.Hr_F_HrSetting(u.TenantId, N'App.HrSettings.Attendance.EarlyLeaveToleranceMinutes')), 10) AS EarlyTol
) x
WHERE u.IsDeleted = 0;
GO

View file

@ -0,0 +1,52 @@
CREATE OR ALTER VIEW [dbo].[Hr_V_TimesheetMonthly]
AS
-- Personel bazlı aylık puantaj: günlük puantajın çalışan × ay toplamı. Id günlük satırların
-- PeriodKey değeridir (alt form ilişkisi). Fazla mesai ücreti çarpanı ve yıllık sınır ayardan gelir;
-- yıllık fazla mesai ocaktan o aya kadarki birikimdir. Ücretsiz izin günü (bordroda eksik gün) izinli
-- günlerin ücretsiz türdeki kısmıdır; eğitim günü çalışılmış sayılır.
WITH m AS (
SELECT t.PeriodKey, t.TenantId, t.EmployeeId, t.PeriodYear, t.PeriodMonth,
SUM(CASE WHEN t.DayType = N'Work' THEN 1 ELSE 0 END) AS WorkDays,
CAST(SUM(t.NetMinutes) / 60.0 AS decimal(9, 2)) AS NetHours,
SUM(t.LateMinutes) AS LateMinutes,
SUM(CASE WHEN t.LateMinutes > 0 THEN 1 ELSE 0 END) AS LateDays,
SUM(t.EarlyLeaveMinutes) AS EarlyLeaveMinutes,
SUM(CASE WHEN t.EarlyLeaveMinutes > 0 THEN 1 ELSE 0 END) AS EarlyLeaveDays,
CAST(SUM(t.OvertimeHours) AS decimal(9, 2)) AS OvertimeHours,
SUM(CASE WHEN t.DayType = N'WeeklyOff' THEN 1 ELSE 0 END) AS WeeklyOffDays,
SUM(CASE WHEN t.DayType = N'Holiday' THEN 1 ELSE 0 END) AS HolidayDays,
SUM(CASE WHEN t.DayType = N'Leave' THEN 1 ELSE 0 END) AS LeaveDays,
SUM(CASE WHEN t.DayType = N'Leave' AND lt.IsPaid = 0 THEN 1 ELSE 0 END) AS UnpaidLeaveDays,
SUM(CASE WHEN t.DayType = N'Training' THEN 1 ELSE 0 END) AS TrainingDays,
SUM(CASE WHEN t.DayType = N'Sick' THEN 1 ELSE 0 END) AS SickDays,
SUM(CASE WHEN t.DayType = N'Absent' THEN 1 ELSE 0 END) AS AbsentDays,
SUM(CASE WHEN t.IsIncomplete = 1 THEN 1 ELSE 0 END) AS IncompleteDays,
SUM(CASE WHEN t.IsAssumed = 1 THEN 1 ELSE 0 END) AS AssumedDays
FROM Hr_T_Timesheet t
LEFT JOIN Hr_T_LeaveType lt ON lt.Id = t.LeaveTypeId
WHERE t.IsDeleted = 0
GROUP BY t.PeriodKey, t.TenantId, t.EmployeeId, t.PeriodYear, t.PeriodMonth
)
SELECT m.PeriodKey AS Id, m.TenantId, m.EmployeeId, u.DepartmentId, u.JobPositionId,
m.PeriodYear, m.PeriodMonth, COALESCE(p.[Status], N'Open') AS PeriodStatus,
m.WorkDays, m.NetHours, m.LateMinutes, m.LateDays, m.EarlyLeaveMinutes, m.EarlyLeaveDays,
m.OvertimeHours,
CAST(m.OvertimeHours * s.Rate AS decimal(9, 2)) AS OvertimePaidHours,
m.WeeklyOffDays, m.HolidayDays, m.LeaveDays, m.UnpaidLeaveDays, m.TrainingDays, m.SickDays, m.AbsentDays, m.IncompleteDays, m.AssumedDays,
CAST(SUM(m.OvertimeHours) OVER (PARTITION BY m.TenantId, m.EmployeeId, m.PeriodYear ORDER BY m.PeriodMonth
ROWS UNBOUNDED PRECEDING) AS decimal(9, 2)) AS YearOvertimeHours,
s.AnnualLimit AS AnnualOvertimeLimit,
CASE WHEN SUM(m.OvertimeHours) OVER (PARTITION BY m.TenantId, m.EmployeeId, m.PeriodYear ORDER BY m.PeriodMonth
ROWS UNBOUNDED PRECEDING) > s.AnnualLimit THEN 1 ELSE 0 END AS IsOverAnnualLimit
FROM m
INNER JOIN AbpUsers u ON u.Id = m.EmployeeId
OUTER APPLY (
SELECT TOP 1 x.[Status] FROM Hr_T_TimesheetPeriod x
WHERE x.IsDeleted = 0 AND x.PeriodYear = m.PeriodYear AND x.PeriodMonth = m.PeriodMonth
AND (x.TenantId = m.TenantId OR (x.TenantId IS NULL AND m.TenantId IS NULL))
) p
CROSS APPLY (
SELECT COALESCE(TRY_CONVERT(decimal(9, 2), REPLACE(dbo.Hr_F_HrSetting(m.TenantId, N'App.HrSettings.Attendance.OvertimeRate'), N',', N'.')), 1.5) AS Rate,
COALESCE(TRY_CONVERT(decimal(9, 2), REPLACE(dbo.Hr_F_HrSetting(m.TenantId, N'App.HrSettings.Attendance.AnnualOvertimeLimitHours'), N',', N'.')), 270) AS AnnualLimit
) s;
GO

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.BenefitType", "MenuCode": "App.Hr.BenefitType",
"MenuOrder": 11, "MenuOrder": 10,
"MenuUrl": "/admin/list/App.Hr.BenefitType", "MenuUrl": "/admin/list/App.Hr.BenefitType",
"MenuIcon": "FcDonate" "MenuIcon": "FcDonate"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.CandidateSource", "MenuCode": "App.Hr.CandidateSource",
"MenuOrder": 13, "MenuOrder": 6,
"MenuUrl": "/admin/list/App.Hr.CandidateSource", "MenuUrl": "/admin/list/App.Hr.CandidateSource",
"MenuIcon": "FcFeedback" "MenuIcon": "FcFeedback"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.Certificate", "MenuCode": "App.Hr.Certificate",
"MenuOrder": 5, "MenuOrder": 4,
"MenuUrl": "/admin/list/App.Hr.Certificate", "MenuUrl": "/admin/list/App.Hr.Certificate",
"MenuIcon": "FcDiploma2" "MenuIcon": "FcDiploma2"
}, },

View file

@ -11,7 +11,7 @@
"MenuParentCode": "App.Hr", "MenuParentCode": "App.Hr",
"MenuParentIcon": "FcConferenceCall", "MenuParentIcon": "FcConferenceCall",
"MenuCode": "App.Hr.DisciplinaryCase", "MenuCode": "App.Hr.DisciplinaryCase",
"MenuOrder": 11, "MenuOrder": 10,
"MenuUrl": "/admin/list/App.Hr.DisciplinaryCase", "MenuUrl": "/admin/list/App.Hr.DisciplinaryCase",
"MenuIcon": "FcHighPriority" "MenuIcon": "FcHighPriority"
}, },
@ -508,7 +508,7 @@
"TabType": "List", "TabType": "List",
"TabTitle": "App.Hr.DisciplinaryDefense", "TabTitle": "App.Hr.DisciplinaryDefense",
"Code": "App.Hr.DisciplinaryDefense", "Code": "App.Hr.DisciplinaryDefense",
"IsRefresh": true, "IsRefresh": false,
"Relation": [ "Relation": [
{ {
"ParentFieldName": "Id", "ParentFieldName": "Id",
@ -521,7 +521,7 @@
"TabType": "List", "TabType": "List",
"TabTitle": "App.Hr.DisciplinaryDecision", "TabTitle": "App.Hr.DisciplinaryDecision",
"Code": "App.Hr.DisciplinaryDecision", "Code": "App.Hr.DisciplinaryDecision",
"IsRefresh": true, "IsRefresh": false,
"Relation": [ "Relation": [
{ {
"ParentFieldName": "Id", "ParentFieldName": "Id",
@ -534,7 +534,7 @@
"TabType": "List", "TabType": "List",
"TabTitle": "App.Hr.DisciplinaryFile", "TabTitle": "App.Hr.DisciplinaryFile",
"Code": "App.Hr.DisciplinaryFile", "Code": "App.Hr.DisciplinaryFile",
"IsRefresh": true, "IsRefresh": false,
"Relation": [ "Relation": [
{ {
"ParentFieldName": "Id", "ParentFieldName": "Id",

View file

@ -1767,7 +1767,7 @@
"CaptionName": "App.Listform.ListformField.DecisionText", "CaptionName": "App.Listform.ListformField.DecisionText",
"PlaceHolder": null, "PlaceHolder": null,
"ReadOnly": false, "ReadOnly": false,
"Visible": true, "Visible": false,
"IsActive": true, "IsActive": true,
"Width": 0, "Width": 0,
"ListOrderNo": 9, "ListOrderNo": 9,
@ -1860,9 +1860,9 @@
"Format": null, "Format": null,
"EditOrderNo": 7, "EditOrderNo": 7,
"EditGroupOrderNo": 1, "EditGroupOrderNo": 1,
"EditorType2": "dxTextArea", "EditorType2": "dxHtmlEditor",
"ColSpan": 2, "ColSpan": 2,
"EditorOptions": "{\"autoResizeEnabled\":false,\"minHeight\":120}", "EditorOptions": "{\"toolbar\":{\"multiline\":true,\"items\":[{\"name\":\"undo\"},{\"name\":\"redo\"},{\"name\":\"separator\"},{\"name\":\"header\",\"acceptedValues\":[false,1,2,3,4,5,6],\"options\":{\"inputAttr\":{\"aria-label\":\"Header\"}}},{\"name\":\"size\",\"acceptedValues\":[\"8pt\",\"10pt\",\"12pt\",\"14pt\",\"18pt\",\"24pt\",\"36pt\"],\"options\":{\"inputAttr\":{\"aria-label\":\"Font size\"}}},{\"name\":\"font\",\"acceptedValues\":[\"Arial\",\"Courier New\",\"Georgia\",\"Impact\",\"Lucida Console\",\"Segoe UI\",\"Tahoma\",\"Times New Roman\",\"Verdana\"],\"options\":{\"inputAttr\":{\"aria-label\":\"Font family\"}}},{\"name\":\"separator\"},{\"name\":\"bold\"},{\"name\":\"italic\"},{\"name\":\"underline\"},{\"name\":\"strike\"},{\"name\":\"superscript\"},{\"name\":\"subscript\"},{\"name\":\"separator\"},{\"name\":\"color\"},{\"name\":\"background\"},{\"name\":\"separator\"},{\"name\":\"alignLeft\"},{\"name\":\"alignCenter\"},{\"name\":\"alignRight\"},{\"name\":\"alignJustify\"},{\"name\":\"separator\"},{\"name\":\"orderedList\"},{\"name\":\"bulletList\"},{\"name\":\"decreaseIndent\"},{\"name\":\"increaseIndent\"},{\"name\":\"separator\"},{\"name\":\"blockquote\"},{\"name\":\"codeBlock\"},{\"name\":\"link\"},{\"name\":\"image\"},{\"name\":\"separator\"},{\"name\":\"insertTable\"},{\"name\":\"insertHeaderRow\"},{\"name\":\"insertRowAbove\"},{\"name\":\"insertRowBelow\"},{\"name\":\"deleteRow\"},{\"name\":\"insertColumnLeft\"},{\"name\":\"insertColumnRight\"},{\"name\":\"deleteColumn\"},{\"name\":\"cellProperties\"},{\"name\":\"tableProperties\"},{\"name\":\"deleteTable\"},{\"name\":\"separator\"},{\"name\":\"clear\"}]},\"imageUpload\":{\"tabs\":[\"file\",\"url\"],\"fileUploadMode\":\"base64\"},\"mediaResizing\":{\"enabled\":true},\"tableResizing\":{\"enabled\":true},\"tableContextMenu\":{\"enabled\":true},\"encodeHtml\":true,\"elementAttr\":{\"style\":\"min-height:250px\"}}",
"GridBoxOptions": null, "GridBoxOptions": null,
"TagBoxOptions": null, "TagBoxOptions": null,
"ImageUploadOptions": null, "ImageUploadOptions": null,

View file

@ -1508,7 +1508,7 @@
"CaptionName": "App.Listform.ListformField.DefenseText", "CaptionName": "App.Listform.ListformField.DefenseText",
"PlaceHolder": null, "PlaceHolder": null,
"ReadOnly": false, "ReadOnly": false,
"Visible": true, "Visible": false,
"IsActive": true, "IsActive": true,
"Width": 0, "Width": 0,
"ListOrderNo": 7, "ListOrderNo": 7,
@ -1601,9 +1601,9 @@
"Format": null, "Format": null,
"EditOrderNo": 5, "EditOrderNo": 5,
"EditGroupOrderNo": 1, "EditGroupOrderNo": 1,
"EditorType2": "dxTextArea", "EditorType2": "dxHtmlEditor",
"ColSpan": 2, "ColSpan": 2,
"EditorOptions": "{\"autoResizeEnabled\":false,\"minHeight\":120}", "EditorOptions": "{\"toolbar\":{\"multiline\":true,\"items\":[{\"name\":\"undo\"},{\"name\":\"redo\"},{\"name\":\"separator\"},{\"name\":\"header\",\"acceptedValues\":[false,1,2,3,4,5,6],\"options\":{\"inputAttr\":{\"aria-label\":\"Header\"}}},{\"name\":\"size\",\"acceptedValues\":[\"8pt\",\"10pt\",\"12pt\",\"14pt\",\"18pt\",\"24pt\",\"36pt\"],\"options\":{\"inputAttr\":{\"aria-label\":\"Font size\"}}},{\"name\":\"font\",\"acceptedValues\":[\"Arial\",\"Courier New\",\"Georgia\",\"Impact\",\"Lucida Console\",\"Segoe UI\",\"Tahoma\",\"Times New Roman\",\"Verdana\"],\"options\":{\"inputAttr\":{\"aria-label\":\"Font family\"}}},{\"name\":\"separator\"},{\"name\":\"bold\"},{\"name\":\"italic\"},{\"name\":\"underline\"},{\"name\":\"strike\"},{\"name\":\"superscript\"},{\"name\":\"subscript\"},{\"name\":\"separator\"},{\"name\":\"color\"},{\"name\":\"background\"},{\"name\":\"separator\"},{\"name\":\"alignLeft\"},{\"name\":\"alignCenter\"},{\"name\":\"alignRight\"},{\"name\":\"alignJustify\"},{\"name\":\"separator\"},{\"name\":\"orderedList\"},{\"name\":\"bulletList\"},{\"name\":\"decreaseIndent\"},{\"name\":\"increaseIndent\"},{\"name\":\"separator\"},{\"name\":\"blockquote\"},{\"name\":\"codeBlock\"},{\"name\":\"link\"},{\"name\":\"image\"},{\"name\":\"separator\"},{\"name\":\"insertTable\"},{\"name\":\"insertHeaderRow\"},{\"name\":\"insertRowAbove\"},{\"name\":\"insertRowBelow\"},{\"name\":\"deleteRow\"},{\"name\":\"insertColumnLeft\"},{\"name\":\"insertColumnRight\"},{\"name\":\"deleteColumn\"},{\"name\":\"cellProperties\"},{\"name\":\"tableProperties\"},{\"name\":\"deleteTable\"},{\"name\":\"separator\"},{\"name\":\"clear\"}]},\"imageUpload\":{\"tabs\":[\"file\",\"url\"],\"fileUploadMode\":\"base64\"},\"mediaResizing\":{\"enabled\":true},\"tableResizing\":{\"enabled\":true},\"tableContextMenu\":{\"enabled\":true},\"encodeHtml\":true,\"elementAttr\":{\"style\":\"min-height:250px\"}}",
"GridBoxOptions": null, "GridBoxOptions": null,
"TagBoxOptions": null, "TagBoxOptions": null,
"ImageUploadOptions": null, "ImageUploadOptions": null,

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.DisciplinaryPenaltyType", "MenuCode": "App.Hr.DisciplinaryPenaltyType",
"MenuOrder": 12, "MenuOrder": 17,
"MenuUrl": "/admin/list/App.Hr.DisciplinaryPenaltyType", "MenuUrl": "/admin/list/App.Hr.DisciplinaryPenaltyType",
"MenuIcon": "FcList" "MenuIcon": "FcList"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.Doctor", "MenuCode": "App.Hr.Doctor",
"MenuOrder": 4, "MenuOrder": 13,
"MenuUrl": "/admin/list/App.Hr.Doctor", "MenuUrl": "/admin/list/App.Hr.Doctor",
"MenuIcon": "FcPortraitMode" "MenuIcon": "FcPortraitMode"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.DocumentType", "MenuCode": "App.Hr.DocumentType",
"MenuOrder": 8, "MenuOrder": 5,
"MenuUrl": "/admin/list/App.Hr.DocumentType", "MenuUrl": "/admin/list/App.Hr.DocumentType",
"MenuIcon": "FcDocument" "MenuIcon": "FcDocument"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Vehicles", "MenuParentCode": "App.Hr.Vehicles",
"MenuParentIcon": "FcAutomotive", "MenuParentIcon": "FcAutomotive",
"MenuCode": "App.Hr.Driver", "MenuCode": "App.Hr.Driver",
"MenuOrder": 4, "MenuOrder": 5,
"MenuUrl": "/admin/list/App.Hr.Driver", "MenuUrl": "/admin/list/App.Hr.Driver",
"MenuIcon": "FcBusinessman" "MenuIcon": "FcBusinessman"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.EvaluationCriterion", "MenuCode": "App.Hr.EvaluationCriterion",
"MenuOrder": 15, "MenuOrder": 8,
"MenuUrl": "/admin/list/App.Hr.EvaluationCriterion", "MenuUrl": "/admin/list/App.Hr.EvaluationCriterion",
"MenuIcon": "FcRating" "MenuIcon": "FcRating"
}, },

View file

@ -11,7 +11,7 @@
"MenuParentCode": "App.Hr", "MenuParentCode": "App.Hr",
"MenuParentIcon": "FcConferenceCall", "MenuParentIcon": "FcConferenceCall",
"MenuCode": "App.Hr.EventLog", "MenuCode": "App.Hr.EventLog",
"MenuOrder": 7, "MenuOrder": 13,
"MenuUrl": "/admin/list/App.Hr.EventLog", "MenuUrl": "/admin/list/App.Hr.EventLog",
"MenuIcon": "FcViewDetails" "MenuIcon": "FcViewDetails"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.ExpenseType", "MenuCode": "App.Hr.ExpenseType",
"MenuOrder": 10, "MenuOrder": 9,
"MenuUrl": "/admin/list/App.Hr.ExpenseType", "MenuUrl": "/admin/list/App.Hr.ExpenseType",
"MenuIcon": "FcMoneyTransfer" "MenuIcon": "FcMoneyTransfer"
}, },

View file

@ -11,7 +11,7 @@
"MenuParentCode": "App.Hr", "MenuParentCode": "App.Hr",
"MenuParentIcon": "FcConferenceCall", "MenuParentIcon": "FcConferenceCall",
"MenuCode": "App.Hr.HealthCard", "MenuCode": "App.Hr.HealthCard",
"MenuOrder": 4, "MenuOrder": 7,
"MenuUrl": "/admin/list/App.Hr.HealthCard", "MenuUrl": "/admin/list/App.Hr.HealthCard",
"MenuIcon": "FcInspection" "MenuIcon": "FcInspection"
}, },

View file

@ -25,8 +25,8 @@
"MenuTr": "İstirahat Raporları", "MenuTr": "İstirahat Raporları",
"TitleEn": "Sick Leaves", "TitleEn": "Sick Leaves",
"TitleTr": "İstirahat Raporları", "TitleTr": "İstirahat Raporları",
"DescEn": "Sick Leaves — the employee's sick leave records.\nWhere: the Sick Leaves tab of Health Cards.\nFields: start and end date, days (end inclusive, automatic), type (Disease, Work accident, Occupational disease, Maternity), institution, clinic, reason.\nSingle record: a report entered here appears in Human Resources › Leave Management as an approved leave request of type Sick, and a sick leave requested by the employee on the Intranet appears in this tab. Deleting the report removes the leave request too. Sick leave does not reduce the annual leave balance.", "DescEn": "Sick Leaves — the employee's sick leave records.\nWhere: the Sick Leaves tab of Health Cards.\nFields: start and end date, days (end inclusive, automatic), type (Disease, Work accident, Occupational disease, Maternity), institution, clinic, reason.\nSingle record: a report entered here appears in Human Resources › Leave Management as an approved leave request of type Sick, and a sick leave requested by the employee on the Intranet appears in this tab. Deleting the report removes the leave request too. Sick leave does not reduce the annual leave balance; annual leave days falling into the report return to the balance. The days are Sick in the timesheet; a report falling into a closed timesheet period cannot be saved.",
"DescTr": "İstirahat Raporları — çalışanın aldığı istirahat (rapor) kayıtları.\nNerede: Sağlık Kartları ekranında kaydın İstirahat Raporları sekmesi.\nAlanlar: başlangıç ve bitiş tarihi, gün (bitiş dahil, otomatik), istirahat türü (Hastalık, İş kazası, Meslek hastalığı, Doğum), kurum, klinik, neden.\nTek kayıt: buradan girilen rapor İnsan Kaynakları › İzin Yönetimi'nde Rapor (Sick) türünde onaylı izin talebi olarak görünür; çalışanın Intranet'ten girdiği rapor talebi de bu sekmeye düşer. Silinen rapor izin talebinden de kalkar. Rapor yıllık izin bakiyesinden düşmez." "DescTr": "İstirahat Raporları — çalışanın aldığı istirahat (rapor) kayıtları.\nNerede: Sağlık Kartları ekranında kaydın İstirahat Raporları sekmesi.\nAlanlar: başlangıç ve bitiş tarihi, gün (bitiş dahil, otomatik), istirahat türü (Hastalık, İş kazası, Meslek hastalığı, Doğum), kurum, klinik, neden.\nTek kayıt: buradan girilen rapor İnsan Kaynakları › İzin Yönetimi'nde Rapor (Sick) türünde onaylı izin talebi olarak görünür; çalışanın Intranet'ten girdiği rapor talebi de bu sekmeye düşer. Silinen rapor izin talebinden de kalkar. Rapor yıllık izin bakiyesinden düşmez; rapora denk gelen yıllık izin günleri bakiyeye döner. Günler puantajda Raporlu yazılır; kapalı puantaj dönemine düşen rapor kaydedilemez."
}, },
"Groups": [ "Groups": [
{ {
@ -104,7 +104,7 @@
"SeedSyncDelete": false, "SeedSyncDelete": false,
"DeleteCommand": "UPDATE \"Adm_T_UserSickLeave\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Adm_T_UserSickLeave\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": null, "DeleteBeforeCommand": null,
"DeleteAfterCommand": "UPDATE Hr_T_LeaveRequest SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId WHERE SickLeaveId IN @Id AND IsDeleted = 0", "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Adm_T_UserSickLeave WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveSickLeaveSync @_id, @DeleterId; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.Hospital", "MenuCode": "App.Hr.Hospital",
"MenuOrder": 6, "MenuOrder": 14,
"MenuUrl": "/admin/list/App.Hr.Hospital", "MenuUrl": "/admin/list/App.Hr.Hospital",
"MenuIcon": "FcOrganization" "MenuIcon": "FcOrganization"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.HospitalDepartment", "MenuCode": "App.Hr.HospitalDepartment",
"MenuOrder": 7, "MenuOrder": 15,
"MenuUrl": "/admin/list/App.Hr.HospitalDepartment", "MenuUrl": "/admin/list/App.Hr.HospitalDepartment",
"MenuIcon": "FcList" "MenuIcon": "FcList"
}, },

View file

@ -32,8 +32,8 @@
"MenuTr": "İzin Talepleri", "MenuTr": "İzin Talepleri",
"TitleEn": "Leave Requests", "TitleEn": "Leave Requests",
"TitleTr": "İzin Talepleri", "TitleTr": "İzin Talepleri",
"DescEn": "Leave Requests — every leave request in the company, with its approval state. Used only by Human Resources.\nWhere: Human Resources › Leave Management › Leave Requests. Employees request leave from the My Leaves widget on Intranet › Dashboard; managers approve from the Team Leaves widget.\nFields:\n• RequestNo → assigned automatically as IZN-YYYY-00001\n• Employee → department and position are copied from the user card\n• Leave type, start/end date and time, half day (morning/afternoon)\n• Days → calculated on save from the working days in Settings › Human Resources and the holidays in Work Calendar (half day = 0.5)\n• Description and supporting document (report etc.; required when the leave type requires a document)\nRules: overlapping requests are rejected; when the annual balance or the yearly limit of the type is exceeded the request is blocked or saved with a warning, as set on the leave type. Gender-specific types are only valid for that gender.\nApproval: Grid Workflow — Department Manager → HR → Approved / Rejected. The manager is the holder of the top position of the employee's department (Job Positions); the HR approver is set on the 'İK Onayı' node. Each step notifies the next approver; the result notifies the employee.\nSick leave: requests of type Sick and Health Card › Sick Leaves are the same record.\nWidgets: awaiting manager, awaiting HR, approved and rejected requests.", "DescEn": "Leave Requests — every leave request in the company, with its approval state. Used only by Human Resources.\nWhere: Human Resources › Leave Management › Leave Requests. Employees request leave from the My Leaves widget on Intranet › Dashboard; managers approve from the Team Leaves widget.\nFields:\n• RequestNo → assigned automatically as IZN-YYYY-00001\n• Employee → department and position are copied from the user card\n• Leave type, start/end date and time, half day (morning/afternoon)\n• Days → calculated on save from the working days in Settings › Human Resources and the holidays in Work Calendar (half day = 0.5); days covered by a sick leave are not counted and return to the balance\n• Description and supporting document (report etc.; required when the leave type requires a document)\nRules: overlapping requests are rejected; when the annual balance or the yearly limit of the type is exceeded the request is blocked or saved with a warning, as set on the leave type. Gender-specific types are only valid for that gender. Dates must be within the employee's hire and termination dates. A request falling into a closed timesheet period cannot be added, changed or deleted.\nApproval: Grid Workflow — Department Manager → HR → Approved / Rejected. The manager is the holder of the top position of the employee's department (Job Positions); the HR approver is set on the 'İK Onayı' node. Each step notifies the next approver; the result notifies the employee.\nSick leave: requests of type Sick and Health Card › Sick Leaves are the same record; a sick leave request appears on the health card once approved.\nWidgets: awaiting manager, awaiting HR, approved and rejected requests.",
"DescTr": "İzin Talepleri — kurumdaki bütün izin talepleri ve onay durumları. Yalnız İnsan Kaynakları kullanır.\nNerede: İnsan Kaynakları › İzin Yönetimi › İzin Talepleri. Çalışan talebini Intranet › Dashboard'daki İzinlerim widget'ından açar; müdür Ekibimin İzinleri widget'ından onaylar.\nAlanlar:\n• RequestNo → IZN-YYYY-00001 biçiminde otomatik verilir\n• Çalışan → departman ve pozisyon kullanıcı kartından kopyalanır\n• İzin türü, başlangıç/bitiş tarih ve saati, yarım gün (sabah/öğleden sonra)\n• Gün → kayıtta Ayarlar › İnsan Kaynakları'ndaki çalışma günleri ve Çalışma Takvimi'ndeki tatillerden hesaplanır (yarım gün = 0,5)\n• Açıklama ve ek belge (rapor vb.; türü belge istiyorsa zorunlu)\nKurallar: aynı tarihlerle çakışan talep reddedilir; yıllık izin bakiyesi ya da türün yıllık sınırı aşılırsa türdeki ayara göre talep engellenir veya uyarıyla kaydedilir. Cinsiyete özel türler yalnız o cinsiyete açıktır.\nOnay: Grid Workflow — Departman Müdürü → İK → Onaylandı / Reddedildi. Müdür, çalışanın departmanındaki en üst pozisyonun (İş Pozisyonları) sahibidir; İK onaycısı 'İK Onayı' düğümünde tanımlıdır. Her adım sıradaki onaycıya, sonuç çalışana bildirim gönderir.\nRapor: Rapor (Sick) türündeki talep ile Sağlık Kartı › İstirahatler aynı kayıttır; hangisinden girilirse diğerinde görünür.\nWidget'lar: müdür onayında, İK onayında, onaylanan ve reddedilen talepler.", "DescTr": "İzin Talepleri — kurumdaki bütün izin talepleri ve onay durumları. Yalnız İnsan Kaynakları kullanır.\nNerede: İnsan Kaynakları › İzin Yönetimi › İzin Talepleri. Çalışan talebini Intranet › Dashboard'daki İzinlerim widget'ından açar; müdür Ekibimin İzinleri widget'ından onaylar.\nAlanlar:\n• RequestNo → IZN-YYYY-00001 biçiminde otomatik verilir\n• Çalışan → departman ve pozisyon kullanıcı kartından kopyalanır\n• İzin türü, başlangıç/bitiş tarih ve saati, yarım gün (sabah/öğleden sonra)\n• Gün → kayıtta Ayarlar › İnsan Kaynakları'ndaki çalışma günleri ve Çalışma Takvimi'ndeki tatillerden hesaplanır (yarım gün = 0,5); rapora denk gelen gün sayılmaz, bakiyeye döner\n• Açıklama ve ek belge (rapor vb.; türü belge istiyorsa zorunlu)\nKurallar: aynı tarihlerle çakışan talep reddedilir; yıllık izin bakiyesi ya da türün yıllık sınırı aşılırsa türdeki ayara göre talep engellenir veya uyarıyla kaydedilir. Cinsiyete özel türler yalnız o cinsiyete açıktır. Tarihler çalışanın işe giriş ve işten çıkış tarihleri arasında olmalıdır. Kapalı puantaj dönemine düşen talep eklenemez, değiştirilemez, silinemez.\nOnay: Grid Workflow — Departman Müdürü → İK → Onaylandı / Reddedildi. Müdür, çalışanın departmanındaki en üst pozisyonun (İş Pozisyonları) sahibidir; İK onaycısı 'İK Onayı' düğümünde tanımlıdır. Her adım sıradaki onaycıya, sonuç çalışana bildirim gönderir.\nRapor: Rapor (Sick) türündeki talep ile Sağlık Kartı › İstirahatler aynı kayıttır; Sağlık Kartı'ndan girilen rapor onaylı talep olur, çalışanın rapor talebi onaylanınca sağlık kartına düşer.\nWidget'lar: müdür onayında, İK onayında, onaylanan ve reddedilen talepler.",
"Texts": [ "Texts": [
{ {
"Key": "App.Hr.Leave.Group.Request", "Key": "App.Hr.Leave.Group.Request",
@ -232,8 +232,8 @@
"SeedSyncUpdate": false, "SeedSyncUpdate": false,
"SeedSyncDelete": false, "SeedSyncDelete": false,
"DeleteCommand": "UPDATE \"Hr_T_LeaveRequest\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Hr_T_LeaveRequest\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": null, "DeleteBeforeCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_LeaveRequest WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveRequestGuard @_id, @DeleterId, N'Hr', N'Delete'; END",
"DeleteAfterCommand": "UPDATE s SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId FROM Adm_T_UserSickLeave s INNER JOIN Hr_T_LeaveRequest r ON r.SickLeaveId = s.Id WHERE r.Id IN @Id AND s.IsDeleted = 0", "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_LeaveRequest WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveRequestAfterSave @_id, @DeleterId, N'Hr'; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",
@ -284,7 +284,7 @@
} }
], ],
"UpdateCommand": null, "UpdateCommand": null,
"UpdateBeforeCommand": null, "UpdateBeforeCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_LeaveRequest WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveRequestGuard @_id, @LastModifierId, N'Hr', N'Update'; END",
"UpdateAfterCommand": "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveRequestAfterSave @_id, @LastModifierId, N'Hr'", "UpdateAfterCommand": "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveRequestAfterSave @_id, @LastModifierId, N'Hr'",
"UpdateFieldsDefaultValueDto": [ "UpdateFieldsDefaultValueDto": [
{ {

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.LeaveType", "MenuCode": "App.Hr.LeaveType",
"MenuOrder": 9, "MenuOrder": 12,
"MenuUrl": "/admin/list/App.Hr.LeaveType", "MenuUrl": "/admin/list/App.Hr.LeaveType",
"MenuIcon": "FcPlanner" "MenuIcon": "FcPlanner"
}, },

View file

@ -162,7 +162,7 @@
"SeedSyncDelete": false, "SeedSyncDelete": false,
"DeleteCommand": "UPDATE \"Hr_T_LeaveRequest\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Hr_T_LeaveRequest\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveRequestGuard @_id, @DeleterId, N'Employee', N'Delete'", "DeleteBeforeCommand": "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveRequestGuard @_id, @DeleterId, N'Employee', N'Delete'",
"DeleteAfterCommand": "UPDATE s SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId FROM Adm_T_UserSickLeave s INNER JOIN Hr_T_LeaveRequest r ON r.SickLeaveId = s.Id WHERE r.Id IN @Id AND s.IsDeleted = 0", "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_LeaveRequest WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_LeaveRequestAfterSave @_id, @DeleterId, N'Employee'; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.RejectionReason", "MenuCode": "App.Hr.RejectionReason",
"MenuOrder": 14, "MenuOrder": 7,
"MenuUrl": "/admin/list/App.Hr.RejectionReason", "MenuUrl": "/admin/list/App.Hr.RejectionReason",
"MenuIcon": "FcCancel" "MenuIcon": "FcCancel"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Definitions", "MenuParentCode": "App.Hr.Definitions",
"MenuParentIcon": "FcFilingCabinet", "MenuParentIcon": "FcFilingCabinet",
"MenuCode": "App.Hr.Shift", "MenuCode": "App.Hr.Shift",
"MenuOrder": 9, "MenuOrder": 11,
"MenuUrl": "/admin/list/App.Hr.Shift", "MenuUrl": "/admin/list/App.Hr.Shift",
"MenuIcon": "FcClock" "MenuIcon": "FcClock"
}, },
@ -68,6 +68,18 @@
"En": "Break (min)", "En": "Break (min)",
"Tr": "Mola (dk)" "Tr": "Mola (dk)"
}, },
{
"FieldName": "LateToleranceMinutes",
"CaptionName": "App.Listform.ListformField.LateToleranceMinutes",
"En": "Late Tolerance (min)",
"Tr": "Geç Kalma Toleransı (dk)"
},
{
"FieldName": "EarlyLeaveToleranceMinutes",
"CaptionName": "App.Listform.ListformField.EarlyLeaveToleranceMinutes",
"En": "Early Leave Tolerance (min)",
"Tr": "Erken Çıkış Toleransı (dk)"
},
{ {
"FieldName": "WorkingHours", "FieldName": "WorkingHours",
"CaptionName": "App.Listform.ListformField.WorkingHours", "CaptionName": "App.Listform.ListformField.WorkingHours",
@ -1365,15 +1377,15 @@
"JoinFieldName2": null, "JoinFieldName2": null,
"BaseTableJoinFieldName2_OrValue": null "BaseTableJoinFieldName2_OrValue": null
}, },
"FieldName": "WorkingHours", "FieldName": "LateToleranceMinutes",
"CaptionName": "App.Listform.ListformField.WorkingHours", "CaptionName": "App.Listform.ListformField.LateToleranceMinutes",
"PlaceHolder": null, "PlaceHolder": null,
"ReadOnly": false, "ReadOnly": false,
"Visible": true, "Visible": true,
"IsActive": true, "IsActive": true,
"Width": 0, "Width": 0,
"ListOrderNo": 6, "ListOrderNo": 6,
"SourceDbType": 7, "SourceDbType": 11,
"CultureName": "en", "CultureName": "en",
"DataType": "number", "DataType": "number",
"SortIndex": 0, "SortIndex": 0,
@ -1464,6 +1476,258 @@
"EditGroupOrderNo": 1, "EditGroupOrderNo": 1,
"EditorType2": "dxNumberBox", "EditorType2": "dxNumberBox",
"ColSpan": 1, "ColSpan": 1,
"EditorOptions": "{\"showSpinButtons\":true,\"min\":0,\"max\":120,\"showClearButton\":true}",
"GridBoxOptions": null,
"TagBoxOptions": null,
"ImageUploadOptions": null,
"EditorScript": null,
"LastModificationTime": null,
"LastModifierId": null,
"CreationTime": "0001-01-01T00:00:00",
"CreatorId": null,
"Id": "00000000-0000-0000-0000-000000000000"
},
{
"EditType": null,
"ListFormCode": "App.Hr.Shift",
"RoleId": null,
"UserId": null,
"ColumnJoinTableDto": {
"JoinType": null,
"TableName": null,
"JoinFieldName": null,
"BaseTableJoinFieldName": null,
"SelectFieldName": null,
"FieldNameAlias": null,
"JoinCondition2": "AND",
"JoinFieldName2": null,
"BaseTableJoinFieldName2_OrValue": null
},
"FieldName": "EarlyLeaveToleranceMinutes",
"CaptionName": "App.Listform.ListformField.EarlyLeaveToleranceMinutes",
"PlaceHolder": null,
"ReadOnly": false,
"Visible": true,
"IsActive": true,
"Width": 0,
"ListOrderNo": 7,
"SourceDbType": 11,
"CultureName": "en",
"DataType": "number",
"SortIndex": 0,
"SortDirection": null,
"AllowSearch": true,
"AllowEditing": true,
"AllowAdding": true,
"ColumnCssClass": null,
"ColumnCssValue": null,
"BandName": null,
"ColumnFilterDto": {
"AllowFiltering": true,
"FilterOperations": null,
"SelectedFilterOperation": null,
"FilterValue": null
},
"ColumnHeaderDto": {
"AllowHeaderFiltering": true,
"AllowSearch": false,
"DataSource": null,
"DataSourceString": ""
},
"ColumnGroupingDto": {
"AllowGrouping": true,
"GroupIndex": null,
"AutoExpandGroup": false
},
"ColumnCustomizationDto": {
"Fixed": false,
"FixedPosition": "left",
"AllowReordering": true
},
"ColumnTotalSummaryDto": {
"SummaryType": null,
"ValueFormat": null,
"ShowInGroupFooter": false,
"AlignByColumn": false,
"DisplayFormat": null,
"ShowInColumn": null
},
"ColumnGroupSummaryDto": {
"SummaryType": null,
"ValueFormat": null,
"ShowInGroupFooter": false,
"AlignByColumn": false,
"DisplayFormat": null,
"ShowInColumn": null
},
"LookupDto": {
"DataSourceType": 0,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"CascadeRelationField": null,
"CascadeFilterOperator": "=",
"CascadeParentFields": null,
"CascadeEmptyFields": null,
"LookupQuery": null
},
"ValidationRuleDto": [],
"ColumnStylingDto": [],
"PermissionDto": {
"Deny": false,
"C": "App.Hr.Shift.Create",
"R": "App.Hr.Shift",
"U": "App.Hr.Shift.Update",
"E": true,
"I": true
},
"CanRead": false,
"CanCreate": false,
"CanUpdate": false,
"CanExport": false,
"DefaultValue": null,
"DefaultValueType": 0,
"PivotSettingsDto": {
"IsPivot": true,
"Expanded": false,
"SortOrder": "asc",
"Area": "filter",
"Format": null,
"SummaryType": null,
"GroupInterval": "",
"WordWrapEnabled": false
},
"Alignment": "right",
"Format": null,
"EditOrderNo": 6,
"EditGroupOrderNo": 1,
"EditorType2": "dxNumberBox",
"ColSpan": 1,
"EditorOptions": "{\"showSpinButtons\":true,\"min\":0,\"max\":120,\"showClearButton\":true}",
"GridBoxOptions": null,
"TagBoxOptions": null,
"ImageUploadOptions": null,
"EditorScript": null,
"LastModificationTime": null,
"LastModifierId": null,
"CreationTime": "0001-01-01T00:00:00",
"CreatorId": null,
"Id": "00000000-0000-0000-0000-000000000000"
},
{
"EditType": null,
"ListFormCode": "App.Hr.Shift",
"RoleId": null,
"UserId": null,
"ColumnJoinTableDto": {
"JoinType": null,
"TableName": null,
"JoinFieldName": null,
"BaseTableJoinFieldName": null,
"SelectFieldName": null,
"FieldNameAlias": null,
"JoinCondition2": "AND",
"JoinFieldName2": null,
"BaseTableJoinFieldName2_OrValue": null
},
"FieldName": "WorkingHours",
"CaptionName": "App.Listform.ListformField.WorkingHours",
"PlaceHolder": null,
"ReadOnly": false,
"Visible": true,
"IsActive": true,
"Width": 0,
"ListOrderNo": 8,
"SourceDbType": 7,
"CultureName": "en",
"DataType": "number",
"SortIndex": 0,
"SortDirection": null,
"AllowSearch": true,
"AllowEditing": true,
"AllowAdding": true,
"ColumnCssClass": null,
"ColumnCssValue": null,
"BandName": null,
"ColumnFilterDto": {
"AllowFiltering": true,
"FilterOperations": null,
"SelectedFilterOperation": null,
"FilterValue": null
},
"ColumnHeaderDto": {
"AllowHeaderFiltering": true,
"AllowSearch": false,
"DataSource": null,
"DataSourceString": ""
},
"ColumnGroupingDto": {
"AllowGrouping": true,
"GroupIndex": null,
"AutoExpandGroup": false
},
"ColumnCustomizationDto": {
"Fixed": false,
"FixedPosition": "left",
"AllowReordering": true
},
"ColumnTotalSummaryDto": {
"SummaryType": null,
"ValueFormat": null,
"ShowInGroupFooter": false,
"AlignByColumn": false,
"DisplayFormat": null,
"ShowInColumn": null
},
"ColumnGroupSummaryDto": {
"SummaryType": null,
"ValueFormat": null,
"ShowInGroupFooter": false,
"AlignByColumn": false,
"DisplayFormat": null,
"ShowInColumn": null
},
"LookupDto": {
"DataSourceType": 0,
"ValueExpr": "Key",
"DisplayExpr": "Name",
"CascadeRelationField": null,
"CascadeFilterOperator": "=",
"CascadeParentFields": null,
"CascadeEmptyFields": null,
"LookupQuery": null
},
"ValidationRuleDto": [],
"ColumnStylingDto": [],
"PermissionDto": {
"Deny": false,
"C": "App.Hr.Shift.Create",
"R": "App.Hr.Shift",
"U": "App.Hr.Shift.Update",
"E": true,
"I": true
},
"CanRead": false,
"CanCreate": false,
"CanUpdate": false,
"CanExport": false,
"DefaultValue": null,
"DefaultValueType": 0,
"PivotSettingsDto": {
"IsPivot": true,
"Expanded": false,
"SortOrder": "asc",
"Area": "filter",
"Format": null,
"SummaryType": null,
"GroupInterval": "",
"WordWrapEnabled": false
},
"Alignment": "right",
"Format": null,
"EditOrderNo": 7,
"EditGroupOrderNo": 1,
"EditorType2": "dxNumberBox",
"ColSpan": 1,
"EditorOptions": "{\"min\":0,\"max\":24,\"showClearButton\":true,\"format\":{\"type\":\"fixedPoint\",\"precision\":2}}", "EditorOptions": "{\"min\":0,\"max\":24,\"showClearButton\":true,\"format\":{\"type\":\"fixedPoint\",\"precision\":2}}",
"GridBoxOptions": null, "GridBoxOptions": null,
"TagBoxOptions": null, "TagBoxOptions": null,
@ -1498,7 +1762,7 @@
"Visible": true, "Visible": true,
"IsActive": true, "IsActive": true,
"Width": 0, "Width": 0,
"ListOrderNo": 7, "ListOrderNo": 9,
"SourceDbType": 3, "SourceDbType": 3,
"CultureName": "en", "CultureName": "en",
"DataType": "boolean", "DataType": "boolean",
@ -1598,7 +1862,7 @@
}, },
"Alignment": null, "Alignment": null,
"Format": null, "Format": null,
"EditOrderNo": 6, "EditOrderNo": 8,
"EditGroupOrderNo": 1, "EditGroupOrderNo": 1,
"EditorType2": "dxCheckBox", "EditorType2": "dxCheckBox",
"ColSpan": 1, "ColSpan": 1,
@ -1636,7 +1900,7 @@
"Visible": true, "Visible": true,
"IsActive": true, "IsActive": true,
"Width": 0, "Width": 0,
"ListOrderNo": 8, "ListOrderNo": 10,
"SourceDbType": 3, "SourceDbType": 3,
"CultureName": "en", "CultureName": "en",
"DataType": "boolean", "DataType": "boolean",
@ -1736,7 +2000,7 @@
}, },
"Alignment": null, "Alignment": null,
"Format": null, "Format": null,
"EditOrderNo": 7, "EditOrderNo": 9,
"EditGroupOrderNo": 1, "EditGroupOrderNo": 1,
"EditorType2": "dxCheckBox", "EditorType2": "dxCheckBox",
"ColSpan": 1, "ColSpan": 1,
@ -1762,7 +2026,9 @@
"App.Listform.ListformField.ShiftName", "App.Listform.ListformField.ShiftName",
"App.Listform.ListformField.BreakMinutes", "App.Listform.ListformField.BreakMinutes",
"App.Listform.ListformField.WorkingHours", "App.Listform.ListformField.WorkingHours",
"App.Listform.ListformField.IsNightShift" "App.Listform.ListformField.IsNightShift",
"App.Listform.ListformField.LateToleranceMinutes",
"App.Listform.ListformField.EarlyLeaveToleranceMinutes"
], ],
"PermissionGroupNames": [], "PermissionGroupNames": [],
"PermissionNames": [ "PermissionNames": [

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -32,8 +32,8 @@
"MenuTr": "Eğitimler", "MenuTr": "Eğitimler",
"TitleEn": "Trainings", "TitleEn": "Trainings",
"TitleTr": "Eğitimler", "TitleTr": "Eğitimler",
"DescEn": "Trainings — each training session: dates/times, duration, place, trainer, cost, skills gained, participants and files.\nWhere: Human Resources › Training › Trainings. The detail has Participants and Files tabs.\nFields:\n• Type → Subject (filtered by type), entry date, branch\n• Start/end date and time → total hours = days × daily hours (automatic)\n• Status → Open / Closed; trainer, place, institution\n• SkillIds → skills gained (informational, not written to the employee profile)\n• Cost items (place, trainer, accommodation, transport, catering, other) → total cost automatic\nRelated: a Performance Management development action can link to a training; when the employee is marked Attended the action completes itself.\nWidgets: total, open, closed trainings and total cost.", "DescEn": "Trainings — each training session: dates/times, duration, place, trainer, cost, skills gained, participants and files.\nWhere: Human Resources › Training › Trainings. The detail has Participants and Files tabs.\nFields:\n• Type → Subject (filtered by type), entry date, branch\n• Start/end date and time → total hours = days × daily hours (automatic)\n• Status → Open / Closed; trainer, place, institution\n• SkillIds → skills gained (informational, not written to the employee profile)\n• Cost items (place, trainer, accommodation, transport, catering, other) → total cost automatic\nRelated: a Performance Management development action can link to a training; when the employee is marked Attended the action completes itself. Work days between the start and end date are Training days in the timesheet of attending participants; changing the dates recalculates them.\nWidgets: total, open, closed trainings and total cost.",
"DescTr": "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.\nNerede: İnsan Kaynakları › Eğitim › Eğitimler. Detayda Katılımcılar ve Dosyalar sekmeleri vardır.\nAlanlar:\n• Tip → Konu (tipe göre süzülür), giriş tarihi, şube\n• Başlangıç/bitiş tarihi ve saati → Toplam süre = gün sayısı × günlük saat (otomatik)\n• Status → Açık / Kapalı; eğitmen, eğitim yeri, eğitim veren kurum\n• SkillIds → eğitimin kazandırdığı yetkinlikler (bilgi amaçlı, çalışan profiline yazılmaz)\n• Maliyet kalemleri (yer, eğitmen, konaklama, ulaşım, ikram, diğer) → toplam maliyet otomatik\nİlişkili: Performans Yönetimi'ndeki gelişim aksiyonu bir eğitime bağlanabilir; çalışan bu eğitimde Katıldı olarak işlenirse aksiyon kendiliğinden tamamlanır.\nWidget'lar: toplam, açık, kapalı eğitim ve toplam maliyet.", "DescTr": "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.\nNerede: İnsan Kaynakları › Eğitim › Eğitimler. Detayda Katılımcılar ve Dosyalar sekmeleri vardır.\nAlanlar:\n• Tip → Konu (tipe göre süzülür), giriş tarihi, şube\n• Başlangıç/bitiş tarihi ve saati → Toplam süre = gün sayısı × günlük saat (otomatik)\n• Status → Açık / Kapalı; eğitmen, eğitim yeri, eğitim veren kurum\n• SkillIds → eğitimin kazandırdığı yetkinlikler (bilgi amaçlı, çalışan profiline yazılmaz)\n• Maliyet kalemleri (yer, eğitmen, konaklama, ulaşım, ikram, diğer) → toplam maliyet otomatik\nİlişkili: Performans Yönetimi'ndeki gelişim aksiyonu bir eğitime bağlanabilir; çalışan bu eğitimde Katıldı olarak işlenirse aksiyon kendiliğinden tamamlanır. Başlangıç–bitiş arasındaki iş günleri katılımcının puantajında Eğitimde yazılır; tarih değişince yeniden hesaplanır.\nWidget'lar: toplam, açık, kapalı eğitim ve toplam maliyet.",
"Texts": [ "Texts": [
{ {
"Key": "App.Hr.Training.Widget.Open", "Key": "App.Hr.Training.Widget.Open",
@ -230,7 +230,7 @@
"SeedSyncDelete": false, "SeedSyncDelete": false,
"DeleteCommand": "UPDATE \"Hr_T_Training\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Hr_T_Training\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": null, "DeleteBeforeCommand": null,
"DeleteAfterCommand": null, "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_Training WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_TrainingSync @_id, NULL, @DeleterId; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",
@ -282,7 +282,7 @@
], ],
"UpdateCommand": null, "UpdateCommand": null,
"UpdateBeforeCommand": null, "UpdateBeforeCommand": null,
"UpdateAfterCommand": null, "UpdateAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_Training WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_TrainingSync @_id, NULL, @LastModifierId; END",
"UpdateFieldsDefaultValueDto": [], "UpdateFieldsDefaultValueDto": [],
"FormFieldsDefaultValueDto": [], "FormFieldsDefaultValueDto": [],
"WidgetsDto": [ "WidgetsDto": [

View file

@ -25,8 +25,8 @@
"MenuTr": "Katılımcılar", "MenuTr": "Katılımcılar",
"TitleEn": "Participants", "TitleEn": "Participants",
"TitleTr": "Katılımcılar", "TitleTr": "Katılımcılar",
"DescEn": "Participants — employees attending a training and their attendance result.\nWhere: the Participants tab of a Training record (no menu entry).\nFields:\n• UserId → employee; hire date, department and position are copied (state at training time)\n• AttendanceStatus → Attended (default) / Not attended / Excused\n• Evaluation score, exam score, leave date, note\nButton: rows with Attended print the Attendance Certificate.\nRelated: Attended completes a linked development action in Performance Management.", "DescEn": "Participants — employees attending a training and their attendance result.\nWhere: the Participants tab of a Training record (no menu entry).\nFields:\n• UserId → employee; hire date, department and position are copied (state at training time)\n• AttendanceStatus → Attended (default) / Not attended / Excused\n• Evaluation score, exam score, leave date, note\nButton: rows with Attended print the Attendance Certificate.\nRelated: Attended completes a linked development action in Performance Management and marks the training days as Training in the timesheet (not absent).",
"DescTr": "Katılımcılar — eğitime katılan personel ve katılım sonucu.\nNerede: Eğitimler ekranında kaydın Katılımcılar sekmesi (menüde ayrıca yoktur).\nAlanlar:\n• UserId → personel; seçilince işe giriş tarihi, bölüm ve görev kopyalanır (eğitim anındaki hâl saklanır)\n• AttendanceStatus → Katıldı (varsayılan) / Katılmadı / Mazeretli\n• Değerlendirme puanı, sınav notu, ayrılma tarihi, not\nButon: Katıldı durumundaki satırda Katılım Belgesi raporu basılır.\nİlişkili: Katıldı kaydı, Performans Yönetimi'nde bu eğitime bağlı gelişim aksiyonunu tamamlar." "DescTr": "Katılımcılar — eğitime katılan personel ve katılım sonucu.\nNerede: Eğitimler ekranında kaydın Katılımcılar sekmesi (menüde ayrıca yoktur).\nAlanlar:\n• UserId → personel; seçilince işe giriş tarihi, bölüm ve görev kopyalanır (eğitim anındaki hâl saklanır)\n• AttendanceStatus → Katıldı (varsayılan) / Katılmadı / Mazeretli\n• Değerlendirme puanı, sınav notu, ayrılma tarihi, not\nButon: Katıldı durumundaki satırda Katılım Belgesi raporu basılır.\nİlişkili: Katıldı kaydı, Performans Yönetimi'nde bu eğitime bağlı gelişim aksiyonunu tamamlar ve eğitim günlerini puantajda Eğitimde yazar (devamsız sayılmaz)."
}, },
"Groups": [ "Groups": [
{ {
@ -116,7 +116,7 @@
"SeedSyncDelete": false, "SeedSyncDelete": false,
"DeleteCommand": "UPDATE \"Hr_T_TrainingParticipant\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Hr_T_TrainingParticipant\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": null, "DeleteBeforeCommand": null,
"DeleteAfterCommand": null, "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_TrainingParticipant WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; DECLARE @_t uniqueidentifier, @_u uniqueidentifier; SELECT @_t = TrainingId, @_u = UserId FROM Hr_T_TrainingParticipant WHERE Id = @_id; EXEC dbo.Hr_S_TrainingSync @_t, @_u, @DeleterId; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",
@ -135,7 +135,7 @@
], ],
"InsertCommand": null, "InsertCommand": null,
"InsertBeforeCommand": null, "InsertBeforeCommand": null,
"InsertAfterCommand": null, "InsertAfterCommand": "DECLARE @_t uniqueidentifier, @_u uniqueidentifier; SELECT @_t = TrainingId, @_u = UserId FROM Hr_T_TrainingParticipant WHERE Id = @Id; EXEC dbo.Hr_S_TrainingSync @_t, @_u, @CreatorId",
"InsertFieldsDefaultValueDto": [ "InsertFieldsDefaultValueDto": [
{ {
"FieldName": "CreationTime", "FieldName": "CreationTime",
@ -168,7 +168,7 @@
], ],
"UpdateCommand": null, "UpdateCommand": null,
"UpdateBeforeCommand": null, "UpdateBeforeCommand": null,
"UpdateAfterCommand": null, "UpdateAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_TrainingParticipant WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; DECLARE @_t uniqueidentifier, @_u uniqueidentifier; SELECT @_t = TrainingId, @_u = UserId FROM Hr_T_TrainingParticipant WHERE Id = @_id; EXEC dbo.Hr_S_TrainingSync @_t, @_u, @LastModifierId; END",
"UpdateFieldsDefaultValueDto": [], "UpdateFieldsDefaultValueDto": [],
"FormFieldsDefaultValueDto": [], "FormFieldsDefaultValueDto": [],
"WidgetsDto": [], "WidgetsDto": [],

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Vehicles", "MenuParentCode": "App.Hr.Vehicles",
"MenuParentIcon": "FcAutomotive", "MenuParentIcon": "FcAutomotive",
"MenuCode": "App.Hr.Vehicle", "MenuCode": "App.Hr.Vehicle",
"MenuOrder": 2, "MenuOrder": 4,
"MenuUrl": "/admin/list/App.Hr.Vehicle", "MenuUrl": "/admin/list/App.Hr.Vehicle",
"MenuIcon": "FcAutomotive" "MenuIcon": "FcAutomotive"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Vehicles", "MenuParentCode": "App.Hr.Vehicles",
"MenuParentIcon": "FcAutomotive", "MenuParentIcon": "FcAutomotive",
"MenuCode": "App.Hr.VehicleExpense", "MenuCode": "App.Hr.VehicleExpense",
"MenuOrder": 6, "MenuOrder": 7,
"MenuUrl": "/admin/list/App.Hr.VehicleExpense", "MenuUrl": "/admin/list/App.Hr.VehicleExpense",
"MenuIcon": "FcMoneyTransfer" "MenuIcon": "FcMoneyTransfer"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Vehicles", "MenuParentCode": "App.Hr.Vehicles",
"MenuParentIcon": "FcAutomotive", "MenuParentIcon": "FcAutomotive",
"MenuCode": "App.Hr.VehicleExpenseDefinition", "MenuCode": "App.Hr.VehicleExpenseDefinition",
"MenuOrder": 5, "MenuOrder": 2,
"MenuUrl": "/admin/list/App.Hr.VehicleExpenseDefinition", "MenuUrl": "/admin/list/App.Hr.VehicleExpenseDefinition",
"MenuIcon": "FcList" "MenuIcon": "FcList"
}, },

View file

@ -19,7 +19,7 @@
"MenuParentCode": "App.Hr.Vehicles", "MenuParentCode": "App.Hr.Vehicles",
"MenuParentIcon": "FcAutomotive", "MenuParentIcon": "FcAutomotive",
"MenuCode": "App.Hr.VehicleMovement", "MenuCode": "App.Hr.VehicleMovement",
"MenuOrder": 7, "MenuOrder": 6,
"MenuUrl": "/admin/list/App.Hr.VehicleMovement", "MenuUrl": "/admin/list/App.Hr.VehicleMovement",
"MenuIcon": "FcInspection" "MenuIcon": "FcInspection"
}, },

View file

@ -11,7 +11,7 @@
"MenuParentCode": "App.Hr", "MenuParentCode": "App.Hr",
"MenuParentIcon": "FcConferenceCall", "MenuParentIcon": "FcConferenceCall",
"MenuCode": "App.Hr.Visitor", "MenuCode": "App.Hr.Visitor",
"MenuOrder": 3, "MenuOrder": 12,
"MenuUrl": "/admin/list/App.Hr.Visitor", "MenuUrl": "/admin/list/App.Hr.Visitor",
"MenuIcon": "FcBusinessman" "MenuIcon": "FcBusinessman"
}, },

View file

@ -11,7 +11,7 @@
"MenuParentCode": "App.Hr", "MenuParentCode": "App.Hr",
"MenuParentIcon": "FcConferenceCall", "MenuParentIcon": "FcConferenceCall",
"MenuCode": "App.Hr.WorkCalendar", "MenuCode": "App.Hr.WorkCalendar",
"MenuOrder": 2, "MenuOrder": 4,
"MenuUrl": "/admin/list/App.Hr.WorkCalendar", "MenuUrl": "/admin/list/App.Hr.WorkCalendar",
"MenuIcon": "FcCalendar" "MenuIcon": "FcCalendar"
}, },
@ -24,8 +24,8 @@
"MenuTr": "Çalışma Takvimi", "MenuTr": "Çalışma Takvimi",
"TitleEn": "Work Calendar", "TitleEn": "Work Calendar",
"TitleTr": "Çalışma Takvimi", "TitleTr": "Çalışma Takvimi",
"DescEn": "Work Calendar — public holidays, half days (eves) and non-working days.\nWhere: Human Resources › Work Calendar. The Scheduler view shows the year.\nFields:\n• Name, start and end date (multi-day holiday in one row)\n• DayType → Holiday / Half day\n• RecurrenceRule → Yearly (fixed-date holidays entered once) or empty (religious holidays entered each year)\nNote: not linked to leave or time-keeping calculations. Records are mirrored to the seed file.", "DescEn": "Work Calendar — public holidays, half days (eves) and non-working days.\nWhere: Human Resources › Work Calendar. The Scheduler view shows the year.\nFields:\n• Name, start and end date (multi-day holiday in one row)\n• DayType → Holiday / Half day\n• RecurrenceRule → Yearly (fixed-date holidays entered once) or empty (religious holidays entered each year)\nRelated: leave days exclude these days and the timesheet marks them as public holidays; saving, changing or deleting a row recalculates the leave days and the timesheet of the affected dates (closed timesheet months are not rewritten). Records are mirrored to the seed file.",
"DescTr": "Çalışma Takvimi — resmi tatiller, arife (yarım gün) ve çalışılmayan günler.\nNerede: İnsan Kaynakları › Çalışma Takvimi. Takvim (Scheduler) görünümünde yıl üzerinde görülür.\nAlanlar:\n• Ad, başlangıç ve bitiş tarihi (çok günlü tatil tek satırda)\n• DayType → Tatil / Yarım Gün\n• RecurrenceRule → Her yıl (sabit tarihli resmi tatiller bir kez girilir) ya da boş (dini bayramlar her yıl ayrı girilir)\nDikkat: takvim izin ya da puantaj hesabına bağlı değildir. Kayıtlar seed dosyasına da yazılır.", "DescTr": "Çalışma Takvimi — resmi tatiller, arife (yarım gün) ve çalışılmayan günler.\nNerede: İnsan Kaynakları › Çalışma Takvimi. Takvim (Scheduler) görünümünde yıl üzerinde görülür.\nAlanlar:\n• Ad, başlangıç ve bitiş tarihi (çok günlü tatil tek satırda)\n• DayType → Tatil / Yarım Gün\n• RecurrenceRule → Her yıl (sabit tarihli resmi tatiller bir kez girilir) ya da boş (dini bayramlar her yıl ayrı girilir)\nİlişkili: izin günleri bu günleri saymaz, puantaj bu günleri resmî tatil yazar; satır eklenince, değişince ya da silinince denk gelen izinlerin gün sayısı ve puantaj yeniden hesaplanır (kapalı puantaj ayı yazılmaz). Kayıtlar seed dosyasına da yazılır.",
"Texts": [ "Texts": [
{ {
"Key": "App.Hr.WorkCalendar.DayType.Holiday", "Key": "App.Hr.WorkCalendar.DayType.Holiday",
@ -119,7 +119,7 @@
"SeedSyncDelete": true, "SeedSyncDelete": true,
"DeleteCommand": "UPDATE \"Hr_T_WorkCalendar\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id", "DeleteCommand": "UPDATE \"Hr_T_WorkCalendar\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\" IN @Id",
"DeleteBeforeCommand": null, "DeleteBeforeCommand": null,
"DeleteAfterCommand": null, "DeleteAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_WorkCalendar WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_WorkCalendarAfterSave @_id, @DeleterId; END",
"DeleteFieldsDefaultValueDto": [ "DeleteFieldsDefaultValueDto": [
{ {
"FieldName": "DeleterId", "FieldName": "DeleterId",
@ -138,7 +138,7 @@
], ],
"InsertCommand": null, "InsertCommand": null,
"InsertBeforeCommand": null, "InsertBeforeCommand": null,
"InsertAfterCommand": null, "InsertAfterCommand": "EXEC dbo.Hr_S_WorkCalendarAfterSave @Id, @CreatorId",
"InsertFieldsDefaultValueDto": [ "InsertFieldsDefaultValueDto": [
{ {
"FieldName": "CreationTime", "FieldName": "CreationTime",
@ -171,7 +171,7 @@
], ],
"UpdateCommand": null, "UpdateCommand": null,
"UpdateBeforeCommand": null, "UpdateBeforeCommand": null,
"UpdateAfterCommand": null, "UpdateAfterCommand": "DECLARE @_k TABLE (Id uniqueidentifier); INSERT INTO @_k SELECT Id FROM Hr_T_WorkCalendar WHERE Id IN @Id; DECLARE @_id uniqueidentifier; WHILE EXISTS (SELECT 1 FROM @_k) BEGIN SELECT TOP 1 @_id = Id FROM @_k; DELETE FROM @_k WHERE Id = @_id; EXEC dbo.Hr_S_WorkCalendarAfterSave @_id, @LastModifierId; END",
"UpdateFieldsDefaultValueDto": [], "UpdateFieldsDefaultValueDto": [],
"FormFieldsDefaultValueDto": [ "FormFieldsDefaultValueDto": [
{ {

View file

@ -4498,7 +4498,6 @@ mr-1.4
sozsoft-* sozsoft-*
# --- custom component classes --- # --- custom component classes ---
!bg-transparent !bg-transparent
${className}
absolute absolute
backdrop-blur-sm backdrop-blur-sm
bg-amber-50 bg-amber-50
@ -4508,11 +4507,13 @@ bg-blue-950/25
bg-gradient-to-br bg-gradient-to-br
bg-gradient-to-r bg-gradient-to-r
bg-gray-100 bg-gray-100
bg-gray-200
bg-gray-50 bg-gray-50
bg-gray-950 bg-gray-950
bg-gray-950/80 bg-gray-950/80
bg-green-700 bg-green-700
bg-indigo-50 bg-indigo-50
bg-indigo-600
bg-orange-100 bg-orange-100
bg-purple-700 bg-purple-700
bg-red-50 bg-red-50
@ -4550,6 +4551,7 @@ break-all
col-start-3 col-start-3
container container
dark:bg-amber-950 dark:bg-amber-950
dark:bg-gray-700
dark:bg-gray-800 dark:bg-gray-800
dark:bg-gray-900 dark:bg-gray-900
dark:bg-gray-900/40 dark:bg-gray-900/40
@ -4591,6 +4593,7 @@ dark:text-green-400
dark:text-indigo-300 dark:text-indigo-300
dark:text-indigo-400 dark:text-indigo-400
dark:text-orange-300 dark:text-orange-300
dark:text-purple-400
dark:text-red-200 dark:text-red-200
dark:text-red-400 dark:text-red-400
dark:text-slate-100 dark:text-slate-100
@ -4621,6 +4624,7 @@ gap-2
gap-3 gap-3
gap-6 gap-6
gap-8 gap-8
gap-x-3
gap-x-4 gap-x-4
gap-y-1 gap-y-1
grid grid
@ -4629,6 +4633,7 @@ grid-cols-2
grid-cols-3 grid-cols-3
grid-cols-[auto_1fr_auto] grid-cols-[auto_1fr_auto]
h-10 h-10
h-2
h-5 h-5
h-9 h-9
h-[600px] h-[600px]
@ -4637,6 +4642,7 @@ hidden
hover:!bg-transparent hover:!bg-transparent
hover:bg-blue-50 hover:bg-blue-50
hover:bg-gray-50 hover:bg-gray-50
hover:bg-indigo-700
hover:bg-red-700 hover:bg-red-700
hover:bg-sky-700 hover:bg-sky-700
hover:bg-slate-50 hover:bg-slate-50
@ -4745,6 +4751,7 @@ py-6
relative relative
rounded rounded
rounded-2xl rounded-2xl
rounded-full
rounded-lg rounded-lg
rounded-md rounded-md
rounded-xl rounded-xl

View file

@ -33,6 +33,7 @@ import {
} from '@/services/identity.service' } from '@/services/identity.service'
import { CountryDto, getCountry } from '@/services/country.service' import { CountryDto, getCountry } from '@/services/country.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Field, FieldArray, FieldProps, Form, Formik, FormikHelpers } from 'formik' import { Field, FieldArray, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { ReactNode, useEffect, useMemo, useRef, useState } from 'react' import { ReactNode, useEffect, useMemo, useRef, useState } from 'react'
@ -75,6 +76,7 @@ import {
FaUpload, FaUpload,
FaHourglassHalf, FaHourglassHalf,
FaUmbrellaBeach, FaUmbrellaBeach,
FaBusinessTime,
} from 'react-icons/fa' } from 'react-icons/fa'
import { import {
CircleStencil, CircleStencil,
@ -98,6 +100,9 @@ import EducationSkillsTab from './EducationSkillsTab'
import FamilyEmergencyTab from './FamilyEmergencyTab' import FamilyEmergencyTab from './FamilyEmergencyTab'
import FinancialTab from './FinancialTab' import FinancialTab from './FinancialTab'
import LeaveTab from './LeaveTab' import LeaveTab from './LeaveTab'
import TimesheetTab from './TimesheetTab'
import HrRecordsTab from './HrRecordsTab'
import { HR_RECORD_TABS } from './hrRecordTabs'
import { import {
CheckboxField, CheckboxField,
DateField, DateField,
@ -141,6 +146,8 @@ const isProbationInvalid = (hireDate?: Date | string, probationEndDate?: Date |
function UserDetails() { function UserDetails() {
const { userId } = useParams() const { userId } = useParams()
const { translate } = useLocalization() const { translate } = useLocalization()
const { checkPermission } = usePermission()
const hrTabs = HR_RECORD_TABS.filter((tab) => tab.lists.some(([code]) => checkPermission(code)))
const [userDetails, setUserDetails] = useState<UserInfoViewModel>() const [userDetails, setUserDetails] = useState<UserInfoViewModel>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [confirmDeleteClaim, setConfirmDeleteClaim] = useState<AssignedClaimViewModel | null>(null) const [confirmDeleteClaim, setConfirmDeleteClaim] = useState<AssignedClaimViewModel | null>(null)
@ -340,6 +347,14 @@ function UserDetails() {
<TabNav value="leaves" icon={<FaUmbrellaBeach className="text-sm" />}> <TabNav value="leaves" icon={<FaUmbrellaBeach className="text-sm" />}>
{translate('::Abp.Identity.User.Leaves')} {translate('::Abp.Identity.User.Leaves')}
</TabNav> </TabNav>
<TabNav value="timesheet" icon={<FaBusinessTime className="text-sm" />}>
{translate('::Abp.Identity.User.Timesheet')}
</TabNav>
{hrTabs.map(({ value, label, Icon }) => (
<TabNav key={value} value={value} icon={<Icon className="text-sm" />}>
{translate(`::${label}`)}
</TabNav>
))}
<TabNav value="permission" icon={<FaCheckCircle className="text-sm" />}> <TabNav value="permission" icon={<FaCheckCircle className="text-sm" />}>
{translate('::Abp.Identity.Permissions')} {translate('::Abp.Identity.Permissions')}
</TabNav> </TabNav>
@ -1065,6 +1080,20 @@ function UserDetails() {
</div> </div>
</TabContent> </TabContent>
<TabContent value="timesheet">
<div className="px-4 py-2">
<TimesheetTab userId={userDetails.id!} />
</div>
</TabContent>
{hrTabs.map(({ value, lists }) => (
<TabContent key={value} value={value}>
<div className="px-4 py-2">
<HrRecordsTab userId={userDetails.id!} lists={lists} />
</div>
</TabContent>
))}
<TabContent value="educationSkills"> <TabContent value="educationSkills">
<div className="px-4 py-2"> <div className="px-4 py-2">
<EducationSkillsTab userDetails={userDetails} onSaved={getUser} /> <EducationSkillsTab userDetails={userDetails} onSaved={getUser} />

View file

@ -0,0 +1,37 @@
import PlatformViewHost from '@/components/componentEditor/PlatformViewHost'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission'
import { useMemo } from 'react'
import type { HrRecordList } from './hrRecordTabs'
function EmployeeList({ code, employeeField, height, userId }: { code: string; employeeField: string; height: string; userId: string }) {
// Kimliği sabit tutulur; her çizimde yeni süzgeç liste verisini yeniden yükletirdi.
const searchParams = useMemo(
() => new URLSearchParams({ filter: JSON.stringify([employeeField, '=', userId]) }),
[employeeField, userId],
)
return <PlatformViewHost view="List" listFormCode={code} height={height} searchParams={searchParams} />
}
/**
* İK modüllerinin çalışana ait kayıtları; ekranlar kendi sorgusu, yetkisi ve kiracı süzmesiyle açılır.
* Yeni satırın çalışan alanı da süzgeçten dolar (applyNewRowDefaults).
*/
function HrRecordsTab({ userId, lists }: { userId: string; lists: HrRecordList[] }) {
const { translate } = useLocalization()
const { checkPermission } = usePermission()
const visible = lists.filter(([code]) => checkPermission(code))
return (
<div className="flex flex-col gap-6">
{visible.map(([code, employeeField, height]) => (
<div key={code}>
{visible.length > 1 && <h6 className="mb-2">{translate(`::${code}`)}</h6>}
<EmployeeList code={code} employeeField={employeeField} height={height} userId={userId} />
</div>
))}
</div>
)
}
export default HrRecordsTab

View file

@ -0,0 +1,109 @@
import PlatformViewHost from '@/components/componentEditor/PlatformViewHost'
import apiService from '@/services/api.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission'
import { useEffect, useMemo, useState } from 'react'
const MONTHLY = 'App.Hr.TimesheetMonthly'
const DAILY = 'App.Hr.Timesheet'
const EVENTS = 'App.Hr.AttendanceLog'
type MonthlyRow = {
PeriodYear?: number
NetHours?: number
WorkDays?: number
OvertimeHours?: number
LateMinutes?: number
EarlyLeaveMinutes?: number
AbsentDays?: number
LeaveDays?: number
SickDays?: number
AnnualOvertimeLimit?: number
}
const format = (value: number) => (Number.isInteger(value) ? String(value) : value.toFixed(1))
/** Puantaj özeti Aylık Puantaj ekranının sorgusundan okunur; yetki ve kiracı süzmesi ListForm'da kalır. */
function TimesheetTab({ userId }: { userId: string }) {
const { translate } = useLocalization()
const { checkPermission } = usePermission()
const [rows, setRows] = useState<MonthlyRow[]>([])
const canSeeMonthly = checkPermission(MONTHLY)
const year = new Date().getFullYear()
// Yeni hareket satırının EmployeeId değeri de bu filtreden dolar (applyNewRowDefaults).
const employeeSearchParams = useMemo(
() => new URLSearchParams({ filter: JSON.stringify(['EmployeeId', '=', userId]) }),
[userId],
)
useEffect(() => {
if (!canSeeMonthly) return
let active = true
apiService
.fetchData<{ data?: MonthlyRow[] }>({
method: 'GET',
url: '/api/app/list-form-select/select',
params: { listFormCode: MONTHLY, filter: JSON.stringify(['EmployeeId', '=', userId]), take: 500 },
})
.then(
(response) =>
active && setRows((response.data?.data ?? []).filter((row) => Number(row.PeriodYear) === year)),
)
.catch(() => active && setRows([]))
return () => {
active = false
}
}, [canSeeMonthly, userId, year])
const total = (name: keyof MonthlyRow) => rows.reduce((sum, row) => sum + Number(row[name] ?? 0), 0)
const field = (name: string) => translate(`::App.Listform.ListformField.${name}`)
const overtime = total('OvertimeHours')
const limit = Number(rows[0]?.AnnualOvertimeLimit ?? 0) || 270
const cards: [string, number, string][] = [
['WorkDays', total('WorkDays'), 'text-gray-900 dark:text-gray-100'],
['NetHours', total('NetHours'), 'text-indigo-600'],
['OvertimeHours', overtime, overtime > limit ? 'text-red-600' : 'text-purple-600'],
['LateMinutes', total('LateMinutes'), 'text-orange-500'],
['EarlyLeaveMinutes', total('EarlyLeaveMinutes'), 'text-orange-500'],
['AbsentDays', total('AbsentDays'), 'text-red-600'],
['LeaveDays', total('LeaveDays'), 'text-teal-600'],
['SickDays', total('SickDays'), 'text-violet-600'],
]
const lists: [string, string][] = [
[MONTHLY, '320px'],
[DAILY, '360px'],
[EVENTS, '320px'],
]
return (
<div className="flex flex-col gap-6">
{canSeeMonthly && (
<div>
<h6 className="mb-2">
{year} · {translate('::App.Listform.ListformField.AnnualOvertimeLimit')}: {format(overtime)} / {format(limit)}
</h6>
<div className="grid grid-cols-2 gap-3 md:grid-cols-4 xl:grid-cols-8">
{cards.map(([name, value, color]) => (
<div key={name} className="rounded-lg border border-gray-200 p-3 text-center dark:border-gray-700">
<div className={`text-xl font-semibold ${color}`}>{format(value)}</div>
<div className="text-xs text-gray-500 dark:text-gray-400">{field(name)}</div>
</div>
))}
</div>
</div>
)}
{lists
.filter(([code]) => checkPermission(code))
.map(([code, height]) => (
<div key={code}>
<h6 className="mb-2">{translate(`::${code}`)}</h6>
<PlatformViewHost view="List" listFormCode={code} height={height} searchParams={employeeSearchParams} />
</div>
))}
</div>
)
}
export default TimesheetTab

View file

@ -0,0 +1,30 @@
import type { IconType } from 'react-icons'
import { FaChalkboardTeacher, FaChartLine, FaGavel } from 'react-icons/fa'
/** Ekran kodu, çalışanı tutan alan ve liste yüksekliği. */
export type HrRecordList = [code: string, employeeField: string, height: string]
/** Kullanıcı detayındaki İK kayıt sekmeleri; sekme, ekranlarından birini görme yetkisi varsa çizilir. */
export const HR_RECORD_TABS: { value: string; label: string; Icon: IconType; lists: HrRecordList[] }[] = [
{
value: 'trainings',
label: 'Abp.Identity.User.Trainings',
Icon: FaChalkboardTeacher,
lists: [['App.Hr.TrainingParticipant', 'UserId', '420px']],
},
{
value: 'performance',
label: 'Abp.Identity.User.Performance',
Icon: FaChartLine,
lists: [
['App.Hr.PerformanceReview', 'EmployeeId', '360px'],
['App.Hr.DevelopmentPlan', 'EmployeeId', '360px'],
],
},
{
value: 'disciplinary',
label: 'Abp.Identity.User.Disciplinary',
Icon: FaGavel,
lists: [['App.Hr.DisciplinaryCase', 'UserId', '420px']],
},
]