İzin Yönetimi
This commit is contained in:
parent
7ecb45a53f
commit
48d7599ced
60 changed files with 22891 additions and 295 deletions
|
|
@ -1374,7 +1374,7 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `
|
||||||
| **Definitions › Department** | `App.Hr.Department` | `Hr_T_Department` | tenant | **Şube bazlı** departman ağacı: ilk sütun `BranchId` (Şube Adı; `LookupQueryValues.TenantBranchValues`, zorunlu), `ParentId` lookup'ı seçili şubenin departmanlarına süzülür (`BranchDepartmentValues`, cascade `BranchId`). `ParentId` ile **ağaç (TreeList) düzeninin** referansı; personel/onay ekranlarının departman lookup'ı. Tekil indeks `TenantId + BranchId + Name`. Seed `data/App.Hr.Department.json`. |
|
| **Definitions › Department** | `App.Hr.Department` | `Hr_T_Department` | tenant | **Şube bazlı** departman ağacı: ilk sütun `BranchId` (Şube Adı; `LookupQueryValues.TenantBranchValues`, zorunlu), `ParentId` lookup'ı seçili şubenin departmanlarına süzülür (`BranchDepartmentValues`, cascade `BranchId`). `ParentId` ile **ağaç (TreeList) düzeninin** referansı; personel/onay ekranlarının departman lookup'ı. Tekil indeks `TenantId + BranchId + Name`. Seed `data/App.Hr.Department.json`. |
|
||||||
| **Definitions › Job Position** | `App.Hr.JobPosition` | `Hr_T_JobPosition` | tenant | Ünvan ağacı. Form sırası `BranchId` → `DepartmentId` (şubeye göre süzülür) → `Name` → `ParentId` (departmana göre süzülür); şube değişince departman ve üst görev temizlenir (`CascadeEmptyFields`). **İki kademeli cascade** örneği. Seed `data/App.Hr.JobPosition.json`. |
|
| **Definitions › Job Position** | `App.Hr.JobPosition` | `Hr_T_JobPosition` | tenant | Ünvan ağacı. Form sırası `BranchId` → `DepartmentId` (şubeye göre süzülür) → `Name` → `ParentId` (departmana göre süzülür); şube değişince departman ve üst görev temizlenir (`CascadeEmptyFields`). **İki kademeli cascade** örneği. Seed `data/App.Hr.JobPosition.json`. |
|
||||||
| **Work Calendar** | `App.Hr.WorkCalendar` | `Hr_T_WorkCalendar` | tenant | Resmi tatil ve çalışılmayan günler: `Name`, `StartDate`, `EndDate`, `DayType` (`Holiday`/`HalfDay`), `RecurrenceRule` (boş = tek sefer, `FREQ=YEARLY` = her yıl), `AllDay` (gizli, `true`), `IsActive`. Grid'e ek olarak **Takvim (Scheduler)** görünümü açıktır (`TextExpr = Name`). İzin ve puantaj hesabının tatil kaynağıdır. Wizard `wizard/WorkCalendar.json`, tablo `sql/object/Hr_T_WorkCalendar.sql`, seed `data/App.Hr.WorkCalendar.json` (sabit tarihli resmi tatiller her yıl tekrar eder; Ramazan ve Kurban bayramları hicri takvime göre kaydığı için 2026–2027 tarihleriyle tek seferlik girilir, sonraki yıllar ekrandan eklenir). |
|
| **Work Calendar** | `App.Hr.WorkCalendar` | `Hr_T_WorkCalendar` | tenant | Resmi tatil ve çalışılmayan günler: `Name`, `StartDate`, `EndDate`, `DayType` (`Holiday`/`HalfDay`), `RecurrenceRule` (boş = tek sefer, `FREQ=YEARLY` = her yıl), `AllDay` (gizli, `true`), `IsActive`. Grid'e ek olarak **Takvim (Scheduler)** görünümü açıktır (`TextExpr = Name`). İzin ve puantaj hesabının tatil kaynağıdır. Wizard `wizard/WorkCalendar.json`, tablo `sql/object/Hr_T_WorkCalendar.sql`, seed `data/App.Hr.WorkCalendar.json` (sabit tarihli resmi tatiller her yıl tekrar eder; Ramazan ve Kurban bayramları hicri takvime göre kaydığı için 2026–2027 tarihleriyle tek seferlik girilir, sonraki yıllar ekrandan eklenir). |
|
||||||
| **Definitions › Leave Type** | `App.Hr.LeaveType` | `Hr_T_LeaveType` | tenant | İzin türü: `Code`, `Name`, `Gender` (`All`/`Male`/`Female`), `MaxDaysPerYear`, `IsPaid`, `DeductsFromAnnualLeave`, `RequiresDocument`, `AllowHalfDay`, `IsActive`. İzin talebi/bakiye ekranlarının izin türü lookup'ı. 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`, `WorkingHours`, `IsNightShift`, `IsActive`. Seed `data/App.Hr.Shift.json`. |
|
||||||
|
|
@ -1396,6 +1396,7 @@ listesinde `Hr` varsa görür (modül listesi boş kiracıda süzme yoktur — `
|
||||||
| **Recruitment › Interview** | `App.Hr.Interview` (alt form `App.Hr.InterviewScore`) | `Hr_T_Interview` · `Hr_T_InterviewScore` | tenant | Mülakat planlama: tür, başlangıç/bitiş (**Scheduler** görünümü), mülakatçı, durum, öneri. Kayıt eklenince mülakatçıya `IseAlimMulakatAtandi` bildirimi SQL ile yazılır (tipin `Custom` kuralları kanalı belirler, metin `App.Hr.Interview.Notification.*`). Puan alt formu kriter başına 1–5; `OverallScore` = Σ(puan × ağırlık) / Σ ağırlık, başvurunun `AverageScore`'u mülakatların ortalaması. Wizard. |
|
| **Recruitment › Interview** | `App.Hr.Interview` (alt form `App.Hr.InterviewScore`) | `Hr_T_Interview` · `Hr_T_InterviewScore` | tenant | Mülakat planlama: tür, başlangıç/bitiş (**Scheduler** görünümü), mülakatçı, durum, öneri. Kayıt eklenince mülakatçıya `IseAlimMulakatAtandi` bildirimi SQL ile yazılır (tipin `Custom` kuralları kanalı belirler, metin `App.Hr.Interview.Notification.*`). Puan alt formu kriter başına 1–5; `OverallScore` = Σ(puan × ağırlık) / Σ ağırlık, başvurunun `AverageScore`'u mülakatların ortalaması. Wizard. |
|
||||||
| **Recruitment › Job Offer** | `App.Hr.JobOffer` | `Hr_T_JobOffer` | tenant | Teklif: `OfferNo` (`TKL-…`), başvuru seçilince pozisyon bilgileri ilandan `copy` ile dolar, brüt ücret + para birimi, yan haklar (`Hr_T_BenefitType` kodları), `Status` (`Draft`/`Sent`/`Accepted`/`Declined`/`Expired`, yanıt tarihi otomatik). İç onay **Grid Workflow** (Kadro Talebi ile aynı akış). Onaylı satırda **Teklif Mektubu** butonu (`DynamicReport`, `Raporlar` kategorisi). Wizard. |
|
| **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. |
|
||||||
| **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. |
|
||||||
|
|
@ -1514,6 +1515,7 @@ alanları da doldurur (`lowcode` §0.9).
|
||||||
| "eğitim / katılımcı, araç / şoför / araç masrafı / araç çıkış-giriş, olay günlüğü, disiplin / tutanak / savunma / ihtar" | İK › Trainings · İK › Vehicles · İK › Event Log · İK › Disciplinary Case | Var olan `Hr_T_Training*` / `Hr_T_Vehicle*` / `Hr_T_Driver*` / `Hr_T_EventLog` / `Hr_T_Disciplinary*` ekranını genişlet ya da lookup bağla; paralel tablo üretme |
|
| "eğitim / katılımcı, araç / şoför / araç masrafı / araç çıkış-giriş, olay günlüğü, disiplin / tutanak / savunma / ihtar" | İK › Trainings · İK › Vehicles · İK › Event Log · İK › Disciplinary Case | Var olan `Hr_T_Training*` / `Hr_T_Vehicle*` / `Hr_T_Driver*` / `Hr_T_EventLog` / `Hr_T_Disciplinary*` ekranını genişlet ya da lookup bağla; paralel tablo üretme |
|
||||||
| "işe alım, kadro talebi, ilan, aday / CV, mülakat, teklif" | İK › Recruitment | Var olan `Hr_T_StaffRequest` / `Hr_T_JobPosting` / `Hr_T_Candidate` / `Hr_T_JobApplication` / `Hr_T_Interview` / `Hr_T_JobOffer` ekranını genişlet; personel kullanıcısını BT elle açar, aday kaydına `UserId` ile bağlanır |
|
| "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`) |
|
||||||
| "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
|
||||||
|
|
|
||||||
18
.github/instructions/lowcode.instructions.md
vendored
18
.github/instructions/lowcode.instructions.md
vendored
|
|
@ -1422,7 +1422,7 @@ cascade eksik yetenek değildir ve analizde `Ready to Start`'ı engellemez. Tam
|
||||||
| `DataSourceType` | `1` StaticData · `2` Query · `3` WebService |
|
| `DataSourceType` | `1` StaticData · `2` Query · `3` WebService |
|
||||||
| `ValueExpr` / `DisplayExpr` | Varsayılan `Key` / `Name` |
|
| `ValueExpr` / `DisplayExpr` | Varsayılan `Key` / `Name` |
|
||||||
| `LookupQuery` | Kaynağın kendisi (tipe göre biçim değişir, aşağıda) |
|
| `LookupQuery` | Kaynağın kendisi (tipe göre biçim değişir, aşağıda) |
|
||||||
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); boş ya da gelmeyen ebeveyn `NULL` bağlanır. Değer her zaman **metin** parametre olarak bağlanır (`ListFormSelectAppService.ToLookupParameter`), sayı anahtarlı ebeveyn de çalışır; dönüşümü kolon tipine göre veritabanı yapar. `WebService` gövdesine değer JSON kaçışlı yazılır |
|
| `CascadeParentFields` | **Çocuk alanda** doldurulur; değerleri sorguya taşınacak ebeveyn alan(lar), virgülle. Sırayla `@param0`, `@param1`… olur (`Query`/`WebService`); boş ya da gelmeyen ebeveyn `NULL` bağlanır. Ebeveyn çocuğu, değeri boşken kilitler (bool ebeveynde `false` da boştur) ve değiştiğinde temizler; ebeveyn yalnızca gerçekten süzülen liste için yazılır, hesap için kullanılmaz. Değer her zaman **metin** parametre olarak bağlanır (`ListFormSelectAppService.ToLookupParameter`), sayı anahtarlı ebeveyn de çalışır; dönüşümü kolon tipine göre veritabanı yapar. `WebService` gövdesine değer JSON kaçışlı yazılır |
|
||||||
| `CascadeRelationField` | **Çocuk alanda**, yalnızca `StaticData`'da anlamlıdır: öğede ilk ebeveynin değeriyle karşılaştırılan alan; boşsa `group`. Ebeveyn boşken liste süzülmez |
|
| `CascadeRelationField` | **Çocuk alanda**, yalnızca `StaticData`'da anlamlıdır: öğede ilk ebeveynin değeriyle karşılaştırılan alan; boşsa `group`. Ebeveyn boşken liste süzülmez |
|
||||||
| `CascadeFilterOperator` | `StaticData` cascade filtresinin operatörü; varsayılan `=` |
|
| `CascadeFilterOperator` | `StaticData` cascade filtresinin operatörü; varsayılan `=` |
|
||||||
| `CascadeEmptyFields` | **Ebeveyn alanda** doldurulur; bu alan değişince boşaltılacak çocuk alanlar, virgülle. Ara halka (İl) hem çocuk hem ebeveyn olduğu için iki tarafı birden taşır |
|
| `CascadeEmptyFields` | **Ebeveyn alanda** doldurulur; bu alan değişince boşaltılacak çocuk alanlar, virgülle. Ara halka (İl) hem çocuk hem ebeveyn olduğu için iki tarafı birden taşır |
|
||||||
|
|
@ -2122,8 +2122,18 @@ Kurallar:
|
||||||
geçer. Bu yüzden dosyada `N1`, `N2` yazman yeterlidir ve **tekil olmaları şarttır**.
|
geçer. Bu yüzden dosyada `N1`, `N2` yazman yeterlidir ve **tekil olmaları şarttır**.
|
||||||
- `Compare` düğümünde çok dallı karar için `CompareOutcomes` kullanılır; iki dallı basit karar
|
- `Compare` düğümünde çok dallı karar için `CompareOutcomes` kullanılır; iki dallı basit karar
|
||||||
için `NextOnTrue` / `NextOnFalse` yeterlidir.
|
için `NextOnTrue` / `NextOnFalse` yeterlidir.
|
||||||
|
Karşılaştırma **sayısaldır** (`EvaluateCondition`: `>`, `>=`, `<`, `<=`, `=`, `!=`); bit/metin kolon
|
||||||
|
okunamaz ve hata verir. Kayda göre adım atlamak için prosedür sayısal bir bayrak kolonu yazar ve
|
||||||
|
kolon ekranda gizli alan olur (örnek: İzin Yönetimi'nde üst pozisyonu olmayan çalışanın müdür
|
||||||
|
adımı, `RequiresManagerApproval`, `HrLeave.md` §5.6).
|
||||||
- `Approval` düğümü `NextOnApprove` / `NextOnReject`, `Start` ve `Inform` düğümleri
|
- `Approval` düğümü `NextOnApprove` / `NextOnReject`, `Start` ve `Inform` düğümleri
|
||||||
`NextOnStart` alanını kullanır. `End` düğümünün çıkışı yoktur.
|
`NextOnStart` alanını kullanır. `End` düğümünün çıkışı yoktur.
|
||||||
|
- **Kayda göre değişen onaycı:** `Approver` değeri `@Kolon` ise (ör. `@ManagerUserNames`) onaycı kaydın o
|
||||||
|
kolonundan okunur (`ListFormWorkflowAppService.ResolveNodeApprover`); kolon `|` ile ayrılmış kullanıcı
|
||||||
|
adı/e-posta taşır ve ekranın alanı olmalıdır (satır ListForm sorgusundan okunur; gizli alan yeter). Kolon
|
||||||
|
boşsa akış hata verir — boş onaycı herkese onay yetkisi verirdi. Kolonu kayıt sonrası prosedür doldurur
|
||||||
|
(örnek: İzin Yönetimi'nde departman müdürü, `HrLeave.md`). Tasarımcıda onaycı listesi kullanıcılarla
|
||||||
|
birlikte `Alan: {Kolon}` seçeneklerini sunar.
|
||||||
- **`Inform` düğümü e-posta gönderir** (MailQueue üzerinden, `Approver` alanındaki kullanıcı/rol
|
- **`Inform` düğümü e-posta gönderir** (MailQueue üzerinden, `Approver` alanındaki kullanıcı/rol
|
||||||
adreslerine, önceki adımların notlarıyla birlikte). Uygulama içi bildirim ya da SMS isteniyorsa
|
adreslerine, önceki adımların notlarıyla birlikte). Uygulama içi bildirim ya da SMS isteniyorsa
|
||||||
ayrıca bir bildirim kuralı tanımlanır (§9.11).
|
ayrıca bir bildirim kuralı tanımlanır (§9.11).
|
||||||
|
|
@ -2561,9 +2571,9 @@ Script `AsyncFunction` ile derlenir, aşağıdaki adlar parametre olarak enjekte
|
||||||
| `pick(nesne, 'a.b')` | Herhangi bir nesneden yol okuma |
|
| `pick(nesne, 'a.b')` | Herhangi bir nesneden yol okuma |
|
||||||
| `set('Alan', deger)` · `set({A:1, B:2})` | Yazar. Değişmeyen değer yazılmaz; yazmalar biriktirilip **tek flush** ile forma ve düzenlenen grid hücresine uygulanır |
|
| `set('Alan', deger)` · `set({A:1, B:2})` | Yazar. Değişmeyen değer yazılmaz; yazmalar biriktirilip **tek flush** ile forma ve düzenlenen grid hücresine uygulanır |
|
||||||
| `clear('A','B')` | Verilen alanları `null` yapar |
|
| `clear('A','B')` | Verilen alanları `null` yapar |
|
||||||
| `copy('kolon','Alan')` | Lookup/GridBox'ta **seçili kayıttan** taşır; hedef verilmezse yolun son parçası hedef olur |
|
| `copy('kolon','Alan')` | Lookup/GridBox'ta **seçili kayıttan** taşır; hedef verilmezse yolun son parçası hedef olur. Seçili kayıt, olay formdan gelse de (popup form, form sayfası) değişen alanın editöründen okunur; lookup sorgusu taşınacak kolonları döndürmelidir (ör. `SELECT Id AS [Key], …, DepartmentId, JobPositionId`) |
|
||||||
| `selected('Yol')` · `snum()` · `sstr()` | Seçili kaydın tamamı / sayı / metin hâli |
|
| `selected('Yol')` · `snum()` · `sstr()` | Seçili kaydın tamamı / sayı / metin hâli |
|
||||||
| `readOnly('Alan', kosul)` | Formdaki **herhangi bir** editörü kilitler/açar (yalnızca script'in bağlı olduğu alanı değil) |
|
| `readOnly('Alan', kosul)` | Formdaki **herhangi bir** editörü kilitler/açar (yalnızca script'in bağlı olduğu alanı değil). Grid popup'ında açılış çalışması (`isReady`) editörler her yeniden çizildiğinde tekrarlanır ve form verisi o anda güncel değildir; koşul başka bir alana bakıyorsa değer `editor.component.cellValue(satır, 'Alan')` ile okunur (örnek: `HrLeave.md` §5.1) |
|
||||||
| `round(x, 2)` · `sum('A','B')` | Matematik |
|
| `round(x, 2)` · `sum('A','B')` | Matematik |
|
||||||
| `days('Bas','Bit')` · `hours('Bas','Bit')` | Gün farkı (bitiş dahil) · saat farkı (negatifse +24) |
|
| `days('Bas','Bit')` · `hours('Bas','Bit')` | Gün farkı (bitiş dahil) · saat farkı (negatifse +24) |
|
||||||
| `tpl('{Alan} - {value}')` | Şablon: `{Alan}`, `{value}`, `{selected.Yol}` |
|
| `tpl('{Alan} - {value}')` | Şablon: `{Alan}`, `{value}`, `{selected.Yol}` |
|
||||||
|
|
@ -2571,7 +2581,7 @@ Script `AsyncFunction` ile derlenir, aşağıdaki adlar parametre olarak enjekte
|
||||||
| `ask('mesaj')` | `window.confirm`; hayır denirse `revert()` çalışır ve `false` döner |
|
| `ask('mesaj')` | `window.confirm`; hayır denirse `revert()` çalışır ve `false` döner |
|
||||||
| `revert()` | Alanı değişiklik öncesi değerine döndürür (editöre de yazar) |
|
| `revert()` | Alanı değişiklik öncesi değerine döndürür (editöre de yazar) |
|
||||||
| `openUrl('/adres', '_blank')` | Yeni sekme/pencere |
|
| `openUrl('/adres', '_blank')` | Yeni sekme/pencere |
|
||||||
| `await api(url, 'data.name', options?)` | Ham `fetch`. **Kimlik doğrulama başlığı eklemez**; korumalı bir uç için Custom Endpoint tarafında erişim açık olmalıdır |
|
| `await api(url, 'data.name', options?)` | `/api/` ile başlayan uygulama adresi platform istemcisinden gider (oturum + kiracı başlığı; `options.method`/`options.body` taşınır). Dış adres ham `fetch`'tir, başlık eklemez. |
|
||||||
| `await geoTo('Lat', 'Lng', 'Acc'?)` | Cihaz konumunu alanlara yazar. İzin yoksa/okunamazsa alanlara **dokunmaz** ve uyarı gösterir, `false` döner |
|
| `await geoTo('Lat', 'Lng', 'Acc'?)` | Cihaz konumunu alanlara yazar. İzin yoksa/okunamazsa alanlara **dokunmaz** ve uyarı gösterir, `false` döner |
|
||||||
| `$` | Tüm yardımcıların tek nesne hâli |
|
| `$` | Tüm yardımcıların tek nesne hâli |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -947,6 +947,8 @@ kullanıcı (personel) kaydını BT elle açar; İK aday kaydını `UserId` ile
|
||||||
`lowcode-reference.instructions.md` §12.4. **Performans Yönetimi** (`App.Hr.Performance`) wizard +
|
`lowcode-reference.instructions.md` §12.4. **Performans Yönetimi** (`App.Hr.Performance`) wizard +
|
||||||
custom component ile üretilmiştir: İK menüsü şartları ve takibi taşır, çalışana ait listeler menüsüzdür ve
|
custom component ile üretilmiştir: İK menüsü şartları ve takibi taşır, çalışana ait listeler menüsüzdür ve
|
||||||
Intranet panosundaki widget'lardan açılır; çalışma şekli [HrPerformance.md](configs/seeds/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,
|
||||||
|
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).
|
||||||
|
|
||||||
**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:
|
||||||
|
|
@ -1213,6 +1215,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) |
|
||||||
| 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) |
|
||||||
|
|
@ -1303,6 +1306,10 @@ Bildirim **tip + kanal** eşleşmesiyle yönlendirilir. Alıcı hedefleme seçen
|
||||||
`All`, `User`, `Role`, `OrganizationUnit`, `Custom`. Kullanıcılar kendi bildirim tercihlerini
|
`All`, `User`, `Role`, `OrganizationUnit`, `Custom`. Kullanıcılar kendi bildirim tercihlerini
|
||||||
`/admin/profile/notification-settings` üzerinden kanal bazında yönetir.
|
`/admin/profile/notification-settings` üzerinden kanal bazında yönetir.
|
||||||
|
|
||||||
|
Bildirim panelinde, masaüstü bildiriminde ve Activity Log'da başlık kaydın **`Subject`**'idir
|
||||||
|
(`NotificationDto.Subject`; bildirimi yazan prosedür dil anahtarından çevrilmiş metni yazar). Tip adı
|
||||||
|
(`PerformansDurumDegisti` gibi) koddur; yalnız `Subject` boşsa gösterilir.
|
||||||
|
|
||||||
### 13.3. Kayıt durumu: gönderildi → okundu
|
### 13.3. Kayıt durumu: gönderildi → okundu
|
||||||
|
|
||||||
Bir bildirim kaydı iki bayrak taşır ve sıra değişmez: **önce `IsSent`, sonra `IsRead`**.
|
Bir bildirim kaydı iki bayrak taşır ve sıra değişmez: **önce `IsSent`, sonra `IsRead`**.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ public class NotificationDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
public required string NotificationChannel { get; set; }
|
public required string NotificationChannel { get; set; }
|
||||||
public required string NotificationType { get; set; }
|
public required string NotificationType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Bildirimi üreten yerin yazdığı, çevrilmiş başlık; tip adı (ör. PerformansDurumDegisti) kod olduğu için başlık olarak gösterilmez.</summary>
|
||||||
|
public string? Subject { get; set; }
|
||||||
public required string Message { get; set; }
|
public required string Message { get; set; }
|
||||||
public bool IsRead { get; set; }
|
public bool IsRead { get; set; }
|
||||||
public bool IsSent { get; set; }
|
public bool IsSent { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,13 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
private const int CriteriaIdPadding = 3;
|
private const int CriteriaIdPadding = 3;
|
||||||
private const string SystemApprovalDescription = "Sistem tarafından otomatik olarak onaylandı.";
|
private const string SystemApprovalDescription = "Sistem tarafından otomatik olarak onaylandı.";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Düğümün onaycısı bu önekle yazılırsa (<c>@ManagerUserNames</c>) kayıttaki o kolonun değeri
|
||||||
|
/// onaycıdır: onaycı kayda göre değiştiğinde (ör. çalışanın departman müdürü) düğüme sabit
|
||||||
|
/// kullanıcı yazılamaz.
|
||||||
|
/// </summary>
|
||||||
|
private const string RowApproverPrefix = "@";
|
||||||
|
|
||||||
private readonly IRepository<ListFormWorkflow, string> criteriaRepository;
|
private readonly IRepository<ListFormWorkflow, string> criteriaRepository;
|
||||||
private readonly IRepository<Note, Guid> noteRepository;
|
private readonly IRepository<Note, Guid> noteRepository;
|
||||||
private readonly IListFormManager listFormManager;
|
private readonly IListFormManager listFormManager;
|
||||||
|
|
@ -578,7 +585,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
{
|
{
|
||||||
if (!context.Workflow.ApprovalUserFieldName.IsNullOrWhiteSpace())
|
if (!context.Workflow.ApprovalUserFieldName.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
update[context.Workflow.ApprovalUserFieldName] = node.Approver ?? string.Empty;
|
update[context.Workflow.ApprovalUserFieldName] = ResolveNodeApprover(context, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node.Kind == "End")
|
else if (node.Kind == "End")
|
||||||
|
|
@ -614,7 +621,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
|
|
||||||
private async Task SendInformEmailAsync(WorkflowRunContext context, ListFormWorkflow node)
|
private async Task SendInformEmailAsync(WorkflowRunContext context, ListFormWorkflow node)
|
||||||
{
|
{
|
||||||
var recipientEmails = await ResolveApproverEmailsAsync(node.Approver);
|
var recipientEmails = await ResolveApproverEmailsAsync(ResolveNodeApprover(context, node));
|
||||||
var senderName = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName);
|
var senderName = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromDisplayName);
|
||||||
var senderEmail = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromAddress);
|
var senderEmail = await settingProvider.GetOrNullAsync(SeedConsts.AbpSettings.Mailing.Default.DefaultFromAddress);
|
||||||
KeyValuePair<string, string>? sender = null;
|
KeyValuePair<string, string>? sender = null;
|
||||||
|
|
@ -690,7 +697,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
var approverValue = GetRowValue(context.Row, context.Workflow.ApprovalUserFieldName)?.ToString();
|
var approverValue = GetRowValue(context.Row, context.Workflow.ApprovalUserFieldName)?.ToString();
|
||||||
if (approverValue.IsNullOrWhiteSpace())
|
if (approverValue.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
approverValue = current.Approver;
|
approverValue = ResolveNodeApprover(context, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
var approvers = SplitWorkflowApprovers(approverValue)
|
var approvers = SplitWorkflowApprovers(approverValue)
|
||||||
|
|
@ -759,7 +766,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
var keyText = string.Join(", ", context.Keys.Select(key => WebUtility.HtmlEncode(key?.ToString() ?? string.Empty)));
|
var keyText = string.Join(", ", context.Keys.Select(key => WebUtility.HtmlEncode(key?.ToString() ?? string.Empty)));
|
||||||
var listFormCode = WebUtility.HtmlEncode(context.ListFormCode ?? string.Empty);
|
var listFormCode = WebUtility.HtmlEncode(context.ListFormCode ?? string.Empty);
|
||||||
var nodeTitle = WebUtility.HtmlEncode(node.Title ?? string.Empty);
|
var nodeTitle = WebUtility.HtmlEncode(node.Title ?? string.Empty);
|
||||||
var recipient = WebUtility.HtmlEncode(FormatWorkflowApprovers(node.Approver));
|
var recipient = WebUtility.HtmlEncode(FormatWorkflowApprovers(DisplayNodeApprover(context, node)));
|
||||||
var processRows = BuildWorkflowNoteContent(context.WorkflowNoteRows);
|
var processRows = BuildWorkflowNoteContent(context.WorkflowNoteRows);
|
||||||
var previousNotesSection = previousWorkflowNotesHtml.IsNullOrWhiteSpace()
|
var previousNotesSection = previousWorkflowNotesHtml.IsNullOrWhiteSpace()
|
||||||
? string.Empty
|
? string.Empty
|
||||||
|
|
@ -828,7 +835,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
var approverLabel = node.Kind == "Inform"
|
var approverLabel = node.Kind == "Inform"
|
||||||
? NoteLabel("App.WorkflowNote.Inform", "Inform")
|
? NoteLabel("App.WorkflowNote.Inform", "Inform")
|
||||||
: NoteLabel("App.WorkflowNote.Approver", "Approver");
|
: NoteLabel("App.WorkflowNote.Approver", "Approver");
|
||||||
context.WorkflowNoteRows.Add((approverLabel, FormatWorkflowApprovers(node.Approver)));
|
context.WorkflowNoteRows.Add((approverLabel, FormatWorkflowApprovers(DisplayNodeApprover(context, node))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -845,13 +852,13 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
localizer["App.ListFormWorkflow.WorkflowStarted"].Value,
|
localizer["App.ListFormWorkflow.WorkflowStarted"].Value,
|
||||||
localizer["App.ListFormWorkflow.Step", node.Title].Value,
|
localizer["App.ListFormWorkflow.Step", node.Title].Value,
|
||||||
localizer["App.ListFormWorkflow.PerformedBy", userName].Value
|
localizer["App.ListFormWorkflow.PerformedBy", userName].Value
|
||||||
}.Concat(FormatNextToastNode(next)),
|
}.Concat(FormatNextToastNode(context, next)),
|
||||||
"Inform" => new[]
|
"Inform" => new[]
|
||||||
{
|
{
|
||||||
localizer["App.ListFormWorkflow.InformReached"].Value,
|
localizer["App.ListFormWorkflow.InformReached"].Value,
|
||||||
localizer["App.ListFormWorkflow.Step", node.Title].Value,
|
localizer["App.ListFormWorkflow.Step", node.Title].Value,
|
||||||
localizer["App.ListFormWorkflow.InformUser", FormatToastUser(node.Approver)].Value
|
localizer["App.ListFormWorkflow.InformUser", FormatToastUser(DisplayNodeApprover(context, node))].Value
|
||||||
}.Concat(FormatNextToastNode(next)),
|
}.Concat(FormatNextToastNode(context, next)),
|
||||||
"End" => new[]
|
"End" => new[]
|
||||||
{
|
{
|
||||||
localizer["App.ListFormWorkflow.WorkflowCompleted"].Value,
|
localizer["App.ListFormWorkflow.WorkflowCompleted"].Value,
|
||||||
|
|
@ -887,7 +894,7 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<string> FormatNextToastNode(ListFormWorkflow? node)
|
private IEnumerable<string> FormatNextToastNode(WorkflowRunContext context, ListFormWorkflow? node)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
|
|
@ -900,13 +907,13 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
[
|
[
|
||||||
localizer["App.WorkflowNextStep.Approval"].Value,
|
localizer["App.WorkflowNextStep.Approval"].Value,
|
||||||
localizer["App.ListFormWorkflow.NextStepName", node.Title].Value,
|
localizer["App.ListFormWorkflow.NextStepName", node.Title].Value,
|
||||||
localizer["App.ListFormWorkflow.ApproverUser", FormatToastUser(node.Approver)].Value
|
localizer["App.ListFormWorkflow.ApproverUser", FormatToastUser(DisplayNodeApprover(context, node))].Value
|
||||||
],
|
],
|
||||||
"Inform" =>
|
"Inform" =>
|
||||||
[
|
[
|
||||||
localizer["App.WorkflowNextStep.Inform"].Value,
|
localizer["App.WorkflowNextStep.Inform"].Value,
|
||||||
localizer["App.ListFormWorkflow.NextStepName", node.Title].Value,
|
localizer["App.ListFormWorkflow.NextStepName", node.Title].Value,
|
||||||
localizer["App.ListFormWorkflow.InformUser", FormatToastUser(node.Approver)].Value
|
localizer["App.ListFormWorkflow.InformUser", FormatToastUser(DisplayNodeApprover(context, node))].Value
|
||||||
],
|
],
|
||||||
"End" =>
|
"End" =>
|
||||||
[
|
[
|
||||||
|
|
@ -924,6 +931,41 @@ public class ListFormWorkflowAppService : PlatformAppService, IListFormWorkflowA
|
||||||
: FormatWorkflowApprovers(userName);
|
: FormatWorkflowApprovers(userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Onay ve bilgilendirme için düğümün onaycısı. <see cref="RowApproverPrefix"/> ile yazılmış
|
||||||
|
/// onaycı kayıttan okunur; boş kalırsa akış durur — boş onaycı herkese onay yetkisi verirdi.
|
||||||
|
/// </summary>
|
||||||
|
private static string ResolveNodeApprover(WorkflowRunContext context, ListFormWorkflow node)
|
||||||
|
{
|
||||||
|
var approver = node.Approver?.Trim() ?? string.Empty;
|
||||||
|
if (!approver.StartsWith(RowApproverPrefix, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return approver;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldName = approver[RowApproverPrefix.Length..];
|
||||||
|
var value = GetRowValue(context.Row, fieldName)?.ToString();
|
||||||
|
if (value.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new UserFriendlyException($"Workflow onaycısı kayıttaki '{fieldName}' alanından okunamadı; alan boş.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Not ve bildirim metinleri için onaycı; kayıttan okunamazsa alan adı gösterilir.</summary>
|
||||||
|
private static string DisplayNodeApprover(WorkflowRunContext context, ListFormWorkflow node)
|
||||||
|
{
|
||||||
|
var approver = node.Approver?.Trim() ?? string.Empty;
|
||||||
|
if (!approver.StartsWith(RowApproverPrefix, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return approver;
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = GetRowValue(context.Row, approver[RowApproverPrefix.Length..])?.ToString();
|
||||||
|
return value.IsNullOrWhiteSpace() ? approver : value;
|
||||||
|
}
|
||||||
|
|
||||||
private static string FormatWorkflowApprovers(string value)
|
private static string FormatWorkflowApprovers(string value)
|
||||||
{
|
{
|
||||||
return string.Join(", ", SplitWorkflowApprovers(value));
|
return string.Join(", ", SplitWorkflowApprovers(value));
|
||||||
|
|
|
||||||
|
|
@ -4458,6 +4458,14 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
||||||
PagerOptionJson = DefaultPagerOptionJson,
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
|
// Istirahat ile Izin Yonetimi'ndeki rapor talebi tek kayittir (Hr_S_LeaveSickLeaveSync).
|
||||||
|
UpdateFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] {
|
||||||
|
new() { FieldName = "LastModificationTime", FieldDbType = DbType.DateTime, Value = "@NOW", CustomValueType = FieldCustomValueTypeEnum.CustomKey },
|
||||||
|
new() { FieldName = "LastModifierId", FieldDbType = DbType.Guid, Value = "@USERID", CustomValueType = FieldCustomValueTypeEnum.CustomKey }
|
||||||
|
}),
|
||||||
|
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",
|
||||||
|
DeleteAfterCommand = "UPDATE Hr_T_LeaveRequest SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId WHERE SickLeaveId IN @Id AND IsDeleted = 0",
|
||||||
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>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11203,6 +11203,526 @@
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Hr"
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.Leave",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Hr.Leave",
|
||||||
|
"Order": 24,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest",
|
||||||
|
"ParentName": "App.Hr.Leave",
|
||||||
|
"DisplayName": "App.Hr.LeaveRequest",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Create",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Update",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Delete",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Export",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Import",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveRequest.Note",
|
||||||
|
"ParentName": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance",
|
||||||
|
"ParentName": "App.Hr.Leave",
|
||||||
|
"DisplayName": "App.Hr.LeaveBalance",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Create",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Update",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Delete",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Export",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Import",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalance.Note",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"Order": 7,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Create",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Update",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Delete",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Export",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Import",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceAdjustment.Note",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceAdjustment",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear",
|
||||||
|
"ParentName": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"Order": 8,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Create",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Update",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Delete",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Export",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Import",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.LeaveBalanceYear.Note",
|
||||||
|
"ParentName": "App.Hr.LeaveBalanceYear",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Hr.MyLeaveRequest",
|
||||||
|
"Order": 25,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Create",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Update",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Delete",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Export",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Import",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveRequest.Note",
|
||||||
|
"ParentName": "App.Hr.MyLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Hr.MyLeaveBalance",
|
||||||
|
"Order": 26,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Create",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Update",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Delete",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Export",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Import",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.MyLeaveBalance.Note",
|
||||||
|
"ParentName": "App.Hr.MyLeaveBalance",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"Order": 27,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Create",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Update",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Delete",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Export",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Import",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Import",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Hr",
|
||||||
|
"Name": "App.Hr.TeamLeaveRequest.Note",
|
||||||
|
"ParentName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"DisplayName": "App.Platform.Note",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.HrSettings",
|
||||||
|
"ParentName": "App.Setting",
|
||||||
|
"DisplayName": "App.HrSettings",
|
||||||
|
"Order": 6,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.HrSettings.Leave",
|
||||||
|
"ParentName": "App.HrSettings",
|
||||||
|
"DisplayName": "App.HrSettings.Leave",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Hr"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"ListFormCode": "App.DeveloperKit.CustomComponents",
|
||||||
|
"KeyFieldName": "Id",
|
||||||
|
"GeneratedAt": "2026-10-04T15:00:00Z",
|
||||||
|
"Order": 0,
|
||||||
|
"Rows": [
|
||||||
|
{
|
||||||
|
"Id": "3b7b16c6-aa96-5765-8e19-fe5e727feb52",
|
||||||
|
"Name": "TeamLeaveWidget",
|
||||||
|
"RoutePath": null,
|
||||||
|
"Description": "Intranet panosu: departman müdürünün onayını bekleyen izin talepleri ve bugün izinde olanlar",
|
||||||
|
"IsActive": true,
|
||||||
|
"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",
|
||||||
|
"Props": null,
|
||||||
|
"DataSources": [],
|
||||||
|
"SeoTitle": null,
|
||||||
|
"SeoDescription": null,
|
||||||
|
"SeoKeywords": null,
|
||||||
|
"SeoOgImage": null,
|
||||||
|
"SeoCanonicalUrl": null,
|
||||||
|
"SeoNoIndex": true,
|
||||||
|
"SeoIncludeInSitemap": false,
|
||||||
|
"SeoChangeFrequency": null,
|
||||||
|
"SeoPriority": null,
|
||||||
|
"SeoStructuredData": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -119,6 +119,32 @@
|
||||||
"Order": 90,
|
"Order": 90,
|
||||||
"Props": "",
|
"Props": "",
|
||||||
"IsActive": true
|
"IsActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "d031eff6-1e6e-5925-aa57-32b4f6da6136",
|
||||||
|
"Code": "my-leave",
|
||||||
|
"Name": "My Leaves",
|
||||||
|
"LabelKey": "App.DashboardWidget.MyLeave",
|
||||||
|
"SourceType": 1,
|
||||||
|
"ComponentName": "MyLeaveWidget",
|
||||||
|
"PermissionName": "App.Hr.MyLeaveRequest",
|
||||||
|
"Column": 0,
|
||||||
|
"Order": 35,
|
||||||
|
"Props": "",
|
||||||
|
"IsActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "69e495dc-f46e-5a77-b674-8a9d1b18c850",
|
||||||
|
"Code": "team-leave",
|
||||||
|
"Name": "Team Leaves",
|
||||||
|
"LabelKey": "App.DashboardWidget.TeamLeave",
|
||||||
|
"SourceType": 1,
|
||||||
|
"ComponentName": "TeamLeaveWidget",
|
||||||
|
"PermissionName": "App.Hr.TeamLeaveRequest",
|
||||||
|
"Column": 0,
|
||||||
|
"Order": 36,
|
||||||
|
"Props": "",
|
||||||
|
"IsActive": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
"DeductsFromAnnualLeave": true,
|
"DeductsFromAnnualLeave": true,
|
||||||
"RequiresDocument": false,
|
"RequiresDocument": false,
|
||||||
"AllowHalfDay": true,
|
"AllowHalfDay": true,
|
||||||
|
"BalanceExceedAction": "Block",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "08615087-48ee-5cc2-b32b-1178fff77593"
|
"Id": "08615087-48ee-5cc2-b32b-1178fff77593"
|
||||||
},
|
},
|
||||||
|
|
@ -25,6 +26,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": false,
|
"RequiresDocument": false,
|
||||||
"AllowHalfDay": true,
|
"AllowHalfDay": true,
|
||||||
|
"BalanceExceedAction": "Warn",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "986f9678-1b46-5197-844d-16bf772a343a"
|
"Id": "986f9678-1b46-5197-844d-16bf772a343a"
|
||||||
},
|
},
|
||||||
|
|
@ -37,6 +39,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": false,
|
"RequiresDocument": false,
|
||||||
"AllowHalfDay": true,
|
"AllowHalfDay": true,
|
||||||
|
"BalanceExceedAction": "Warn",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "030adbff-8bff-51ac-8cc0-07496a616c91"
|
"Id": "030adbff-8bff-51ac-8cc0-07496a616c91"
|
||||||
},
|
},
|
||||||
|
|
@ -49,6 +52,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": true,
|
"RequiresDocument": true,
|
||||||
"AllowHalfDay": false,
|
"AllowHalfDay": false,
|
||||||
|
"BalanceExceedAction": "Warn",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "3b82ab6e-d846-583d-afc6-59cc97ba4a21"
|
"Id": "3b82ab6e-d846-583d-afc6-59cc97ba4a21"
|
||||||
},
|
},
|
||||||
|
|
@ -61,6 +65,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": true,
|
"RequiresDocument": true,
|
||||||
"AllowHalfDay": false,
|
"AllowHalfDay": false,
|
||||||
|
"BalanceExceedAction": "Block",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "7e391128-01b3-58a3-911a-fc300960ae2b"
|
"Id": "7e391128-01b3-58a3-911a-fc300960ae2b"
|
||||||
},
|
},
|
||||||
|
|
@ -73,6 +78,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": true,
|
"RequiresDocument": true,
|
||||||
"AllowHalfDay": false,
|
"AllowHalfDay": false,
|
||||||
|
"BalanceExceedAction": "Block",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "2caac0cf-91b9-5693-bb30-dcfca42e33c9"
|
"Id": "2caac0cf-91b9-5693-bb30-dcfca42e33c9"
|
||||||
},
|
},
|
||||||
|
|
@ -85,6 +91,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": true,
|
"RequiresDocument": true,
|
||||||
"AllowHalfDay": false,
|
"AllowHalfDay": false,
|
||||||
|
"BalanceExceedAction": "Block",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "b744305a-d519-5b6a-8bfe-f7dae3d7c76f"
|
"Id": "b744305a-d519-5b6a-8bfe-f7dae3d7c76f"
|
||||||
},
|
},
|
||||||
|
|
@ -97,6 +104,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": true,
|
"RequiresDocument": true,
|
||||||
"AllowHalfDay": false,
|
"AllowHalfDay": false,
|
||||||
|
"BalanceExceedAction": "Block",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "5f61e945-848b-57ab-a266-9b3ef76b58b5"
|
"Id": "5f61e945-848b-57ab-a266-9b3ef76b58b5"
|
||||||
},
|
},
|
||||||
|
|
@ -109,6 +117,7 @@
|
||||||
"DeductsFromAnnualLeave": false,
|
"DeductsFromAnnualLeave": false,
|
||||||
"RequiresDocument": false,
|
"RequiresDocument": false,
|
||||||
"AllowHalfDay": true,
|
"AllowHalfDay": true,
|
||||||
|
"BalanceExceedAction": "Warn",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Id": "77df8125-8af7-5d2e-89b3-084e23d5a4e8"
|
"Id": "77df8125-8af7-5d2e-89b3-084e23d5a4e8"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2163,6 +2163,51 @@
|
||||||
"IsDisabled": false,
|
"IsDisabled": false,
|
||||||
"ElementId": null,
|
"ElementId": null,
|
||||||
"ModuleId": "Hr"
|
"ModuleId": "Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "c3ac8beb-302f-5285-89a5-9c98d2f19524",
|
||||||
|
"Code": "App.Hr.Leave",
|
||||||
|
"DisplayName": "App.Hr.Leave",
|
||||||
|
"Order": 14,
|
||||||
|
"Url": null,
|
||||||
|
"Icon": "FcOvertime",
|
||||||
|
"ParentCode": "App.Hr",
|
||||||
|
"RequiredPermissionName": null,
|
||||||
|
"CssClass": null,
|
||||||
|
"Target": null,
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ElementId": null,
|
||||||
|
"ModuleId": "Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "635e0daa-53c5-5956-91a4-a17d581a97d7",
|
||||||
|
"Code": "App.Hr.LeaveRequest",
|
||||||
|
"DisplayName": "App.Hr.LeaveRequest",
|
||||||
|
"Order": 1,
|
||||||
|
"Url": "/admin/list/App.Hr.LeaveRequest",
|
||||||
|
"Icon": "FcLeave",
|
||||||
|
"ParentCode": "App.Hr.Leave",
|
||||||
|
"RequiredPermissionName": "App.Hr.LeaveRequest",
|
||||||
|
"CssClass": null,
|
||||||
|
"Target": null,
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ElementId": null,
|
||||||
|
"ModuleId": "Hr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "4a7c4fd7-ce42-5cef-bd64-f2eeb9dd188f",
|
||||||
|
"Code": "App.Hr.LeaveBalance",
|
||||||
|
"DisplayName": "App.Hr.LeaveBalance",
|
||||||
|
"Order": 2,
|
||||||
|
"Url": "/admin/list/App.Hr.LeaveBalance",
|
||||||
|
"Icon": "FcComboChart",
|
||||||
|
"ParentCode": "App.Hr.Leave",
|
||||||
|
"RequiredPermissionName": "App.Hr.LeaveBalance",
|
||||||
|
"CssClass": null,
|
||||||
|
"Target": null,
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ElementId": null,
|
||||||
|
"ModuleId": "Hr"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,46 @@
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"IsFixed": false,
|
"IsFixed": false,
|
||||||
"IsCustomized": false
|
"IsCustomized": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "6da9cf5c-1b30-5905-977a-5a27410c63d8",
|
||||||
|
"NotificationTypeId": "92cb441c-3ce9-5e6d-a34e-d281260374c3",
|
||||||
|
"RecipientType": "Custom",
|
||||||
|
"RecipientId": null,
|
||||||
|
"Channel": "UiActivity",
|
||||||
|
"IsActive": true,
|
||||||
|
"IsFixed": false,
|
||||||
|
"IsCustomized": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "de9aa39f-c642-5886-9638-8149125cddc1",
|
||||||
|
"NotificationTypeId": "92cb441c-3ce9-5e6d-a34e-d281260374c3",
|
||||||
|
"RecipientType": "Custom",
|
||||||
|
"RecipientId": null,
|
||||||
|
"Channel": "UiToast",
|
||||||
|
"IsActive": true,
|
||||||
|
"IsFixed": false,
|
||||||
|
"IsCustomized": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "ced331bb-92a9-5f72-b311-3e1a185852ac",
|
||||||
|
"NotificationTypeId": "7ea2271f-e71c-5b63-8826-9df5e632eb4b",
|
||||||
|
"RecipientType": "Custom",
|
||||||
|
"RecipientId": null,
|
||||||
|
"Channel": "UiActivity",
|
||||||
|
"IsActive": true,
|
||||||
|
"IsFixed": false,
|
||||||
|
"IsCustomized": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "4b1d2769-7073-550d-85a9-b391668bf51e",
|
||||||
|
"NotificationTypeId": "7ea2271f-e71c-5b63-8826-9df5e632eb4b",
|
||||||
|
"RecipientType": "Custom",
|
||||||
|
"RecipientId": null,
|
||||||
|
"Channel": "UiToast",
|
||||||
|
"IsActive": true,
|
||||||
|
"IsFixed": false,
|
||||||
|
"IsCustomized": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,16 @@
|
||||||
"Id": "cd6e4aed-f460-5af3-ab18-c3baa33a0a03",
|
"Id": "cd6e4aed-f460-5af3-ab18-c3baa33a0a03",
|
||||||
"Name": "Performans360Talebi",
|
"Name": "Performans360Talebi",
|
||||||
"Description": "Bir değerlendirmeye 360 derece değerlendirici eklendiğinde değerlendiriciye gider. Alıcı geri bildirim kaydındaki değerlendiricidir; bu tipin Custom kuralları yalnızca kanalı belirler (Hr_S_PerformanceFeedbackOpen yazar)."
|
"Description": "Bir değerlendirmeye 360 derece değerlendirici eklendiğinde değerlendiriciye gider. Alıcı geri bildirim kaydındaki değerlendiricidir; bu tipin Custom kuralları yalnızca kanalı belirler (Hr_S_PerformanceFeedbackOpen yazar)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "92cb441c-3ce9-5e6d-a34e-d281260374c3",
|
||||||
|
"Name": "IzinTalebiOnayBekliyor",
|
||||||
|
"Description": "İzin talebi müdür onayına ya da İK onayına geldiğinde sıradaki onaycıya gider (müdür: çalışanın departman müdürü, İK: İzin Talepleri akışının İK Onayı düğümü). Alıcı talepten gelir; bu tipin Custom kuralları yalnızca kanalı belirler (Hr_S_LeaveRequestAfterSave yazar)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "7ea2271f-e71c-5b63-8826-9df5e632eb4b",
|
||||||
|
"Name": "IzinTalebiSonuclandi",
|
||||||
|
"Description": "İzin talebi onaylandığında ya da reddedildiğinde talep sahibi çalışana gider. Alıcı talepten gelir; bu tipin Custom kuralları yalnızca kanalı belirler (Hr_S_LeaveRequestAfterSave yazar)."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1226,6 +1226,193 @@
|
||||||
"IsVisibleToClients": false,
|
"IsVisibleToClients": false,
|
||||||
"IsInherited": false,
|
"IsInherited": false,
|
||||||
"IsEncrypted": false
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "cd6af2de-ef79-5a19-a6c0-5f4a55049d19",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkMonday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 94,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkMonday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "True",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "87448fd3-70d9-509c-9834-fc2e3f90bb70",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkTuesday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 95,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkTuesday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "True",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "12157e82-3279-5749-a707-d9eca903ab58",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkWednesday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 96,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkWednesday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "True",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "78398216-592a-5c8c-bedb-96728413c324",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkThursday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 97,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkThursday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "True",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "9280bf63-43c3-5068-8b2e-18029b5da547",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkFriday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 98,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkFriday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "True",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "667c825b-e7d2-5c63-9aa3-8e7dba200d69",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkSaturday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 99,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkSaturday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "False",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "8e4f2daa-771f-54e9-9d2e-01bb2a06c4a9",
|
||||||
|
"Code": "App.HrSettings.Leave.WorkSunday",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 100,
|
||||||
|
"NameKey": "App.HrSettings.Leave.WorkSunday",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.WorkDay.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "False",
|
||||||
|
"DataType": "Bool",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "efae6640-7a65-5c87-baeb-a1c019248c89",
|
||||||
|
"Code": "App.HrSettings.Leave.AnnualDays1To5",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 101,
|
||||||
|
"NameKey": "App.HrSettings.Leave.AnnualDays1To5",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.AnnualDays1To5.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "14",
|
||||||
|
"DataType": "Number",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "56518255-d95f-51c5-a5a5-aeb079f98059",
|
||||||
|
"Code": "App.HrSettings.Leave.AnnualDays5To15",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 102,
|
||||||
|
"NameKey": "App.HrSettings.Leave.AnnualDays5To15",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.AnnualDays5To15.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "20",
|
||||||
|
"DataType": "Number",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "3c2df0c4-e64b-5264-95f6-d35208e90444",
|
||||||
|
"Code": "App.HrSettings.Leave.AnnualDays15Plus",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 103,
|
||||||
|
"NameKey": "App.HrSettings.Leave.AnnualDays15Plus",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.AnnualDays15Plus.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "26",
|
||||||
|
"DataType": "Number",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "649eb63e-98a7-5fcc-85c5-082580d4825c",
|
||||||
|
"Code": "App.HrSettings.Leave.MinDaysYoungOld",
|
||||||
|
"MainGroupKey": "App.HrSettings",
|
||||||
|
"SubGroupKey": "App.HrSettings.Leave",
|
||||||
|
"Order": 104,
|
||||||
|
"NameKey": "App.HrSettings.Leave.MinDaysYoungOld",
|
||||||
|
"DescriptionKey": "App.HrSettings.Leave.MinDaysYoungOld.Description",
|
||||||
|
"RequiredPermissionName": "App.HrSettings.Leave",
|
||||||
|
"Providers": "T|G|D",
|
||||||
|
"DefaultValue": "20",
|
||||||
|
"DataType": "Number",
|
||||||
|
"SelectOptions": "{}",
|
||||||
|
"IsVisibleToClients": false,
|
||||||
|
"IsInherited": false,
|
||||||
|
"IsEncrypted": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ Hepsi Grid, Card, Pivot, Chart görünümlüdür.
|
||||||
| Hastaneler | Kurum adı*, aktif | Toplam · Aktif · Pasif | 45 |
|
| Hastaneler | Kurum adı*, aktif | Toplam · Aktif · Pasif | 45 |
|
||||||
| Hastane Bölümleri | Bölüm adı*, aktif | Toplam · Aktif · Pasif | 31 |
|
| Hastane Bölümleri | Bölüm adı*, aktif | Toplam · Aktif · Pasif | 31 |
|
||||||
| Evrak Türleri | Dosya grubu* (Genel / Özlük Evrakları / Sağlık), dosya türü*, zorunlu, aktif | Toplam · Aktif · Pasif · Zorunlu | 48 |
|
| Evrak Türleri | Dosya grubu* (Genel / Özlük Evrakları / Sağlık), dosya türü*, zorunlu, aktif | Toplam · Aktif · Pasif · Zorunlu | 48 |
|
||||||
| İzin Türleri | Kod*, ad*, cinsiyet* (All/Male/Female), yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün kullanılabilir, aktif | Toplam · Ücretli · Ücretsiz | 9 (Yıllık, Mazeret, Ücretsiz, Hastalık, Doğum 112 gün, Babalık 5, Evlilik 3, Ölüm 3, Süt) |
|
| İzin Türleri | Kod*, ad*, cinsiyet* (All/Male/Female), yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün kullanılabilir, bakiye aşılırsa (Engelle/Uyar), aktif | Toplam · Ücretli · Ücretsiz | 9 (Yıllık, Mazeret, Ücretsiz, Hastalık, Doğum 112 gün, Babalık 5, Evlilik 3, Ölüm 3, Süt) |
|
||||||
| Masraf Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, fiş/belge gerekir, aktif | Toplam · Aktif · Pasif | 7 (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) |
|
| Masraf Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, fiş/belge gerekir, aktif | Toplam · Aktif · Pasif | 7 (yemek, yol, konaklama, akaryakıt, telefon, temsil, kırtasiye) |
|
||||||
| Yan Hak Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, aktif | Toplam · Aktif · Pasif | 10 (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk, yakacak, diğer) |
|
| Yan Hak Türleri | Kod*, ad*, varsayılan tutar, para birimi, gelir vergisine tabi, SGK'ya tabi, aktif | Toplam · Aktif · Pasif | 10 (yemek kartı, ulaşım, özel sağlık sigortası, BES, konut, şirket aracı, telefon, çocuk, yakacak, diğer) |
|
||||||
|
|
||||||
|
|
@ -103,7 +103,8 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
|
||||||
| Yeterlilik Belgeleri | Kullanıcı detayı › Eğitim ve Yetkinlik (`UserCertificate`), Performans gelişim planı (sertifika aksiyonu) |
|
| Yeterlilik Belgeleri | Kullanıcı detayı › Eğitim ve Yetkinlik (`UserCertificate`), Performans gelişim planı (sertifika aksiyonu) |
|
||||||
| Evrak Türleri | Eğitim dosyaları, Disiplin belgeleri |
|
| Evrak Türleri | Eğitim dosyaları, Disiplin belgeleri |
|
||||||
| Yan Hak Türleri | İşe Alım › Teklif (`BenefitCodes`, kod ile) |
|
| Yan Hak Türleri | İşe Alım › Teklif (`BenefitCodes`, kod ile) |
|
||||||
| Hastaneler, Hastane Bölümleri, İzin Türleri, Masraf Türleri | Henüz kullanan ekran yok |
|
| İzin Türleri | İzin Yönetimi'nin tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı); `Sick` kodlu tür Sağlık Kartı istirahatiyle eşlenir — `HrLeave.md` |
|
||||||
|
| Hastaneler, Hastane Bölümleri, Masraf Türleri | Henüz kullanan ekran yok |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -269,7 +270,7 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
|
||||||
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||||
| Kapsam | Kiracı |
|
| Kapsam | Kiracı |
|
||||||
| Widget'lar | `App.Widget.Total`, `App.Widget.Paid`, `App.Widget.Unpaid` |
|
| 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 |
|
| Form varsayılanları | IsPaid=true, DeductsFromAnnualLeave=false, RequiresDocument=false, AllowHalfDay=false, Gender=All, IsActive=true, BalanceExceedAction=Block |
|
||||||
| Veri aynası | `data/App.Hr.LeaveType.json` |
|
| Veri aynası | `data/App.Hr.LeaveType.json` |
|
||||||
|
|
||||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
|
@ -282,6 +283,7 @@ lookup olarak okunmaları ekran yetkisi gerektirmez. Hiçbir yetki role otomatik
|
||||||
| `DeductsFromAnnualLeave` | Yıllık İzinden Düşer | dxCheckBox | ✓ | ✓ | |
|
| `DeductsFromAnnualLeave` | Yıllık İzinden Düşer | dxCheckBox | ✓ | ✓ | |
|
||||||
| `RequiresDocument` | Belge Gerekir | dxCheckBox | ✓ | ✓ | |
|
| `RequiresDocument` | Belge Gerekir | dxCheckBox | ✓ | ✓ | |
|
||||||
| `AllowHalfDay` | Yarım Gün Kullanılabilir | dxCheckBox | ✓ | ✓ | |
|
| `AllowHalfDay` | Yarım Gün Kullanılabilir | dxCheckBox | ✓ | ✓ | |
|
||||||
|
| `BalanceExceedAction` | Bakiye Aşılırsa | dxRadioGroup | ✓ | ✓ | liste: Block, Warn |
|
||||||
| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | |
|
| `IsActive` | Aktif | dxCheckBox | ✓ | ✓ | |
|
||||||
|
|
||||||
### Masraf Türleri — `App.Hr.ExpenseType`
|
### Masraf Türleri — `App.Hr.ExpenseType`
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ Kapsam: kiracı. Liste, kiracının **tüm kullanıcılarıdır** (aktif/pasif);
|
||||||
| Sonuç | `App.Hr.HealthCardResult` | `AbpUsers` | `Id → Id` | Yalnız güncelleme |
|
| Sonuç | `App.Hr.HealthCardResult` | `AbpUsers` | `Id → Id` | Yalnız güncelleme |
|
||||||
| Periyodik Muayeneler | `App.Hr.HealthCardPeriodicExamination` | `Adm_T_UserPeriodicExamination` | `Id → UserId` | Ekle/düzenle/sil |
|
| Periyodik Muayeneler | `App.Hr.HealthCardPeriodicExamination` | `Adm_T_UserPeriodicExamination` | `Id → UserId` | Ekle/düzenle/sil |
|
||||||
| Hasta Protokol Defteri | `App.Hr.HealthCardPatientProtocol` | `Adm_T_UserPatientProtocol` | `Id → UserId` | Ekle/düzenle/sil |
|
| Hasta Protokol Defteri | `App.Hr.HealthCardPatientProtocol` | `Adm_T_UserPatientProtocol` | `Id → UserId` | Ekle/düzenle/sil |
|
||||||
| İstirahat Raporları | `App.Hr.HealthCardSickLeave` | `Adm_T_UserSickLeave` | `Id → UserId` | Ekle/düzenle/sil |
|
| İstirahat Raporları | `App.Hr.HealthCardSickLeave` | `Adm_T_UserSickLeave` | `Id → UserId` | Ekle/düzenle/sil; kayıt sonrası İzin Yönetimi'ne eşlenir (`HrLeave.md` §5.5) |
|
||||||
|
|
||||||
Widget'lar (liste): Toplam · Aktif · Pasif kullanıcı.
|
Widget'lar (liste): Toplam · Aktif · Pasif kullanıcı.
|
||||||
|
|
||||||
|
|
@ -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 izin bakiyesine yansıyor mu?** Hayır; izin modülü yoktur (İzin Türleri yalnız tanımdır).
|
**İ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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -414,6 +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 |
|
||||||
|
|
||||||
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ Pano kutuları (seed):
|
||||||
| `today-birthdays` | Sol / 10 | `AbpIdentity.Users.Widget` | Bugün doğanlar: avatar, ad, yaş, departman |
|
| `today-birthdays` | Sol / 10 | `AbpIdentity.Users.Widget` | Bugün doğanlar: avatar, ad, yaş, departman |
|
||||||
| `documents` | Sol / 20 | `App.Files.Widget` | Yayındaki ilk 3 doküman (tür, boyut, tarih, indir) |
|
| `documents` | Sol / 20 | `App.Files.Widget` | Yayındaki ilk 3 doküman (tür, boyut, tarih, indir) |
|
||||||
| `active-surveys` | Sol / 30 | `App.Hr.Intranet.Survey.Widget` | Aktif anketler (kalan gün, soru/yanıt sayısı, doldurdum/doldur) |
|
| `active-surveys` | Sol / 30 | `App.Hr.Intranet.Survey.Widget` | Aktif anketler (kalan gün, soru/yanıt sayısı, doldurdum/doldur) |
|
||||||
|
| `my-leave` | Sol / 35 | `App.Hr.MyLeaveRequest` | Custom `MyLeaveWidget`: izin bakiyesi, süren talepler → İzin Talebi Oluştur · Taleplerim · Bakiyem |
|
||||||
|
| `team-leave` | Sol / 36 | `App.Hr.TeamLeaveRequest` | Custom `TeamLeaveWidget`: müdürün onayını bekleyen izin talepleri, bugün izinde olanlar → Onay Bekleyenler |
|
||||||
| `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 |
|
||||||
|
|
@ -81,7 +83,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`). 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), 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.
|
||||||
|
|
||||||
|
|
|
||||||
586
configs/seeds/host/docs/modules/HrLeave.md
Normal file
586
configs/seeds/host/docs/modules/HrLeave.md
Normal file
|
|
@ -0,0 +1,586 @@
|
||||||
|
# İK › İzin Yönetimi (`App.Hr.Leave`)
|
||||||
|
|
||||||
|
İzin talebi, iki aşamalı onay (departman müdürü → İK), yıllık izin bakiyesi ve rapor (istirahat)
|
||||||
|
eşlemesi. **İnsan Kaynakları menüsü yalnız İK içindir**: tüm talepleri ve bakiyeleri İK izler.
|
||||||
|
Çalışan ve müdür izinle ilgili her şeyi **Intranet › Dashboard**'daki widget'lardan yapar. Wizard
|
||||||
|
ekranları, SQL nesneleri ve custom component widget'larıyla kuruludur. Çerçeve dışında iki ek
|
||||||
|
vardır (kullanıcı onayıyla): Grid Workflow'da kayıttan okunan onaycı (`@Kolon`) ve kullanıcı
|
||||||
|
detayındaki **İzinler** sekmesi.
|
||||||
|
|
||||||
|
> Bu doküman modülün tek "nasıl çalışır" kaynağıdır. Modülde yapılan her değişiklik aynı commit'te
|
||||||
|
> buraya yansır (`lowcode.instructions.md` §0.13).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Amaç ve kapsam
|
||||||
|
|
||||||
|
| Persona | Ne yapar | Ekran |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Çalışan | Bakiyesini izler, izin talebi açar, taleplerinin onay durumunu takip eder, henüz karar verilmemiş talebini düzeltir/siler | Intranet panosu: **İzinlerim** widget'ı → İzin Talebi Oluştur · Taleplerim · Bakiyem |
|
||||||
|
| Departman müdürü | Departmanının taleplerini onaylar/reddeder | Intranet panosu: **Ekibimin İzinleri** widget'ı → Ekibimin İzin Talepleri |
|
||||||
|
| İK | Tüm talepleri izler, ikinci onayı verir, çalışan adına talep girer, bakiyeleri izler, açılış/devir düzeltmesi girer, çalışma günlerini ve kademeleri ayarlar | İK › İzin Yönetimi › İzin Talepleri · İzin Bakiyeleri · Ayarlar › İnsan Kaynakları › İzin · Kullanıcı detayı › İzinler |
|
||||||
|
| Sağlık birimi | Raporu Sağlık Kartı'na girer; kayıt izin listesine onaylı düşer | İK › Sağlık Kartları › İstirahat Raporları |
|
||||||
|
|
||||||
|
Kapsam: kiracı (`IsTenant`). Şube kırılımı yoktur.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Analiz ve kararlar
|
||||||
|
|
||||||
|
### 2.1 Talep
|
||||||
|
|
||||||
|
> İnsan Kaynakları › İzin Yönetimi. Kullanıcı Intranet Dashboard'dan kendi bakiye raporunu izler,
|
||||||
|
> izin talebi oluşturur, bir butonla taleplerini ve onay durumlarını takip eder (Performansım
|
||||||
|
> widget'ındaki Değerlendirmelerim gibi). İzin türüne göre gerekli alanlar doldurulur; bakiye
|
||||||
|
> yetmezse talep engellenir veya uyarı verilir; aynı tarihlerde çakışan talep oluşturulamaz.
|
||||||
|
> Sağlık Kartı › İstirahatler ile Rapor türündeki izin tek kayıttır. İzin bakiyesi kullanıcı
|
||||||
|
> kartında gösterilir. Alanlar: izin türü, başlangıç/bitiş tarihi ve saati, yarım gün, gün sayısı
|
||||||
|
> (otomatik), açıklama, ek belge, durum. Yıllık hak çalışma yılına göre hesaplanır. Onay önce
|
||||||
|
> departman müdürü (İş Pozisyonları'ndaki departman müdürü), sonra İK. Talep gelince yöneticiye
|
||||||
|
> bildirim gider. İK menüsü yalnız İK kullanır; widget'lar Aktif Anketler'in altına (sol kolon).
|
||||||
|
|
||||||
|
### 2.2 Depodan okunanlar (sorulmadı)
|
||||||
|
|
||||||
|
- İzin türleri `Hr_T_LeaveType` (İK › Tanımlamalar): cinsiyet, yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün.
|
||||||
|
- Rapor kayıtları `Adm_T_UserSickLeave`; iki ekran kullanır: Sağlık Kartı (`App.Hr.HealthCardSickLeave`) ve kullanıcı detayı (`App.IdentityManagement.UserSickLeave`).
|
||||||
|
- Kıdem `AbpUsers.SeniorityStartDate` (boşsa `HireDate`), doğum `BirthDate`, cinsiyet `Gender`, departman/pozisyon `DepartmentId`/`JobPositionId`.
|
||||||
|
- Tatiller `Hr_T_WorkCalendar` (`Holiday` / `HalfDay`, `FREQ=YEARLY` tekrar).
|
||||||
|
- Pozisyon ağacı `Hr_T_JobPosition` (`DepartmentId` + `ParentId`); departmanda "müdür" alanı yoktur.
|
||||||
|
- Grid Workflow onaycıyı düğümde sabit tutuyordu — kayda göre değişen müdür için motor eki gerekti.
|
||||||
|
|
||||||
|
### 2.3 Keşif turu cevapları
|
||||||
|
|
||||||
|
| # | Soru | Seçilen |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 1 | Onay akışı | Grid Workflow + motor eki: düğüm onaycısı `@Kolon` ise kayıttan okunur |
|
||||||
|
| 2 | Müdür nasıl bulunur | Departmanın en üst pozisyonu (üst pozisyonu başka departmanda ya da üstü olmayan); çalışan o pozisyondaysa bir üst pozisyonun sahibi; birden çok müdür varsa herhangi biri |
|
||||||
|
| 3 | Yıllık hak | İş Kanunu md.53 kademeleri + devir (kullanılmayan izin devreder) |
|
||||||
|
| 4 | Bakiye yetersiz | İzin türü bazında İK seçer: `BalanceExceedAction` = Engelle / Uyar ve kaydet |
|
||||||
|
| 5 | İK onaycısı | Düğümde sabit kullanıcı(lar) (İzin Talepleri akışının "İK Onayı" düğümü) |
|
||||||
|
| 6 | Gün sayısı | Ayarlar › İnsan Kaynakları › İzin'deki çalışma günleri + Çalışma Takvimi tatilleri (kullanıcı kararı: tüm İK ayarları bu grupta) |
|
||||||
|
| 7 | Rapor talebi | Onay akışından geçer; kayıt anında Sağlık Kartı'nda görünür, reddedilirse kalkar |
|
||||||
|
| 8 | Kullanıcı kartı | Kullanıcı detayına **İzinler** sekmesi (bakiye özeti + talepler + defter) |
|
||||||
|
| 9 | Üstü olmayan pozisyon (Genel Müdür) | Müdür adımı atlanır, talep doğrudan İK Onayı'na gider (üretim sırasında soruldu) |
|
||||||
|
|
||||||
|
### 2.4 Üretimde verilen kararlar
|
||||||
|
|
||||||
|
| Konu | Karar | Neden |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Persona ekranında akış | **İzin Taleplerim** ekranında Workflow yoktur; ilk adımı (`Müdür Onayı` + müdür kullanıcı adları) kayıt sonrası prosedür yazar | Workflow alanlarını yazabilen persona ekranı, çalışanın durumu API ile "Onaylandı" yapmasına izin verirdi; alanlar İK yetkisine kilitli |
|
||||||
|
| Müdür ekranı | **Ekibimin İzin Talepleri** ayrı ekran, aynı akış başlıklarıyla; satır `ManagerIds` ile süzülür | Akış düğümleri ekrana bağlıdır, durum başlıkla eşleşir (`FindCurrentCriteria`) |
|
||||||
|
| İK onaycısının tek kaynağı | Kayıt sonrası prosedür İK adımına girerken onaycıyı **İzin Talepleri** akışının "İK Onayı" düğümünden okur | Ekibimin İzin Talepleri akışındaki İK düğümü ayrı düzenlenirse sapma olmasın |
|
||||||
|
| Yöneticinin geçişleri | Müdür yalnız Müdür Onayı → İK Onayı / Reddedildi yapabilir; başka geçiş geri alınır | Workflow alanları müdür ekranında yazılabilir olmak zorunda (motor ekranın kayıt yolunu kullanır) |
|
||||||
|
| Bakiye defteri | Hak ediş yılı başına satır; 0. yıl düzeltmeler ve ilk hak edişten önceki kullanım | Devirli kümülatif bakiyenin denetlenebilir dökümü |
|
||||||
|
| Açılış bakiyesi | **Bakiye Düzeltmeleri** (± gün) | Devirli hesapta sistem öncesi kullanım girilmezse geçmiş bütün yıllar kullanılmamış görünür |
|
||||||
|
| Bildirim | Uygulama içi + toast (`IzinTalebiOnayBekliyor`, `IzinTalebiSonuclandi`); Workflow `Inform` düğümü kullanılmadı | Inform yalnız e-posta gönderir ve onaycısı sabittir |
|
||||||
|
| Ek belge | `dxImageUpload` (base64, `nvarchar(MAX)`), listede gizli | Platform standardı |
|
||||||
|
| En üst pozisyon | Prosedür `RequiresManagerApproval`'ı yazar (1 = müdür onayı gerekir, 0 = atlanır); İzin Talepleri akışında Başlangıç ile Müdür Onayı arasında bu kolona bakan karşılaştırma düğümü vardır, çalışanın kendi talebinde prosedür durumu doğrudan İK Onayı yapar | Motorun karşılaştırma düğümü yalnız sayısal kolon okur (`EvaluateCondition`) ve satırı ekranın sorgusundan alır; kolon İzin Talepleri'nde gizli alandır |
|
||||||
|
| Form günü | Gün formda tarayıcıda önizlenir (hafta içi gün, yarım günde 0,5), kalıcı değer prosedürün hesabıdır; İzin Türü lookup'ı cascade değildir | Cascade ebeveyni çocuğu kilitler ve değiştiğinde temizler; ayrıntı §5.1 |
|
||||||
|
| Bildirim başlığı | Bildirim panelinde ve etkinlik kaydında tip adı yerine kaydın `Subject`'i gösterilir (bütün modüller) | Tip adı (`PerformansDurumDegisti`) koddur; konu çevrilmiş metindir |
|
||||||
|
|
||||||
|
### 2.5 Varsayılan kalanlar
|
||||||
|
|
||||||
|
- Çalışma günleri Pzt–Cum; kademeler 14 / 20 / 26, genç/yaşlı en az 20 (ayarlarda değiştirilir).
|
||||||
|
- İzin türü varsayılanı: yıllık izinden düşen ya da yıllık sınırı olan türler **Engelle**, diğerleri **Uyar ve kaydet** (seed).
|
||||||
|
- Rapor kaydı `SickLeaveType = Disease`, gün sayısı takvim günü (Sağlık Kartı kuralı); izin talebindeki gün çalışma günüdür.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Menü ve ekranlar
|
||||||
|
|
||||||
|
### 3.1 İK menüsü
|
||||||
|
|
||||||
|
`İnsan Kaynakları › İzin Yönetimi` (`App.Hr.Leave`, sıra 14, `FcOvertime`) — yalnız İK.
|
||||||
|
|
||||||
|
| Sıra | Menü (TR / EN) | `ListFormCode` | Wizard | Kaynak | Alt formlar | Widget'lar |
|
||||||
|
| --- | --- | --- | --- | --- | --- | --- |
|
||||||
|
| 1 | İzin Talepleri / Leave Requests | `App.Hr.LeaveRequest` | `LeaveRequest.json` | `Hr_T_LeaveRequest` | — | Müdür Onayında · İK Onayında · Onaylanan (bu yıl) · Reddedilen (bu yıl) |
|
||||||
|
| 2 | İzin Bakiyeleri / Leave Balances | `App.Hr.LeaveBalance` | `LeaveBalance.json` | `Hr_V_LeaveSummary` (salt okunur) | `LeaveBalanceAdjustment`, `LeaveBalanceYear` (`Id → EmployeeId`) | Çalışan · Toplam Kalan Gün · Eksi Bakiye · Onay Bekleyen Gün |
|
||||||
|
|
||||||
|
Menüsüz alt formlar: **Bakiye Düzeltmeleri** (`App.Hr.LeaveBalanceAdjustment`, `Hr_T_LeaveBalanceAdjustment`),
|
||||||
|
**İzin Defteri** (`App.Hr.LeaveBalanceYear`, `Hr_V_LeaveBalanceYear`, salt okunur).
|
||||||
|
|
||||||
|
Görünümler: hepsi Grid, Card, Pivot, Chart.
|
||||||
|
|
||||||
|
### 3.2 Çalışana ve müdüre ait ekranlar (menüsüz)
|
||||||
|
|
||||||
|
| Ekran | `ListFormCode` | Satır süzmesi | Yapılabilen |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| İzin Taleplerim | `App.Hr.MyLeaveRequest` | `EmployeeId = @USERID` | Ekle; karar verilmeden düzelt/sil. `EmployeeId` sunucuda `@USERID` ile yazılır |
|
||||||
|
| Bakiyem | `App.Hr.MyLeaveBalance` | `EmployeeId = @USERID` | Defteri görür |
|
||||||
|
| Ekibimin İzin Talepleri | `App.Hr.TeamLeaveRequest` | `ManagerIds` içinde kullanıcı | Müdür adımında Onayla / Reddet |
|
||||||
|
|
||||||
|
Talep formu doğrudan açılır: `/admin/form/App.Hr.MyLeaveRequest`.
|
||||||
|
|
||||||
|
### 3.3 Intranet › Dashboard widget'ları
|
||||||
|
|
||||||
|
Sol kolon (`Column: 0`), Aktif Anketler'in (30) altında; kayıtlar `data/App.DeveloperKit.IntranetWidgets.json`.
|
||||||
|
|
||||||
|
| `Code` · sıra | Bileşen | `PermissionName` | Gösterir | Butonlar |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| `my-leave` · 35 | `MyLeaveWidget` | `App.Hr.MyLeaveRequest` | Kalan / kullanılan / onay bekleyen gün, sonraki hak ediş, süren ilk 3 talep ve durumu | İzin Talebi Oluştur · Taleplerim · Bakiyem |
|
||||||
|
| `team-leave` · 36 | `TeamLeaveWidget` | `App.Hr.TeamLeaveRequest` | Onayımı bekleyen talep sayısı ve ilk 5'i, bugün izinde olanlar | Onay Bekleyenler |
|
||||||
|
|
||||||
|
Bileşenler code modunda, rotasızdır; veriyi ekranların kendi sorgusundan okur
|
||||||
|
(`GET /api/app/list-form-select/select`). Bakiye kartları `App.Hr.MyLeaveBalance` yetkisi yoksa gizlenir.
|
||||||
|
|
||||||
|
### 3.4 Kullanıcı detayı › İzinler
|
||||||
|
|
||||||
|
`ui/src/views/admin/user-management/LeaveTab.tsx`: İzin Bakiyeleri satırından altı kart (hak edilen,
|
||||||
|
düzeltme, kullanılan, bekleyen, kalan, kullanılabilir), altında kullanıcıya süzülmüş **İzin Talepleri**
|
||||||
|
ve **İzin Defteri** listeleri. Her parça kendi ekran yetkisiyle görünür; İK buradan çalışan adına talep
|
||||||
|
ekleyebilir (yeni satırın `EmployeeId`'si süzgeçten dolar).
|
||||||
|
|
||||||
|
### 3.5 Ayarlar
|
||||||
|
|
||||||
|
Ayarlar › İnsan Kaynakları › İzin (`App.HrSettings` › `App.HrSettings.Leave`, sağlayıcılar `T|G|D`):
|
||||||
|
|
||||||
|
| Kod | Varsayılan |
|
||||||
|
| --- | --- |
|
||||||
|
| `App.HrSettings.Leave.Work{Monday…Sunday}` | Pzt–Cum `True`, Cmt–Paz `False` |
|
||||||
|
| `App.HrSettings.Leave.AnnualDays1To5` / `AnnualDays5To15` / `AnnualDays15Plus` | 14 / 20 / 26 |
|
||||||
|
| `App.HrSettings.Leave.MinDaysYoungOld` | 20 |
|
||||||
|
|
||||||
|
SQL tarafı ayarı `dbo.Hr_F_HrSetting` ile ABP'nin sırasıyla okur (kiracı → genel → tanım varsayılanı).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Veri modeli
|
||||||
|
|
||||||
|
```
|
||||||
|
AbpUsers ──< Hr_T_LeaveRequest >── Hr_T_LeaveType
|
||||||
|
│ └── Adm_T_UserSickLeave (SickLeaveId, Rapor türünde)
|
||||||
|
└──< Hr_T_LeaveBalanceAdjustment
|
||||||
|
Hr_V_LeaveBalanceYear (defter) ──▶ Hr_V_LeaveSummary (çalışan başına toplam)
|
||||||
|
```
|
||||||
|
|
||||||
|
| Nesne | Önemli kolonlar | Kural |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Hr_T_LeaveRequest` | `RequestNo`, `EmployeeId`/`EmployeeName`/`DepartmentId`/`JobPositionId`, `LeaveTypeId`, `StartDate`/`EndDate` (tarih+saat), `IsHalfDay`, `HalfDayPart` (Morning/Afternoon), `Days` (0,5 adımlı), `Description`, `DocumentFileName`/`DocumentContent`, `BalanceWarning`, `SickLeaveId`, `ManagerIds`/`ManagerUserNames`, `RequiresManagerApproval` (int, 1/0), `ApprovalStatus`/`ApprovalUser`/`ApprovalDate`/`ApprovalDescription`, `LastNotifiedStatus`, `IsActive` | `EndDate ≥ StartDate`; kiracı + tam audit |
|
||||||
|
| `Hr_T_LeaveBalanceAdjustment` | `EmployeeId`, `AdjustmentDate`, `Days` (≠ 0, ±), `Reason`, `IsActive` | — |
|
||||||
|
| `Hr_T_LeaveType` (+ kolon) | `BalanceExceedAction` (`Block`/`Warn`, varsayılan `Block`) | Kayıpsız `ALTER ADD` |
|
||||||
|
| `Hr_V_LeaveBalanceYear` | `Id` (`{EmployeeId}-{YearNo}`), `YearNo`, `AccrualDate`, `PeriodEndDate`, `EntitledDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `CumulativeRemainingDays`, `NextAccrualDate`, `NextAccrualDays` | Görünüm |
|
||||||
|
| `Hr_V_LeaveSummary` | `Id` (= kullanıcı), `ServiceYears`, `EntitledDays`, `AdjustmentDays`, `UsedDays`, `PendingDays`, `RemainingDays`, `AvailableDays`, `NextAccrualDate/Days`, `IsActive` | Görünüm |
|
||||||
|
|
||||||
|
Durum değerleri (Workflow düğüm başlıkları): `Onaya Gönderildi` · `Müdür Onayı` · `İK Onayı` · `Onaylandı` · `Reddedildi`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. İş kuralları ve hesaplar
|
||||||
|
|
||||||
|
### 5.1 Gün sayısı (`Hr_F_LeaveWorkDays`)
|
||||||
|
|
||||||
|
Başlangıç–bitiş tarihleri (saat dikkate alınmaz) arasındaki her gün: ayarlarda çalışma günü değilse 0;
|
||||||
|
Çalışma Takvimi'nde `Holiday` ise 0, `HalfDay` ise 0,5; aksi 1. Yıllık tekrarlı satır başlangıç
|
||||||
|
yılından itibaren her yıl aynı gün/aya düşer. Yarım gün talepte sonuç en fazla 0,5'tir.
|
||||||
|
|
||||||
|
Formda gün veri girerken dolar (Başlangıç, Bitiş ve Yarım Gün alanlarının `EditorScript`'i, `custom` tarifi).
|
||||||
|
Bu bir önizlemedir: iki tarih arasındaki hafta içi günler sayılır, yarım günde 0,5 yazılır; Çalışma Günleri
|
||||||
|
ayarı ve Çalışma Takvimi tatilleri formda düşülmez. Kayıtta prosedür günü `Hr_F_LeaveWorkDays` ile yeniden
|
||||||
|
hesaplar ve kayıtlı değer odur.
|
||||||
|
|
||||||
|
| Olay | Formda |
|
||||||
|
| --- | --- |
|
||||||
|
| Başlangıç / Bitiş değişir | Gün yeniden hesaplanır; yarım gün açıkken Başlangıç değişirse Bitiş onu izler |
|
||||||
|
| Yarım Gün işaretlenir | Bitiş = Başlangıç, Gün 0,5, Yarım Gün Dilimi açılır |
|
||||||
|
| Yarım Gün kaldırılır | Dilim temizlenip kilitlenir, Gün tam gün olarak hesaplanır |
|
||||||
|
|
||||||
|
Notlar:
|
||||||
|
|
||||||
|
- **Dilim kilidi `custom` kuralıdır** (`readOnly` tarifi değil). Grid popup'ında editörler yeniden çizilince
|
||||||
|
kural açılış olayıyla (`isReady`) tekrar çalışır; o anda form verisi güncel değildir (`form.getEditor` popup
|
||||||
|
editörünü döndürmez) ve tarif Yarım Gün'ü eski hâliyle okuyup kilidi geri kapatırdı. Kural bu çalışmada
|
||||||
|
değeri grid'in düzenlenen satırından (`editor.component.cellValue`) okur; form sayfasında form verisinden.
|
||||||
|
- **Dilimin script'i yoktur.** Form sayfası script'li bir editör değişince `formData`'yı baştan yazar; bu sırada
|
||||||
|
açılır liste temizlenip yeniden dolar ve script'i olsaydı kendini tetikleyip sonsuz döngüye girerdi.
|
||||||
|
Tutarlılığı prosedür sağlar: yarım gün değilse dilim silinir, yarım günde boş dilim `Morning` olur.
|
||||||
|
- **İzin Türü düz bir lookup'tır**, cascade kullanılmaz: bool ebeveyn `false` iken çocuğu kilitler, tarih
|
||||||
|
değişince değeri silerdi.
|
||||||
|
|
||||||
|
### 5.2 Yıllık hak ve bakiye (`Hr_V_LeaveBalanceYear`)
|
||||||
|
|
||||||
|
| Değer | Formül |
|
||||||
|
| --- | --- |
|
||||||
|
| Hak ediş tarihi | Kıdem başlangıcı + n yıl (n = 1, 2, …), bugün ve (varsa) işten çıkış tarihine kadar |
|
||||||
|
| Hak edilen | n ≤ 5 → `AnnualDays1To5`; 6 ≤ n ≤ 14 → `AnnualDays5To15`; n ≥ 15 → `AnnualDays15Plus`. Hak ediş tarihindeki yaş ≤ 18 ya da ≥ 50 ise en az `MinDaysYoungOld` |
|
||||||
|
| Kullanılan / bekleyen | Yıllık izinden düşen türdeki onaylı / onay bekleyen taleplerin günü; talep başlangıcının düştüğü hak ediş dönemine yazılır |
|
||||||
|
| 0. yıl | Düzeltmelerin toplamı ve ilk hak edişten önce başlayan talepler |
|
||||||
|
| Kalan | Σ(hak edilen + düzeltme) − Σ kullanılan (devirli) |
|
||||||
|
| Kullanılabilir | Kalan − onay bekleyen |
|
||||||
|
|
||||||
|
### 5.3 Kayıt sonrası (`Hr_S_LeaveRequestAfterSave`)
|
||||||
|
|
||||||
|
Her ekleme/güncellemede (Workflow kararı dahil) çalışır; `THROW` kaydı geri alır.
|
||||||
|
|
||||||
|
1. Çalışan adı, departman, pozisyon kullanıcı kartından; talep no `IZN-YYYY-00001`. (İK formunda çalışan seçilince departman ve pozisyon formda da hemen dolar: Çalışan lookup'ı iki kolonu döndürür, `copy` tarifi yazar.)
|
||||||
|
2. Müdür (§2.3 karar 2) bulunur → `ManagerIds`, `ManagerUserNames`. Bulunamazsa: çalışanın pozisyonunun üst pozisyonu yoksa (Genel Müdür) `RequiresManagerApproval = 0` yazılır ve müdür adımı atlanır; değilse ve talep müdür adımına kadar ise `THROW 51110` (yapılandırma eksik).
|
||||||
|
3. Müdür ekranından izinsiz geçiş önceki duruma geri alınır.
|
||||||
|
4. Çalışanın yeni talebi `Müdür Onayı`'na (müdür adımı atlanıyorsa `İK Onayı`'na) alınır; adıma girerken onaycı yazılır (müdür adımı → `ManagerUserNames`, İK adımı → İzin Talepleri akışının "İK Onayı" düğümü).
|
||||||
|
5. Gün sayısı hesaplanır.
|
||||||
|
6. Talep sonuçlanmamışsa doğrulanır:
|
||||||
|
|
||||||
|
| Kod | Kural |
|
||||||
|
| --- | --- |
|
||||||
|
| 51111 | Tür cinsiyeti çalışana uymuyor |
|
||||||
|
| 51112 | Tür yarım güne izin vermiyor |
|
||||||
|
| 51113 | Yarım günde başlangıç ve bitiş aynı gün olmalı |
|
||||||
|
| 51114 | Tür belge istiyor, belge yok |
|
||||||
|
| 51115 | Aralıkta çalışma günü yok |
|
||||||
|
| 51116 | Reddedilmemiş başka bir talep ya da talebe bağlı olmayan istirahat aynı güne düşüyor (aynı günün iki ayrı yarısı serbest) |
|
||||||
|
| 51117 | Yıllık izinden düşen türde gün > kullanılabilir bakiye, ya da türün yıllık sınırı aşılıyor — tür `Block` ise; `Warn` ise kayıt yapılır, uyarı `BalanceWarning`'e yazılır |
|
||||||
|
|
||||||
|
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.
|
||||||
|
8. Durum bildirim taşıyan bir değere geçtiyse bir kez bildirim gider, `LastNotifiedStatus` güncellenir.
|
||||||
|
|
||||||
|
### 5.4 Satır koruması (`Hr_S_LeaveRequestGuard`, before-command)
|
||||||
|
|
||||||
|
| Aktör | Kural |
|
||||||
|
| --- | --- |
|
||||||
|
| Çalışan | Yalnız kendi talebi (`51100`); durum `Onaya Gönderildi`/`Müdür Onayı` değilse düzeltme/silme yok (`51101`) |
|
||||||
|
| Müdür | Silemez (`51102`); `ManagerIds` içinde olmalı (`51103`); talep `Müdür Onayı`'nda olmalı (`51104`) |
|
||||||
|
| İK | Serbest |
|
||||||
|
|
||||||
|
Alan kilidi: persona ekranlarında çalışanın/müdürün değiştirmemesi gereken alanların yazma yetkisi
|
||||||
|
`App.Hr.LeaveRequest.Create/.Update`'e bağlıdır; sunucu yetkisi olmayan alanı düşürür. Bu yüzden
|
||||||
|
çalışan/müdür rolüne İzin Talepleri'nin `.Create/.Update` yetkisi verilmez.
|
||||||
|
|
||||||
|
### 5.5 Rapor ↔ izin (tek kayıt)
|
||||||
|
|
||||||
|
| Nereden | Ne olur |
|
||||||
|
| --- | --- |
|
||||||
|
| İzin talebi, tür Rapor | `Adm_T_UserSickLeave` satırı açılır (`SickLeaveId`); 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 |
|
||||||
|
|
||||||
|
### 5.6 Onay akışı (Grid Workflow)
|
||||||
|
|
||||||
|
`Onaya Gönderildi` (Start) → `Müdür Onayı Gerekli mi?` (Compare, `RequiresManagerApproval = 1`) →
|
||||||
|
evet: `Müdür Onayı` (Approval, `@ManagerUserNames`) / hayır: doğrudan `İK Onayı` (Approval, seed'de
|
||||||
|
`system@sozsoft.com`) → `Onaylandı` (End); iki onay adımının reddi → `Reddedildi` (End).
|
||||||
|
Karşılaştırma düğümü yalnız İzin Talepleri akışındadır (akış İK grid'inden eklenen kayıtta orada başlar);
|
||||||
|
Ekibimin İzin Talepleri akışı başlatılmaz, yalnız müdür adımından ilerler. Akış iki ekranda aynı başlıklarla durur. İK onaycısı İzin
|
||||||
|
Talepleri › ListForm › Workflow › "İK Onayı" düğümünden değiştirilir (§2.4).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Yetki ve görünürlük
|
||||||
|
|
||||||
|
İzin grubu `App.Hr`, modül `Sas|Hr`. Dal `App.Hr.Leave` → `App.Hr.LeaveRequest`, `App.Hr.LeaveBalance`
|
||||||
|
(altında `LeaveBalanceAdjustment`, `LeaveBalanceYear`). Kökte menüsüz `App.Hr.MyLeaveRequest`,
|
||||||
|
`App.Hr.MyLeaveBalance`, `App.Hr.TeamLeaveRequest`. Ayar: `App.HrSettings` › `App.HrSettings.Leave`
|
||||||
|
(Administration grubu, `App.Setting` altında). Her ekranda `.Create/.Update/.Delete/.Export/.Import/.Note`.
|
||||||
|
**Hiçbir yetki role otomatik atanmaz.**
|
||||||
|
|
||||||
|
| Rol | Verilecek yetkiler |
|
||||||
|
| --- | --- |
|
||||||
|
| Tüm çalışanlar | `App.Hr.MyLeaveRequest` (+ `.Create/.Update/.Delete`), `App.Hr.MyLeaveBalance` |
|
||||||
|
| Müdürler | Yukarıdakiler + `App.Hr.TeamLeaveRequest` (+ `.Update` — Workflow kararı güncelleme yetkisi ister) |
|
||||||
|
| İK | `App.Hr.Leave` dalının tamamı + `App.HrSettings.Leave` |
|
||||||
|
|
||||||
|
Widget'lar liste okuma yetkisiyle görünür (İzinlerim `App.Hr.MyLeaveRequest`, Ekibimin İzinleri `App.Hr.TeamLeaveRequest`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Entegrasyonlar
|
||||||
|
|
||||||
|
| Kaynak | Kullanım |
|
||||||
|
| --- | --- |
|
||||||
|
| `AbpUsers` | Çalışan, kıdem, doğum tarihi, cinsiyet, departman/pozisyon; onaycı kullanıcı adları |
|
||||||
|
| `Hr_T_JobPosition` / `Hr_T_Department` | Departman müdürü çözümü |
|
||||||
|
| `Hr_T_LeaveType` | Tür kuralları (cinsiyet, yarım gün, belge, yıllık sınır, yıllık izinden düşme, aşım davranışı) |
|
||||||
|
| `Hr_T_WorkCalendar` | Tatil ve yarım günler |
|
||||||
|
| `AbpSettings` / `Sas_H_SettingDefinition` | Çalışma günleri ve kademeler |
|
||||||
|
| `Adm_T_UserSickLeave` | Rapor eşlemesi |
|
||||||
|
| Bildirimler | `IzinTalebiOnayBekliyor` (müdür / İK onaycısı), `IzinTalebiSonuclandi` (çalışan); kurallar `Custom` + `UiActivity`/`UiToast`. Metinler `App.Hr.Leave.Notification.{Approval,Result}.{Subject,Message}` (TR), yer tutucular `[Employee]`, `[LeaveType]`, `[StartDate]`, `[EndDate]`, `[Days]`, `[Status]`. Yazan: `Hr_S_LeaveNotify` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Akış örneği
|
||||||
|
|
||||||
|
1. İK Ayarlar › İnsan Kaynakları › İzin'de Cumartesi'yi çalışma günü yapar (gerekirse); eski çalışanlar için İzin Bakiyeleri › Bakiye Düzeltmeleri'ne sistem öncesi kullanılan günleri eksi olarak girer.
|
||||||
|
2. Muhasebe Şefi panodaki **İzinlerim** widget'ında kalan 18 günü görür, **İzin Talebi Oluştur** ile 3 günlük yıllık izin açar.
|
||||||
|
3. Gün kayıtta 3 hesaplanır, talep `Müdür Onayı`'na düşer, Muhasebe Müdürü bildirim alır.
|
||||||
|
4. Müdür **Ekibimin İzinleri** → Onay Bekleyenler'den talebi seçip **Onayla** der → talep `İK Onayı`'na geçer, İK onaycısı bildirim alır.
|
||||||
|
5. İK İzin Talepleri'nde onaylar → `Onaylandı`; çalışan bildirim alır, bakiye 15'e iner.
|
||||||
|
6. Çalışan rapor alır, Rapor türünde talep açıp raporu ekler → Sağlık Kartı › İstirahat Raporları'nda görünür; aynı onay akışından geçer.
|
||||||
|
7. Sağlık birimi başka bir raporu doğrudan Sağlık Kartı'na girer → İzin Talepleri'nde onaylı Rapor talebi olarak görünür.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Sık sorulanlar
|
||||||
|
|
||||||
|
**"Departman müdürü bulunamadı" hatası.** Çalışanın kullanıcı kartında departman ve pozisyon dolu olmalı; departmanın en üst pozisyonunda (ya da üst pozisyonlarda) aktif bir kullanıcı bulunmalı (§5.3 adım 2). Üst pozisyonu olmayan çalışan (Genel Müdür) bu hatayı almaz; talebi doğrudan İK onayına gider.
|
||||||
|
|
||||||
|
**Genel Müdür'ün talebini kim onaylar?** Müdür adımı atlanır, yalnız İK onaylar (§2.3 karar 9).
|
||||||
|
|
||||||
|
**Gün sayısı beklenenden az.** Hafta sonu, ayarlarda kapalı gün ve Çalışma Takvimi tatilleri sayılmaz; arife 0,5 sayılır.
|
||||||
|
|
||||||
|
**Bakiye çok yüksek görünüyor.** Devirli hesap kıdem başlangıcından bugüne bütün yılları sayar; sistem öncesi kullanılan izin Bakiye Düzeltmeleri'ne eksi olarak girilmelidir.
|
||||||
|
|
||||||
|
**Bakiyem/İzinlerim'de kıdem uyarısı.** Kullanıcı kartında Kıdem Başlangıç ya da İşe Giriş tarihi yok.
|
||||||
|
|
||||||
|
**Talebimi değiştiremiyorum.** Müdür karar verdikten sonra çalışan değiştiremez/silemez (`51101`); İK ile görüşülür.
|
||||||
|
|
||||||
|
**Müdür Onayla butonunu görmüyor.** Rolünde `App.Hr.TeamLeaveRequest.Update` olmalı; talep `Müdür Onayı`'nda ve kullanıcı o departmanın müdürü olmalı.
|
||||||
|
|
||||||
|
**İK onaycısı nasıl değişir?** İzin Talepleri › ListForm › Workflow › "İK Onayı" düğümü. Ekibimin İzin Talepleri'ndeki aynı düğüm akışı ilerletir; onaycı kayda İzin Talepleri düğümünden yazılır.
|
||||||
|
|
||||||
|
**Bildirim gelmiyor.** Kiracıda `IzinTalebiOnayBekliyor` / `IzinTalebiSonuclandi` tipi ve `Custom` kuralları olmalı (yeni kiracıya kopyalanır, mevcut kiracıda Administration › Bildirimler'den eklenir).
|
||||||
|
|
||||||
|
**Kullanıcı detayındaki İstirahatler'den girilen rapor izinlere düşmüyor.** O ekranın kancaları C# seeder'dadır (`ListFormSeeder_Administration`); daha önce kurulmuş bir veritabanında ekran yeniden kurulmadıkça kanca yoktur. Sağlık Kartı ekranı wizard'dır ve migrate ile güncellenir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Dosyalar ve geri alma
|
||||||
|
|
||||||
|
| Dosya | İçerik |
|
||||||
|
| --- | --- |
|
||||||
|
| `configs/seeds/host/sql/object/Hr_T_LeaveRequest.sql`, `Hr_T_LeaveBalanceAdjustment.sql`, `Hr_T_LeaveType.sql` (`BalanceExceedAction`) | Tablolar |
|
||||||
|
| `…/Hr_F_HrSetting.sql`, `Hr_F_LeaveWorkDays.sql` | Ayar okuma, gün sayısı |
|
||||||
|
| `…/Hr_V_LeaveBalanceYear.sql`, `Hr_V_LeaveSummary.sql` | Bakiye görünümleri |
|
||||||
|
| `…/Hr_S_LeaveRequestAfterSave.sql`, `Hr_S_LeaveRequestGuard.sql`, `Hr_S_LeaveNotify.sql`, `Hr_S_LeaveSickLeaveSync.sql` | Prosedürler |
|
||||||
|
| `configs/seeds/host/wizard/{LeaveRequest,MyLeaveRequest,TeamLeaveRequest,LeaveBalance,LeaveBalanceAdjustment,LeaveBalanceYear,MyLeaveBalance}.json` | 7 wizard; `LeaveType.json` (alan), `HealthCardSickLeave.json` (kancalar) |
|
||||||
|
| `configs/seeds/host/data/App.DeveloperKit.CustomComponents/{23744edc-eda9-512e-8079-fe2e8e5fd2a8,3b7b16c6-aa96-5765-8e19-fe5e727feb52}.json` | `MyLeaveWidget`, `TeamLeaveWidget` |
|
||||||
|
| `configs/seeds/host/data/App.DeveloperKit.IntranetWidgets.json`, `App.SettingDefinitions.json`, `App.Notifications.Notification{Types,Rules}.json`, `App.Menus.Menu.json`, `Abp.Identity.Permissions.json`, `App.Languages.LanguageText.json`, `App.Hr.LeaveType.json` | Seed satırları |
|
||||||
|
| `api/src/Sozsoft.Platform.Application/ListForms/ListFormWorkflowAppService.cs` | `@Kolon` onaycı |
|
||||||
|
| `api/src/Sozsoft.Platform.DbMigrator/Migrations/ListFormSeeder_Administration.cs` | Kullanıcı detayı istirahat kancaları |
|
||||||
|
| `ui/src/views/admin/listForm/workflow/WorkflowCriteria.tsx` | Tasarımcıda alan onaycısı seçeneği |
|
||||||
|
| `ui/src/views/admin/user-management/LeaveTab.tsx`, `Details.tsx` | İzinler sekmesi |
|
||||||
|
|
||||||
|
Kurulum: DB Migrate (SQL nesneleri, ekranlar `WizardDataSeeder`, satırlar `ListFormSeedDataApplier`),
|
||||||
|
ardından rollere yetki (§6). Ayar tanımları uygulama yeniden başlayınca ayar ekranında görünür.
|
||||||
|
|
||||||
|
Geri alma: Wizard Manager'dan 7 wizard silinir (alt formlar önce); tabloları düşürmek onayda seçilirse olur.
|
||||||
|
Widget bileşenleri ve pano kayıtları, bildirim tip/kural satırları, ayar tanımları, `Hr_F_*`/`Hr_V_*`/`Hr_S_Leave*`
|
||||||
|
nesneleri elle kaldırılır. `BalanceExceedAction` kolonu kalır (kayıpsız ekleme geri alınmaz).
|
||||||
|
|
||||||
|
<!-- 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.
|
||||||
|
|
||||||
|
### İzin Talepleri — `App.Hr.LeaveRequest`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/LeaveRequest.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | `App.Hr.Leave` › `App.Hr.LeaveRequest` (sıra 1) |
|
||||||
|
| Yetki | `App.Hr.LeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | İzin Talepleri — kurumdaki bütün izin talepleri ve onay durumları. Yalnız İnsan Kaynakları kullanır. |
|
||||||
|
| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false'` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
| Widget'lar | `App.Hr.Leave.Widget.ManagerApproval`, `App.Hr.Leave.Widget.HrApproval`, `App.Hr.Leave.Widget.Approved`, `App.Hr.Leave.Widget.Rejected` |
|
||||||
|
| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteAfter: SQL |
|
||||||
|
| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE |
|
||||||
|
| Onay akışı | Start 'Onaya Gönderildi' → Compare 'Müdür Onayı Gerekli mi?' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `RequestNo` | Talep No | dxTextBox | | ✓ | |
|
||||||
|
| `EmployeeId` | Çalışan | dxSelectBox | ✓ | ✓ | sorgu: AbpUsers · script |
|
||||||
|
| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department |
|
||||||
|
| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition |
|
||||||
|
| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType |
|
||||||
|
| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script |
|
||||||
|
| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script |
|
||||||
|
| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script |
|
||||||
|
| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon |
|
||||||
|
| `Days` | Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | |
|
||||||
|
| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | |
|
||||||
|
| `RequiresManagerApproval` | Müdür Onayı Gerekli | dxNumberBox | | | |
|
||||||
|
| `Description` | Açıklama | dxTextArea | | ✓ | |
|
||||||
|
| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | |
|
||||||
|
| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | |
|
||||||
|
| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | |
|
||||||
|
|
||||||
|
### İzin Bakiyeleri — `App.Hr.LeaveBalance`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/LeaveBalance.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | `App.Hr.Leave` › `App.Hr.LeaveBalance` (sıra 2) |
|
||||||
|
| Yetki | `App.Hr.LeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | İzin Bakiyeleri — her çalışanın yıllık izin bakiyesi. |
|
||||||
|
| Kaynak | `Hr_V_LeaveSummary` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
| Alt formlar | `App.Hr.LeaveBalanceAdjustment` (Id → EmployeeId), `App.Hr.LeaveBalanceYear` (Id → EmployeeId) |
|
||||||
|
| Widget'lar | `App.Widget.Total`, `App.Hr.Leave.Widget.RemainingDays`, `App.Hr.Leave.Widget.NegativeBalance`, `App.Hr.Leave.Widget.PendingDays` |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `EmployeeName` | Çalışan Adı | dxTextBox | | ✓ | |
|
||||||
|
| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department |
|
||||||
|
| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition |
|
||||||
|
| `SeniorityStartDate` | Kıdem Başlangıcı | dxDateBox | | ✓ | |
|
||||||
|
| `ServiceYears` | Kıdem Yılı | dxNumberBox | | ✓ | |
|
||||||
|
| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `AdjustmentDays` | Düzeltme Günü | dxNumberBox | | ✓ | |
|
||||||
|
| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `AvailableDays` | Kullanılabilir Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | |
|
||||||
|
| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | |
|
||||||
|
| `IsActive` | Aktif | dxCheckBox | | ✓ | |
|
||||||
|
|
||||||
|
### Bakiye Düzeltmeleri — `App.Hr.LeaveBalanceAdjustment`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/LeaveBalanceAdjustment.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | Menüsüz (alt form) |
|
||||||
|
| Yetki | `App.Hr.LeaveBalanceAdjustment` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | Bakiye Düzeltmeleri — çalışanın yıllık izin bakiyesine elle yapılan ekleme ve düşümler. |
|
||||||
|
| Kaynak | `Hr_T_LeaveBalanceAdjustment` · filtre `"IsDeleted" = 'false'` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
| Form varsayılanları | IsActive=true, AdjustmentDate=@DATE |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers |
|
||||||
|
| `AdjustmentDate` | Düzeltme Tarihi | dxDateBox | ✓ | ✓ | |
|
||||||
|
| `Days` | Gün | dxNumberBox | ✓ | ✓ | |
|
||||||
|
| `IsActive` | Aktif | dxCheckBox | | ✓ | |
|
||||||
|
| `Reason` | Neden | dxTextArea | ✓ | ✓ | |
|
||||||
|
|
||||||
|
### İzin Defteri — `App.Hr.LeaveBalanceYear`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/LeaveBalanceYear.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | Menüsüz (alt form) |
|
||||||
|
| Yetki | `App.Hr.LeaveBalanceYear` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | İzin Defteri — çalışanın yıllık izninin yıl yıl dökümü. |
|
||||||
|
| Kaynak | `Hr_V_LeaveBalanceYear` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers |
|
||||||
|
| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | |
|
||||||
|
| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | |
|
||||||
|
| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | |
|
||||||
|
| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | |
|
||||||
|
| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | |
|
||||||
|
|
||||||
|
### İzin Taleplerim — `App.Hr.MyLeaveRequest`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/MyLeaveRequest.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | Menüsüz (alt form) |
|
||||||
|
| Yetki | `App.Hr.MyLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | İzin Taleplerim — oturum açan çalışanın kendi izin talepleri ve onay durumları. |
|
||||||
|
| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND "EmployeeId" = '@USERID'` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✓ · düzenle ✓ · sil ✓ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
| Komutlar | InsertAfter: `Hr_S_LeaveRequestAfterSave` · UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` · DeleteBefore: `Hr_S_LeaveRequestGuard` · DeleteAfter: SQL |
|
||||||
|
| Form varsayılanları | IsHalfDay=false, StartDate=@DATE, EndDate=@DATE |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `RequestNo` | Talep No | dxTextBox | | ✓ | |
|
||||||
|
| `LeaveTypeId` | İzin Türü | dxSelectBox | ✓ | ✓ | sorgu: Hr_T_LeaveType |
|
||||||
|
| `StartDate` | Başlangıç Tarihi | dxDateBox | ✓ | ✓ | script |
|
||||||
|
| `EndDate` | Bitiş Tarihi | dxDateBox | ✓ | ✓ | script |
|
||||||
|
| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | script |
|
||||||
|
| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon |
|
||||||
|
| `Days` | Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | |
|
||||||
|
| `Description` | Açıklama | dxTextArea | | ✓ | |
|
||||||
|
| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | |
|
||||||
|
| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | |
|
||||||
|
| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `ApprovalDescription` | Onay Açıklaması | dxTextBox | | ✓ | |
|
||||||
|
|
||||||
|
### Ekibimin İzin Talepleri — `App.Hr.TeamLeaveRequest`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/TeamLeaveRequest.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | Menüsüz (alt form) |
|
||||||
|
| Yetki | `App.Hr.TeamLeaveRequest` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | Ekibimin İzin Talepleri — müdürü olduğunuz departmandaki çalışanların izin talepleri. |
|
||||||
|
| Kaynak | `Hr_T_LeaveRequest` · filtre `"IsDeleted" = 'false' AND '\|' + "ManagerIds" + '\|' LIKE '%\|@USERID\|%'` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
| Komutlar | UpdateBefore: `Hr_S_LeaveRequestGuard` · UpdateAfter: `Hr_S_LeaveRequestAfterSave` |
|
||||||
|
| Onay akışı | Start 'Onaya Gönderildi' → Approval 'Müdür Onayı' → Approval 'İK Onayı' → End 'Onaylandı' → End 'Reddedildi' |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `RequestNo` | Talep No | dxTextBox | | ✓ | |
|
||||||
|
| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers |
|
||||||
|
| `DepartmentId` | Departman | dxSelectBox | | ✓ | sorgu: Hr_T_Department |
|
||||||
|
| `JobPositionId` | İş Pozisyonu | dxSelectBox | | ✓ | sorgu: Hr_T_JobPosition |
|
||||||
|
| `LeaveTypeId` | İzin Türü | dxSelectBox | | ✓ | sorgu: Hr_T_LeaveType |
|
||||||
|
| `StartDate` | Başlangıç Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `EndDate` | Bitiş Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `IsHalfDay` | Yarım Gün | dxCheckBox | | ✓ | |
|
||||||
|
| `HalfDayPart` | Yarım Gün Dilimi | dxSelectBox | | ✓ | liste: Morning, Afternoon |
|
||||||
|
| `Days` | Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `BalanceWarning` | Bakiye Uyarısı | dxTextBox | | ✓ | |
|
||||||
|
| `ManagerUserNames` | Departman Müdürleri | dxTextBox | | | |
|
||||||
|
| `Description` | Açıklama | dxTextArea | | ✓ | |
|
||||||
|
| `DocumentFileName` | Belge Adı | dxTextBox | | ✓ | |
|
||||||
|
| `DocumentContent` | Belge (rapor vb.) | dxImageUpload | | ✓ | |
|
||||||
|
| `ApprovalStatus` | Onay Durumu | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalUser` | Onaylayan | dxTextBox | | ✓ | |
|
||||||
|
| `ApprovalDate` | Onay Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `ApprovalDescription` | Onay Açıklaması | dxTextArea | | ✓ | |
|
||||||
|
|
||||||
|
### Bakiyem — `App.Hr.MyLeaveBalance`
|
||||||
|
|
||||||
|
| Özellik | Değer |
|
||||||
|
| --- | --- |
|
||||||
|
| Wizard | `wizard/MyLeaveBalance.json` |
|
||||||
|
| Yol | Liste (Wizard) |
|
||||||
|
| Menü | Menüsüz (alt form) |
|
||||||
|
| Yetki | `App.Hr.MyLeaveBalance` + `.Create`, `.Update`, `.Delete`, `.Export`, `.Import`, `.Note` |
|
||||||
|
| Açıklama | Bakiyem — yıllık izin hakkınızın ve kullanımınızın yıl yıl dökümü. |
|
||||||
|
| Kaynak | `Hr_V_LeaveBalanceYear` · filtre `"EmployeeId" = '@USERID'` |
|
||||||
|
| Görünümler | Grid, Card, Pivot, Chart (açılış grid) |
|
||||||
|
| Düzenleme | ekle ✗ · düzenle ✗ · sil ✗ · popup |
|
||||||
|
| Kapsam | Kiracı |
|
||||||
|
|
||||||
|
| Alan | Başlık | Editör | Zorunlu | Formda | Kaynak |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| `EmployeeId` | Çalışan | dxSelectBox | | ✓ | sorgu: AbpUsers |
|
||||||
|
| `YearNo` | Hizmet Yılı | dxNumberBox | | ✓ | |
|
||||||
|
| `AccrualDate` | Hak Ediş Tarihi | dxDateBox | | ✓ | |
|
||||||
|
| `PeriodEndDate` | Dönem Sonu | dxDateBox | | ✓ | |
|
||||||
|
| `EntitledDays` | Hak Edilen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `UsedDays` | Kullanılan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `PendingDays` | Onay Bekleyen Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `RemainingDays` | Kalan Gün | dxNumberBox | | ✓ | |
|
||||||
|
| `CumulativeRemainingDays` | Kümülatif Bakiye | dxNumberBox | | ✓ | |
|
||||||
|
| `NextAccrualDate` | Sonraki Hak Ediş | dxDateBox | | ✓ | |
|
||||||
|
| `NextAccrualDays` | Sonraki Hak Ediş Günü | dxNumberBox | | ✓ | |
|
||||||
|
|
||||||
|
<!-- module-doc:auto:end -->
|
||||||
|
|
@ -423,7 +423,7 @@ geri alınmaz.
|
||||||
| `CompetencyWeight` | Yetkinlik Ağırlığı % | dxNumberBox | ✓ | ✓ | script |
|
| `CompetencyWeight` | Yetkinlik Ağırlığı % | dxNumberBox | ✓ | ✓ | script |
|
||||||
| `Is360Enabled` | 360 Derece Açık | dxCheckBox | | ✓ | |
|
| `Is360Enabled` | 360 Derece Açık | dxCheckBox | | ✓ | |
|
||||||
| `IsActive` | Aktif | dxCheckBox | | ✓ | |
|
| `IsActive` | Aktif | dxCheckBox | | ✓ | |
|
||||||
| `Description` | Açıklama | dxTextArea | | ✓ | |
|
| `Description` | Açıklama | dxTextBox | | ✓ | |
|
||||||
|
|
||||||
### Tüm Değerlendirmeler — `App.Hr.PerformanceReview`
|
### Tüm Değerlendirmeler — `App.Hr.PerformanceReview`
|
||||||
|
|
||||||
|
|
|
||||||
19
configs/seeds/host/sql/object/Hr_F_HrSetting.sql
Normal file
19
configs/seeds/host/sql/object/Hr_F_HrSetting.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
CREATE OR ALTER FUNCTION [dbo].[Hr_F_HrSetting]
|
||||||
|
(
|
||||||
|
@TenantId uniqueidentifier,
|
||||||
|
@Name nvarchar(128)
|
||||||
|
)
|
||||||
|
RETURNS nvarchar(2048)
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
-- Ayar ekranının çözüm sırası (T|G|D): kiracı değeri, genel değer, tanımdaki varsayılan.
|
||||||
|
RETURN COALESCE(
|
||||||
|
(SELECT TOP 1 [Value] FROM AbpSettings
|
||||||
|
WHERE [Name] = @Name AND ProviderName = N'T' AND @TenantId IS NOT NULL
|
||||||
|
AND ProviderKey = CONVERT(nvarchar(64), @TenantId)),
|
||||||
|
(SELECT TOP 1 [Value] FROM AbpSettings
|
||||||
|
WHERE [Name] = @Name AND ProviderName = N'G'),
|
||||||
|
(SELECT TOP 1 DefaultValue FROM Sas_H_SettingDefinition
|
||||||
|
WHERE Code = @Name AND IsDeleted = 0));
|
||||||
|
END
|
||||||
|
GO
|
||||||
66
configs/seeds/host/sql/object/Hr_F_LeaveWorkDays.sql
Normal file
66
configs/seeds/host/sql/object/Hr_F_LeaveWorkDays.sql
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
CREATE OR ALTER FUNCTION [dbo].[Hr_F_LeaveWorkDays]
|
||||||
|
(
|
||||||
|
@TenantId uniqueidentifier,
|
||||||
|
@StartDate date,
|
||||||
|
@EndDate date
|
||||||
|
)
|
||||||
|
RETURNS decimal(9, 1)
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
-- İzin günü = ayarlarda çalışma günü işaretli olup Çalışma Takvimi'nde tatil olmayan gün.
|
||||||
|
-- Yarım gün (arife) 0,5 sayılır. Yıllık tekrarlı satır başlangıç yılından itibaren her yıl
|
||||||
|
-- aynı gün/ay aralığına düşer (29 Şubat artık olmayan yılda 28 Şubat'a kayar).
|
||||||
|
IF @StartDate IS NULL OR @EndDate IS NULL OR @EndDate < @StartDate
|
||||||
|
RETURN 0;
|
||||||
|
|
||||||
|
-- Gün sırası Pazartesi = 0 (DATEFIRST ayarından bağımsız). Ayar 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;
|
||||||
|
|
||||||
|
DECLARE @Total decimal(9, 1) = 0;
|
||||||
|
DECLARE @Day date = @StartDate;
|
||||||
|
DECLARE @Value decimal(3, 1);
|
||||||
|
|
||||||
|
WHILE @Day <= @EndDate
|
||||||
|
BEGIN
|
||||||
|
SET @Value = 0;
|
||||||
|
|
||||||
|
IF EXISTS (SELECT 1 FROM @Work WHERE DayIndex = DATEDIFF(day, '19000101', @Day) % 7 AND IsWork = 1)
|
||||||
|
BEGIN
|
||||||
|
SET @Value = 1;
|
||||||
|
|
||||||
|
SELECT @Value = CASE WHEN MAX(CASE WHEN c.DayType = N'Holiday' THEN 1 ELSE 0 END) = 1 THEN 0 ELSE 0.5 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 c.StartDate AND c.EndDate)
|
||||||
|
OR (c.RecurrenceRule = N'FREQ=YEARLY' AND YEAR(@Day) >= YEAR(c.StartDate)
|
||||||
|
AND @Day BETWEEN DATEADD(year, YEAR(@Day) - YEAR(c.StartDate), c.StartDate)
|
||||||
|
AND DATEADD(year, YEAR(@Day) - YEAR(c.StartDate), c.EndDate))
|
||||||
|
)
|
||||||
|
HAVING COUNT(*) > 0;
|
||||||
|
END
|
||||||
|
|
||||||
|
SET @Total += @Value;
|
||||||
|
SET @Day = DATEADD(day, 1, @Day);
|
||||||
|
END
|
||||||
|
|
||||||
|
RETURN @Total;
|
||||||
|
END
|
||||||
|
GO
|
||||||
42
configs/seeds/host/sql/object/Hr_S_LeaveNotify.sql
Normal file
42
configs/seeds/host/sql/object/Hr_S_LeaveNotify.sql
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_LeaveNotify]
|
||||||
|
@RequestId uniqueidentifier,
|
||||||
|
@RecipientId uniqueidentifier,
|
||||||
|
@TypeName nvarchar(64),
|
||||||
|
@SubjectKey nvarchar(128),
|
||||||
|
@MessageKey nvarchar(128),
|
||||||
|
@ActorId uniqueidentifier = NULL
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
-- Alıcı talepten gelir (müdür, İK onaycısı ya da çalışan); tipin Custom kuralları yalnızca
|
||||||
|
-- kanalı belirler. Metin TR dil anahtarından okunur, yer tutucular talepten dolar.
|
||||||
|
IF @RequestId IS NULL OR @RecipientId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
INSERT INTO Adm_T_Notification (Id, TenantId, NotificationRuleId, NotificationChannel, NotificationTypeId, Identifier, UserId, Message, Subject, IsSent, IsRead, CreationTime, CreatorId, IsDeleted)
|
||||||
|
SELECT NEWID(), lr.TenantId, r.Id, r.Channel, t.Id,
|
||||||
|
CASE WHEN r.Channel = N'Mail' THEN u.Email ELSE CONVERT(nvarchar(64), u.Id) END,
|
||||||
|
u.Id,
|
||||||
|
LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(msg.Value, @MessageKey),
|
||||||
|
N'[Employee]', COALESCE(lr.EmployeeName, N'')),
|
||||||
|
N'[LeaveType]', COALESCE(lt.Name, N'')),
|
||||||
|
N'[StartDate]', FORMAT(lr.StartDate, 'dd.MM.yyyy')),
|
||||||
|
N'[EndDate]', FORMAT(lr.EndDate, 'dd.MM.yyyy')),
|
||||||
|
N'[Days]', FORMAT(lr.Days, '0.#')),
|
||||||
|
N'[Status]', COALESCE(lr.ApprovalStatus, N'')), 2048),
|
||||||
|
LEFT(COALESCE(sub.Value, @SubjectKey), 256),
|
||||||
|
CASE WHEN r.Channel = N'UiActivity' THEN 1 ELSE 0 END, 0, GETUTCDATE(), @ActorId, 0
|
||||||
|
FROM Hr_T_LeaveRequest lr
|
||||||
|
INNER JOIN Hr_T_LeaveType lt ON lt.Id = lr.LeaveTypeId
|
||||||
|
INNER JOIN AbpUsers u ON u.Id = @RecipientId AND u.IsActive = 1
|
||||||
|
INNER JOIN Adm_T_NotificationType t ON t.Name = @TypeName AND t.IsDeleted = 0
|
||||||
|
AND (t.TenantId = lr.TenantId OR (t.TenantId IS NULL AND lr.TenantId IS NULL))
|
||||||
|
INNER JOIN Adm_T_NotificationRule r ON r.NotificationTypeId = t.Id AND r.IsActive = 1 AND r.IsCustomized = 0
|
||||||
|
AND r.IsDeleted = 0 AND r.RecipientType = N'Custom' AND r.RecipientId IS NULL
|
||||||
|
LEFT JOIN Sas_H_LanguageText msg ON msg.ResourceName = N'Platform' AND msg.[Key] = @MessageKey AND msg.CultureName = N'tr'
|
||||||
|
LEFT JOIN Sas_H_LanguageText sub ON sub.ResourceName = N'Platform' AND sub.[Key] = @SubjectKey AND sub.CultureName = N'tr'
|
||||||
|
WHERE lr.Id = @RequestId
|
||||||
|
AND (r.Channel <> N'Mail' OR u.Email IS NOT NULL);
|
||||||
|
END
|
||||||
|
GO
|
||||||
327
configs/seeds/host/sql/object/Hr_S_LeaveRequestAfterSave.sql
Normal file
327
configs/seeds/host/sql/object/Hr_S_LeaveRequestAfterSave.sql
Normal file
|
|
@ -0,0 +1,327 @@
|
||||||
|
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_LeaveRequestAfterSave]
|
||||||
|
@RequestId uniqueidentifier,
|
||||||
|
@ActorId uniqueidentifier,
|
||||||
|
@Actor nvarchar(16)
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
-- İzin talebinin her kaydından (ekleme, güncelleme, Grid Workflow kararı) sonra çalışır:
|
||||||
|
-- ç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.
|
||||||
|
DECLARE @StatusStart nvarchar(50) = N'Onaya Gönderildi',
|
||||||
|
@StatusManager nvarchar(50) = N'Müdür Onayı',
|
||||||
|
@StatusHr nvarchar(50) = N'İK Onayı',
|
||||||
|
@StatusApproved nvarchar(50) = N'Onaylandı',
|
||||||
|
@StatusRejected nvarchar(50) = N'Reddedildi';
|
||||||
|
|
||||||
|
DECLARE @TenantId uniqueidentifier, @EmployeeId uniqueidentifier, @LeaveTypeId uniqueidentifier,
|
||||||
|
@StartDate datetime2, @EndDate datetime2, @IsHalfDay bit, @HalfDayPart nvarchar(16),
|
||||||
|
@Document nvarchar(MAX), @SickLeaveId uniqueidentifier, @Status nvarchar(50),
|
||||||
|
@LastStatus nvarchar(50), @Description nvarchar(1024);
|
||||||
|
|
||||||
|
SELECT @TenantId = TenantId, @EmployeeId = EmployeeId, @LeaveTypeId = LeaveTypeId,
|
||||||
|
@StartDate = StartDate, @EndDate = EndDate, @IsHalfDay = IsHalfDay, @HalfDayPart = HalfDayPart,
|
||||||
|
@Document = DocumentContent, @SickLeaveId = SickLeaveId, @Status = ApprovalStatus,
|
||||||
|
@LastStatus = LastNotifiedStatus, @Description = [Description]
|
||||||
|
FROM Hr_T_LeaveRequest
|
||||||
|
WHERE Id = @RequestId AND IsDeleted = 0;
|
||||||
|
|
||||||
|
IF @EmployeeId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
DECLARE @Message nvarchar(1024);
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
-- Çalışan ve departman müdürü
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
DECLARE @EmployeeName nvarchar(256), @DepartmentId uniqueidentifier, @JobPositionId uniqueidentifier,
|
||||||
|
@Gender nvarchar(16);
|
||||||
|
|
||||||
|
SELECT @EmployeeName = CONCAT(Name, N' ', Surname), @DepartmentId = DepartmentId,
|
||||||
|
@JobPositionId = JobPositionId, @Gender = Gender
|
||||||
|
FROM AbpUsers
|
||||||
|
WHERE Id = @EmployeeId;
|
||||||
|
|
||||||
|
-- Müdür = çalışanın departmanındaki en üst pozisyon(lar)ın sahibi (üst pozisyonu başka
|
||||||
|
-- departmanda olan ya da üstü olmayan pozisyon). Çalışan bu pozisyondaysa ya da pozisyon boşsa
|
||||||
|
-- bir üst pozisyona çıkılır.
|
||||||
|
DECLARE @Positions TABLE (Id uniqueidentifier PRIMARY KEY);
|
||||||
|
DECLARE @Managers TABLE (Id uniqueidentifier PRIMARY KEY, UserName nvarchar(256));
|
||||||
|
DECLARE @Parents TABLE (Id uniqueidentifier PRIMARY KEY);
|
||||||
|
DECLARE @Level int = 0;
|
||||||
|
|
||||||
|
INSERT INTO @Positions (Id)
|
||||||
|
SELECT p.Id
|
||||||
|
FROM Hr_T_JobPosition p
|
||||||
|
LEFT JOIN Hr_T_JobPosition parent ON parent.Id = p.ParentId
|
||||||
|
WHERE p.IsDeleted = 0 AND p.DepartmentId = @DepartmentId
|
||||||
|
AND (p.TenantId = @TenantId OR (p.TenantId IS NULL AND @TenantId IS NULL))
|
||||||
|
AND (p.ParentId IS NULL OR parent.DepartmentId <> p.DepartmentId);
|
||||||
|
|
||||||
|
IF EXISTS (SELECT 1 FROM @Positions WHERE Id = @JobPositionId)
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM @Positions;
|
||||||
|
INSERT INTO @Positions (Id)
|
||||||
|
SELECT ParentId FROM Hr_T_JobPosition WHERE Id = @JobPositionId AND ParentId IS NOT NULL;
|
||||||
|
END
|
||||||
|
|
||||||
|
WHILE @Level < 10 AND EXISTS (SELECT 1 FROM @Positions)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO @Managers (Id, UserName)
|
||||||
|
SELECT u.Id, u.UserName
|
||||||
|
FROM AbpUsers u
|
||||||
|
WHERE u.IsDeleted = 0 AND u.IsActive = 1 AND u.Id <> @EmployeeId
|
||||||
|
AND (u.TenantId = @TenantId OR (u.TenantId IS NULL AND @TenantId IS NULL))
|
||||||
|
AND u.JobPositionId IN (SELECT Id FROM @Positions);
|
||||||
|
|
||||||
|
IF EXISTS (SELECT 1 FROM @Managers)
|
||||||
|
BREAK;
|
||||||
|
|
||||||
|
DELETE FROM @Parents;
|
||||||
|
INSERT INTO @Parents (Id)
|
||||||
|
SELECT DISTINCT p.ParentId FROM Hr_T_JobPosition p
|
||||||
|
WHERE p.Id IN (SELECT Id FROM @Positions) AND p.ParentId IS NOT NULL;
|
||||||
|
|
||||||
|
DELETE FROM @Positions;
|
||||||
|
INSERT INTO @Positions (Id) SELECT Id FROM @Parents;
|
||||||
|
SET @Level += 1;
|
||||||
|
END
|
||||||
|
|
||||||
|
DECLARE @ManagerIds nvarchar(1024) = (SELECT STRING_AGG(CONVERT(nvarchar(36), Id), N'|') FROM @Managers);
|
||||||
|
DECLARE @ManagerUserNames nvarchar(1024) = (SELECT STRING_AGG(UserName, N'|') FROM @Managers);
|
||||||
|
|
||||||
|
-- Pozisyonu en üstte olan (üst pozisyonu olmayan) çalışanın onaylayacak müdürü yoktur; müdür adımı
|
||||||
|
-- atlanır ve talep İK onayına gider. Akış bu kolona bakan karşılaştırma düğümüyle dallanır.
|
||||||
|
DECLARE @RequiresManager int =
|
||||||
|
CASE WHEN @ManagerIds IS NULL AND EXISTS (SELECT 1 FROM Hr_T_JobPosition
|
||||||
|
WHERE Id = @JobPositionId AND ParentId IS NULL AND IsDeleted = 0)
|
||||||
|
THEN 0 ELSE 1 END;
|
||||||
|
|
||||||
|
IF @ManagerIds IS NULL AND @RequiresManager = 1 AND (@Status IS NULL OR @Status IN (@StatusStart, @StatusManager))
|
||||||
|
THROW 51110, N'Çalışanın departman müdürü bulunamadı. Kullanıcı kartında departman ve pozisyon tanımlı olmalı, departmanın müdür pozisyonunda aktif bir kullanıcı bulunmalıdır.', 1;
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
-- Yöneticinin yapabileceği geçişler: müdür onayından İK onayına ya da redde. Başka bir
|
||||||
|
-- geçiş (ör. doğrudan Onaylandı) önceki duruma geri alınır.
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
IF @Actor = N'Manager' AND COALESCE(@Status, N'') <> COALESCE(@LastStatus, N'')
|
||||||
|
AND NOT (@LastStatus = @StatusManager AND @Status IN (@StatusHr, @StatusRejected))
|
||||||
|
BEGIN
|
||||||
|
SET @Status = @LastStatus;
|
||||||
|
UPDATE Hr_T_LeaveRequest SET ApprovalStatus = @LastStatus WHERE Id = @RequestId;
|
||||||
|
END
|
||||||
|
|
||||||
|
-- Çalışanın açtığı talep doğrudan müdür onayına düşer (persona ekranında akış başlatılmaz);
|
||||||
|
-- müdürü olmayan en üst pozisyonda İK onayına.
|
||||||
|
IF @Status IS NULL AND @Actor = N'Employee'
|
||||||
|
SET @Status = CASE WHEN @RequiresManager = 1 THEN @StatusManager ELSE @StatusHr END;
|
||||||
|
|
||||||
|
-- Adıma girerken onaycı kayıttan çözülür: müdür adımında departman müdürü, İK adımında İK
|
||||||
|
-- ekranının akışındaki İK düğümü (tek kaynak; diğer ekranların düğümü yalnız geçişi yapar).
|
||||||
|
-- Adım içindeki kayıtta (karar anı) motorun yazdığı karar vereni ezmemek için dokunulmaz.
|
||||||
|
DECLARE @HrApprover nvarchar(1024) =
|
||||||
|
(SELECT TOP 1 Approver FROM Sas_H_ListFormWorkflow
|
||||||
|
WHERE ListFormCode = N'App.Hr.LeaveRequest' AND Kind = N'Approval' AND Title = @StatusHr);
|
||||||
|
|
||||||
|
UPDATE Hr_T_LeaveRequest
|
||||||
|
SET EmployeeName = @EmployeeName,
|
||||||
|
DepartmentId = @DepartmentId,
|
||||||
|
JobPositionId = @JobPositionId,
|
||||||
|
ManagerIds = COALESCE(@ManagerIds, ManagerIds),
|
||||||
|
ManagerUserNames = COALESCE(@ManagerUserNames, ManagerUserNames),
|
||||||
|
RequiresManagerApproval = @RequiresManager,
|
||||||
|
ApprovalStatus = @Status,
|
||||||
|
ApprovalUser = CASE
|
||||||
|
WHEN @Status = COALESCE(@LastStatus, N'') THEN ApprovalUser
|
||||||
|
WHEN @Status = @StatusManager THEN COALESCE(@ManagerUserNames, ApprovalUser)
|
||||||
|
WHEN @Status = @StatusHr AND @HrApprover IS NOT NULL THEN @HrApprover
|
||||||
|
ELSE ApprovalUser
|
||||||
|
END,
|
||||||
|
HalfDayPart = CASE WHEN @IsHalfDay = 1 THEN COALESCE(@HalfDayPart, N'Morning') ELSE NULL END,
|
||||||
|
RequestNo = CASE
|
||||||
|
WHEN RequestNo IS NULL OR RequestNo = N'' THEN
|
||||||
|
N'IZN-' + CAST(YEAR(CreationTime) AS nvarchar(4)) + N'-' + RIGHT(N'00000' + CAST(
|
||||||
|
(SELECT COALESCE(MAX(TRY_CAST(RIGHT(x.RequestNo, 5) AS int)), 0) + 1
|
||||||
|
FROM Hr_T_LeaveRequest x
|
||||||
|
WHERE (x.TenantId = @TenantId OR (x.TenantId IS NULL AND @TenantId IS NULL))
|
||||||
|
AND x.RequestNo LIKE N'IZN-' + CAST(YEAR(CreationTime) AS nvarchar(4)) + N'-%') AS nvarchar(10)), 5)
|
||||||
|
ELSE RequestNo
|
||||||
|
END
|
||||||
|
WHERE Id = @RequestId;
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
-- Gün sayısı ve kurallar (sonuçlanmış talepte yeniden doğrulanmaz)
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
DECLARE @TypeCode nvarchar(32), @TypeGender nvarchar(16), @MaxDaysPerYear int, @Deducts bit,
|
||||||
|
@RequiresDocument bit, @AllowHalfDay bit, @ExceedAction nvarchar(16);
|
||||||
|
|
||||||
|
SELECT @TypeCode = Code, @TypeGender = Gender, @MaxDaysPerYear = MaxDaysPerYear,
|
||||||
|
@Deducts = DeductsFromAnnualLeave, @RequiresDocument = RequiresDocument,
|
||||||
|
@AllowHalfDay = AllowHalfDay
|
||||||
|
FROM Hr_T_LeaveType
|
||||||
|
WHERE Id = @LeaveTypeId;
|
||||||
|
|
||||||
|
-- Kolon Hr_T_LeaveType.sql'de sonradan eklenir; migrate prosedürleri tablolardan önce
|
||||||
|
-- derlediği için kurulu bir veritabanında doğrudan başvuru derlemeyi düşürürdü.
|
||||||
|
EXEC sp_executesql N'SELECT @Action = BalanceExceedAction FROM Hr_T_LeaveType WHERE Id = @Id',
|
||||||
|
N'@Action nvarchar(16) OUTPUT, @Id uniqueidentifier', @Action = @ExceedAction OUTPUT, @Id = @LeaveTypeId;
|
||||||
|
|
||||||
|
DECLARE @Days decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, CAST(@StartDate AS date), CAST(@EndDate AS date));
|
||||||
|
IF @IsHalfDay = 1
|
||||||
|
SET @Days = CASE WHEN @Days > 0.5 THEN 0.5 ELSE @Days END;
|
||||||
|
|
||||||
|
UPDATE Hr_T_LeaveRequest SET Days = @Days WHERE Id = @RequestId;
|
||||||
|
|
||||||
|
IF @Status IS NULL OR @Status IN (@StatusStart, @StatusManager, @StatusHr)
|
||||||
|
BEGIN
|
||||||
|
IF @TypeGender IS NOT NULL AND @TypeGender <> N'All' AND COALESCE(@Gender, N'') <> @TypeGender
|
||||||
|
THROW 51111, N'Bu izin türü çalışanın cinsiyetine uygun değil.', 1;
|
||||||
|
|
||||||
|
IF @IsHalfDay = 1 AND @AllowHalfDay = 0
|
||||||
|
THROW 51112, N'Bu izin türü yarım gün kullanılamaz.', 1;
|
||||||
|
|
||||||
|
IF @IsHalfDay = 1 AND CAST(@StartDate AS date) <> CAST(@EndDate AS date)
|
||||||
|
THROW 51113, N'Yarım gün izinde başlangıç ve bitiş aynı gün olmalıdır.', 1;
|
||||||
|
|
||||||
|
IF @RequiresDocument = 1 AND (@Document IS NULL OR @Document = N'')
|
||||||
|
THROW 51114, N'Bu izin türü için belge (rapor vb.) eklenmelidir.', 1;
|
||||||
|
|
||||||
|
IF @Days <= 0
|
||||||
|
THROW 51115, N'Seçilen tarih aralığında çalışma günü yok.', 1;
|
||||||
|
|
||||||
|
-- Ç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.
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1 FROM Hr_T_LeaveRequest o
|
||||||
|
WHERE o.EmployeeId = @EmployeeId AND o.Id <> @RequestId AND o.IsDeleted = 0
|
||||||
|
AND (o.ApprovalStatus IS NULL OR o.ApprovalStatus <> @StatusRejected)
|
||||||
|
AND CAST(o.StartDate AS date) <= CAST(@EndDate AS date)
|
||||||
|
AND CAST(o.EndDate AS date) >= CAST(@StartDate AS date)
|
||||||
|
AND NOT (o.IsHalfDay = 1 AND @IsHalfDay = 1 AND COALESCE(o.HalfDayPart, N'Morning') <> COALESCE(@HalfDayPart, N'Morning')))
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM Adm_T_UserSickLeave s
|
||||||
|
WHERE s.UserId = @EmployeeId AND s.IsDeleted = 0
|
||||||
|
AND (@SickLeaveId IS NULL OR s.Id <> @SickLeaveId)
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM Hr_T_LeaveRequest l WHERE l.SickLeaveId = s.Id AND l.IsDeleted = 0)
|
||||||
|
AND CAST(s.StartDate AS date) <= CAST(@EndDate AS date)
|
||||||
|
AND CAST(s.EndDate AS date) >= CAST(@StartDate AS date))
|
||||||
|
THROW 51116, N'Bu tarihlerle çakışan başka bir izin ya da rapor kaydı var.', 1;
|
||||||
|
|
||||||
|
DECLARE @Warning nvarchar(512) = NULL;
|
||||||
|
|
||||||
|
IF @Deducts = 1
|
||||||
|
BEGIN
|
||||||
|
DECLARE @Remaining decimal(9, 1) = COALESCE((SELECT RemainingDays FROM Hr_V_LeaveSummary WHERE Id = @EmployeeId), 0);
|
||||||
|
DECLARE @OtherPending decimal(9, 1) = COALESCE((
|
||||||
|
SELECT SUM(o.Days) FROM Hr_T_LeaveRequest o
|
||||||
|
INNER JOIN Hr_T_LeaveType ot ON ot.Id = o.LeaveTypeId
|
||||||
|
WHERE o.EmployeeId = @EmployeeId AND o.Id <> @RequestId AND o.IsDeleted = 0
|
||||||
|
AND ot.DeductsFromAnnualLeave = 1
|
||||||
|
AND (o.ApprovalStatus IS NULL OR o.ApprovalStatus IN (@StatusStart, @StatusManager, @StatusHr))), 0);
|
||||||
|
|
||||||
|
IF @Days > @Remaining - @OtherPending
|
||||||
|
SET @Warning = CONCAT(N'Yıllık izin bakiyesi yetersiz: kullanılabilir ', FORMAT(@Remaining - @OtherPending, '0.#'),
|
||||||
|
N' gün, talep ', FORMAT(@Days, '0.#'), N' gün.');
|
||||||
|
END
|
||||||
|
|
||||||
|
IF @Warning IS NULL AND @MaxDaysPerYear IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DECLARE @UsedThisYear decimal(9, 1) = COALESCE((
|
||||||
|
SELECT SUM(o.Days) FROM Hr_T_LeaveRequest o
|
||||||
|
WHERE o.EmployeeId = @EmployeeId AND o.Id <> @RequestId AND o.IsDeleted = 0
|
||||||
|
AND o.LeaveTypeId = @LeaveTypeId AND YEAR(o.StartDate) = YEAR(@StartDate)
|
||||||
|
AND (o.ApprovalStatus IS NULL OR o.ApprovalStatus <> @StatusRejected)), 0);
|
||||||
|
|
||||||
|
IF @UsedThisYear + @Days > @MaxDaysPerYear
|
||||||
|
SET @Warning = CONCAT(N'Bu izin türünün yıllık sınırı ', @MaxDaysPerYear, N' gün; bu yıl kullanılan/bekleyen ',
|
||||||
|
FORMAT(@UsedThisYear, '0.#'), N' gün, talep ', FORMAT(@Days, '0.#'), N' gün.');
|
||||||
|
END
|
||||||
|
|
||||||
|
IF @Warning IS NOT NULL AND COALESCE(@ExceedAction, N'Block') = N'Block'
|
||||||
|
BEGIN
|
||||||
|
SET @Message = @Warning;
|
||||||
|
THROW 51117, @Message, 1;
|
||||||
|
END
|
||||||
|
|
||||||
|
UPDATE Hr_T_LeaveRequest SET BalanceWarning = @Warning WHERE Id = @RequestId;
|
||||||
|
END
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
-- Rapor türü = Sağlık Kartı › İstirahatler satırı (tek kayıt)
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
IF @TypeCode = N'Sick' AND COALESCE(@Status, N'') <> @StatusRejected
|
||||||
|
BEGIN
|
||||||
|
IF @SickLeaveId IS NULL OR NOT EXISTS (SELECT 1 FROM Adm_T_UserSickLeave WHERE Id = @SickLeaveId)
|
||||||
|
BEGIN
|
||||||
|
SET @SickLeaveId = NEWID();
|
||||||
|
INSERT INTO Adm_T_UserSickLeave (Id, TenantId, UserId, StartDate, EndDate, Days, SickLeaveType, Institution, Clinic, SickLeaveReason, CreationTime, CreatorId, IsDeleted)
|
||||||
|
VALUES (@SickLeaveId, @TenantId, @EmployeeId, CAST(@StartDate AS date), CAST(@EndDate AS date),
|
||||||
|
DATEDIFF(day, CAST(@StartDate AS date), CAST(@EndDate AS date)) + 1, N'Disease', NULL, NULL,
|
||||||
|
LEFT(@Description, 512), GETUTCDATE(), @ActorId, 0);
|
||||||
|
|
||||||
|
UPDATE Hr_T_LeaveRequest SET SickLeaveId = @SickLeaveId WHERE Id = @RequestId;
|
||||||
|
END
|
||||||
|
ELSE
|
||||||
|
BEGIN
|
||||||
|
UPDATE Adm_T_UserSickLeave
|
||||||
|
SET StartDate = CAST(@StartDate AS date),
|
||||||
|
EndDate = CAST(@EndDate AS date),
|
||||||
|
Days = DATEDIFF(day, CAST(@StartDate AS date), CAST(@EndDate AS date)) + 1,
|
||||||
|
IsDeleted = 0, DeletionTime = NULL, DeleterId = NULL,
|
||||||
|
LastModificationTime = GETUTCDATE(), LastModifierId = @ActorId
|
||||||
|
WHERE Id = @SickLeaveId;
|
||||||
|
END
|
||||||
|
END
|
||||||
|
ELSE IF @SickLeaveId IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
-- Reddedilen ya da türü rapordan başka bir türe çevrilen talebin istirahati kalkar.
|
||||||
|
UPDATE Adm_T_UserSickLeave
|
||||||
|
SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId
|
||||||
|
WHERE Id = @SickLeaveId AND IsDeleted = 0;
|
||||||
|
|
||||||
|
IF @TypeCode <> N'Sick'
|
||||||
|
UPDATE Hr_T_LeaveRequest SET SickLeaveId = NULL WHERE Id = @RequestId;
|
||||||
|
END
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
-- Bildirim: yalnızca bildirim taşıyan durumlara geçişte, bir kez
|
||||||
|
---------------------------------------------------------------------------------------------
|
||||||
|
IF @Status IN (@StatusManager, @StatusHr, @StatusApproved, @StatusRejected)
|
||||||
|
AND COALESCE(@LastStatus, N'') <> @Status
|
||||||
|
BEGIN
|
||||||
|
DECLARE @Recipients TABLE (Id uniqueidentifier PRIMARY KEY);
|
||||||
|
|
||||||
|
IF @Status = @StatusManager
|
||||||
|
INSERT INTO @Recipients (Id) SELECT Id FROM @Managers;
|
||||||
|
ELSE IF @Status = @StatusHr
|
||||||
|
INSERT INTO @Recipients (Id)
|
||||||
|
SELECT DISTINCT u.Id
|
||||||
|
FROM STRING_SPLIT(COALESCE(@HrApprover, N''), N'|') a
|
||||||
|
INNER JOIN AbpUsers u ON (u.UserName = LTRIM(RTRIM(a.value)) OR u.Email = LTRIM(RTRIM(a.value)))
|
||||||
|
AND u.IsDeleted = 0
|
||||||
|
AND (u.TenantId = @TenantId OR (u.TenantId IS NULL AND @TenantId IS NULL))
|
||||||
|
WHERE LTRIM(RTRIM(a.value)) <> N'';
|
||||||
|
ELSE
|
||||||
|
INSERT INTO @Recipients (Id) VALUES (@EmployeeId);
|
||||||
|
|
||||||
|
DECLARE @Type nvarchar(64) = CASE WHEN @Status IN (@StatusManager, @StatusHr) THEN N'IzinTalebiOnayBekliyor' ELSE N'IzinTalebiSonuclandi' END;
|
||||||
|
DECLARE @Subject nvarchar(128) = CASE WHEN @Status IN (@StatusManager, @StatusHr) THEN N'App.Hr.Leave.Notification.Approval.Subject' ELSE N'App.Hr.Leave.Notification.Result.Subject' END;
|
||||||
|
DECLARE @Body nvarchar(128) = CASE WHEN @Status IN (@StatusManager, @StatusHr) THEN N'App.Hr.Leave.Notification.Approval.Message' ELSE N'App.Hr.Leave.Notification.Result.Message' END;
|
||||||
|
DECLARE @Recipient uniqueidentifier;
|
||||||
|
|
||||||
|
DECLARE recipient_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT Id FROM @Recipients;
|
||||||
|
OPEN recipient_cursor;
|
||||||
|
FETCH NEXT FROM recipient_cursor INTO @Recipient;
|
||||||
|
WHILE @@FETCH_STATUS = 0
|
||||||
|
BEGIN
|
||||||
|
EXEC dbo.Hr_S_LeaveNotify @RequestId, @Recipient, @Type, @Subject, @Body, @ActorId;
|
||||||
|
FETCH NEXT FROM recipient_cursor INTO @Recipient;
|
||||||
|
END
|
||||||
|
CLOSE recipient_cursor;
|
||||||
|
DEALLOCATE recipient_cursor;
|
||||||
|
|
||||||
|
UPDATE Hr_T_LeaveRequest SET LastNotifiedStatus = @Status WHERE Id = @RequestId;
|
||||||
|
END
|
||||||
|
END
|
||||||
|
GO
|
||||||
48
configs/seeds/host/sql/object/Hr_S_LeaveRequestGuard.sql
Normal file
48
configs/seeds/host/sql/object/Hr_S_LeaveRequestGuard.sql
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_LeaveRequestGuard]
|
||||||
|
@RequestId uniqueidentifier,
|
||||||
|
@ActorId uniqueidentifier,
|
||||||
|
@Actor nvarchar(16),
|
||||||
|
@Operation nvarchar(16)
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
-- 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.
|
||||||
|
IF @RequestId IS NULL OR @Actor = N'Hr'
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
DECLARE @EmployeeId uniqueidentifier, @Status nvarchar(50), @ManagerIds nvarchar(1024);
|
||||||
|
|
||||||
|
SELECT @EmployeeId = EmployeeId, @Status = ApprovalStatus, @ManagerIds = ManagerIds
|
||||||
|
FROM Hr_T_LeaveRequest
|
||||||
|
WHERE Id = @RequestId AND IsDeleted = 0;
|
||||||
|
|
||||||
|
IF @EmployeeId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
IF @Actor = N'Employee'
|
||||||
|
BEGIN
|
||||||
|
IF @EmployeeId <> @ActorId
|
||||||
|
THROW 51100, N'Bu izin talebi size ait değil.', 1;
|
||||||
|
|
||||||
|
-- Karar verilmiş talep çalışan tarafından değiştirilemez; iptal için İK'ya başvurulur.
|
||||||
|
IF @Status IS NOT NULL AND @Status NOT IN (N'Onaya Gönderildi', N'Müdür Onayı')
|
||||||
|
THROW 51101, N'Onay sürecinde ilerlemiş ya da sonuçlanmış izin talebi değiştirilemez veya silinemez. İptal için İnsan Kaynakları ile görüşün.', 1;
|
||||||
|
|
||||||
|
RETURN;
|
||||||
|
END
|
||||||
|
|
||||||
|
IF @Actor = N'Manager'
|
||||||
|
BEGIN
|
||||||
|
IF @Operation = N'Delete'
|
||||||
|
THROW 51102, N'Yönetici izin talebini silemez.', 1;
|
||||||
|
|
||||||
|
IF @ActorId IS NULL OR N'|' + COALESCE(@ManagerIds, N'') + N'|' NOT LIKE N'%|' + CONVERT(nvarchar(36), @ActorId) + N'|%'
|
||||||
|
THROW 51103, N'Bu izin talebinin onaycısı değilsiniz.', 1;
|
||||||
|
|
||||||
|
IF @Status IS NULL OR @Status <> N'Müdür Onayı'
|
||||||
|
THROW 51104, N'İzin talebi müdür onayında beklemiyor.', 1;
|
||||||
|
END
|
||||||
|
END
|
||||||
|
GO
|
||||||
77
configs/seeds/host/sql/object/Hr_S_LeaveSickLeaveSync.sql
Normal file
77
configs/seeds/host/sql/object/Hr_S_LeaveSickLeaveSync.sql
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
CREATE OR ALTER PROCEDURE [dbo].[Hr_S_LeaveSickLeaveSync]
|
||||||
|
@SickLeaveId uniqueidentifier,
|
||||||
|
@ActorId uniqueidentifier = NULL
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
-- Sağlık Kartı › İstirahatler'den (ya da kullanıcı detayındaki istirahat listesinden) girilen
|
||||||
|
-- rapor, İzin Yönetimi'nde onaylanmış "Sick" türünde talep olarak görünür (tek kayıt). Talep
|
||||||
|
-- tarafı istirahati kendisi yazar; bu prosedür yalnızca istirahat ekranından gelen değişikliği taşır.
|
||||||
|
IF @SickLeaveId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
DECLARE @TenantId uniqueidentifier, @UserId uniqueidentifier, @StartDate date, @EndDate date,
|
||||||
|
@Reason nvarchar(1024), @IsDeleted bit;
|
||||||
|
|
||||||
|
SELECT @TenantId = TenantId, @UserId = UserId, @StartDate = CAST(StartDate AS date),
|
||||||
|
@EndDate = CAST(EndDate AS date), @Reason = SickLeaveReason, @IsDeleted = IsDeleted
|
||||||
|
FROM Adm_T_UserSickLeave
|
||||||
|
WHERE Id = @SickLeaveId;
|
||||||
|
|
||||||
|
IF @UserId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
DECLARE @RequestId uniqueidentifier =
|
||||||
|
(SELECT TOP 1 Id FROM Hr_T_LeaveRequest WHERE SickLeaveId = @SickLeaveId ORDER BY IsDeleted, CreationTime);
|
||||||
|
|
||||||
|
IF @IsDeleted = 1
|
||||||
|
BEGIN
|
||||||
|
UPDATE Hr_T_LeaveRequest
|
||||||
|
SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @ActorId
|
||||||
|
WHERE SickLeaveId = @SickLeaveId AND IsDeleted = 0;
|
||||||
|
RETURN;
|
||||||
|
END
|
||||||
|
|
||||||
|
DECLARE @Days decimal(9, 1) = dbo.Hr_F_LeaveWorkDays(@TenantId, @StartDate, @EndDate);
|
||||||
|
|
||||||
|
IF @RequestId IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
UPDATE Hr_T_LeaveRequest
|
||||||
|
SET StartDate = @StartDate, EndDate = @EndDate, Days = @Days,
|
||||||
|
IsDeleted = 0, DeletionTime = NULL, DeleterId = NULL,
|
||||||
|
LastModificationTime = GETUTCDATE(), LastModifierId = @ActorId
|
||||||
|
WHERE Id = @RequestId;
|
||||||
|
RETURN;
|
||||||
|
END
|
||||||
|
|
||||||
|
-- Kiracıda rapor türü tanımlı değilse eşlenecek talep yoktur.
|
||||||
|
DECLARE @LeaveTypeId uniqueidentifier =
|
||||||
|
(SELECT TOP 1 Id FROM Hr_T_LeaveType
|
||||||
|
WHERE Code = N'Sick' AND IsDeleted = 0
|
||||||
|
AND (TenantId = @TenantId OR (TenantId IS NULL AND @TenantId IS NULL)));
|
||||||
|
|
||||||
|
IF @LeaveTypeId IS NULL
|
||||||
|
RETURN;
|
||||||
|
|
||||||
|
DECLARE @ActorName nvarchar(256) = (SELECT UserName FROM AbpUsers WHERE Id = @ActorId);
|
||||||
|
DECLARE @Year nvarchar(4) = CAST(YEAR(GETUTCDATE()) AS nvarchar(4));
|
||||||
|
|
||||||
|
-- İstirahat sağlık birimince girilmiş bir belgedir; onay akışına girmeden onaylı yazılır.
|
||||||
|
INSERT INTO Hr_T_LeaveRequest
|
||||||
|
(Id, TenantId, RequestNo, EmployeeId, EmployeeName, DepartmentId, JobPositionId, LeaveTypeId,
|
||||||
|
StartDate, EndDate, IsHalfDay, Days, [Description], SickLeaveId,
|
||||||
|
ApprovalStatus, ApprovalUser, ApprovalDate, LastNotifiedStatus, IsActive, CreationTime, CreatorId, IsDeleted)
|
||||||
|
SELECT NEWID(), @TenantId,
|
||||||
|
N'IZN-' + @Year + N'-' + RIGHT(N'00000' + CAST(
|
||||||
|
(SELECT COALESCE(MAX(TRY_CAST(RIGHT(x.RequestNo, 5) AS int)), 0) + 1
|
||||||
|
FROM Hr_T_LeaveRequest x
|
||||||
|
WHERE (x.TenantId = @TenantId OR (x.TenantId IS NULL AND @TenantId IS NULL))
|
||||||
|
AND x.RequestNo LIKE N'IZN-' + @Year + N'-%') AS nvarchar(10)), 5),
|
||||||
|
u.Id, CONCAT(u.Name, N' ', u.Surname), u.DepartmentId, u.JobPositionId, @LeaveTypeId,
|
||||||
|
@StartDate, @EndDate, 0, @Days, LEFT(@Reason, 1024), @SickLeaveId,
|
||||||
|
N'Onaylandı', @ActorName, GETUTCDATE(), N'Onaylandı', 1, GETUTCDATE(), @ActorId, 0
|
||||||
|
FROM AbpUsers u
|
||||||
|
WHERE u.Id = @UserId;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
IF OBJECT_ID(N'[dbo].[Hr_T_LeaveBalanceAdjustment]', 'U') IS NULL
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[Hr_T_LeaveBalanceAdjustment]
|
||||||
|
(
|
||||||
|
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
|
||||||
|
[TenantId] uniqueidentifier NULL,
|
||||||
|
[EmployeeId] uniqueidentifier NOT NULL,
|
||||||
|
[AdjustmentDate] date NOT NULL,
|
||||||
|
[Days] decimal(5, 1) NOT NULL,
|
||||||
|
[Reason] nvarchar(512) NOT NULL,
|
||||||
|
[IsActive] bit NOT NULL DEFAULT 1,
|
||||||
|
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
|
||||||
|
[CreatorId] uniqueidentifier NULL,
|
||||||
|
[LastModificationTime] datetime2 NULL,
|
||||||
|
[LastModifierId] uniqueidentifier NULL,
|
||||||
|
[IsDeleted] bit NOT NULL DEFAULT 0,
|
||||||
|
[DeletionTime] datetime2 NULL,
|
||||||
|
[DeleterId] uniqueidentifier NULL,
|
||||||
|
CONSTRAINT [PK_Hr_T_LeaveBalanceAdjustment] PRIMARY KEY NONCLUSTERED
|
||||||
|
(
|
||||||
|
[Id] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveBalanceAdjustment_Days]', 'C') IS NULL
|
||||||
|
ALTER TABLE [dbo].[Hr_T_LeaveBalanceAdjustment] ADD CONSTRAINT [CK_Hr_T_LeaveBalanceAdjustment_Days] CHECK ([Days] <> 0)
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_LeaveBalanceAdjustment_Employee' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_LeaveBalanceAdjustment]'))
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_Hr_T_LeaveBalanceAdjustment_Employee] ON [dbo].[Hr_T_LeaveBalanceAdjustment] ([TenantId], [EmployeeId]) WHERE [IsDeleted] = 0
|
||||||
|
GO
|
||||||
65
configs/seeds/host/sql/object/Hr_T_LeaveRequest.sql
Normal file
65
configs/seeds/host/sql/object/Hr_T_LeaveRequest.sql
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
IF OBJECT_ID(N'[dbo].[Hr_T_LeaveRequest]', 'U') IS NULL
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[Hr_T_LeaveRequest]
|
||||||
|
(
|
||||||
|
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
|
||||||
|
[TenantId] uniqueidentifier NULL,
|
||||||
|
[RequestNo] nvarchar(32) NULL,
|
||||||
|
[EmployeeId] uniqueidentifier NOT NULL,
|
||||||
|
[EmployeeName] nvarchar(256) NULL,
|
||||||
|
[DepartmentId] uniqueidentifier NULL,
|
||||||
|
[JobPositionId] uniqueidentifier NULL,
|
||||||
|
[LeaveTypeId] uniqueidentifier NOT NULL,
|
||||||
|
[StartDate] datetime2 NOT NULL,
|
||||||
|
[EndDate] datetime2 NOT NULL,
|
||||||
|
[IsHalfDay] bit NOT NULL DEFAULT 0,
|
||||||
|
[HalfDayPart] nvarchar(16) NULL,
|
||||||
|
[Days] decimal(5, 1) NOT NULL DEFAULT 0,
|
||||||
|
[Description] nvarchar(1024) NULL,
|
||||||
|
[DocumentFileName] nvarchar(256) NULL,
|
||||||
|
[DocumentContent] nvarchar(MAX) NULL,
|
||||||
|
[BalanceWarning] nvarchar(512) NULL,
|
||||||
|
[SickLeaveId] uniqueidentifier NULL,
|
||||||
|
[ManagerIds] nvarchar(1024) NULL,
|
||||||
|
[ManagerUserNames] nvarchar(1024) NULL,
|
||||||
|
[RequiresManagerApproval] int NOT NULL DEFAULT 1,
|
||||||
|
[ApprovalStatus] nvarchar(50) NULL,
|
||||||
|
[ApprovalUser] nvarchar(1024) NULL,
|
||||||
|
[ApprovalDate] datetime2 NULL,
|
||||||
|
[ApprovalDescription] nvarchar(512) NULL,
|
||||||
|
[LastNotifiedStatus] nvarchar(50) NULL,
|
||||||
|
[IsActive] bit NOT NULL DEFAULT 1,
|
||||||
|
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
|
||||||
|
[CreatorId] uniqueidentifier NULL,
|
||||||
|
[LastModificationTime] datetime2 NULL,
|
||||||
|
[LastModifierId] uniqueidentifier NULL,
|
||||||
|
[IsDeleted] bit NOT NULL DEFAULT 0,
|
||||||
|
[DeletionTime] datetime2 NULL,
|
||||||
|
[DeleterId] uniqueidentifier NULL,
|
||||||
|
CONSTRAINT [PK_Hr_T_LeaveRequest] 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 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
|
||||||
|
ALTER TABLE [dbo].[Hr_T_LeaveRequest] ADD CONSTRAINT [CK_Hr_T_LeaveRequest_Dates] CHECK ([EndDate] >= [StartDate])
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID(N'[dbo].[CK_Hr_T_LeaveRequest_HalfDayPart]', 'C') IS NULL
|
||||||
|
ALTER TABLE [dbo].[Hr_T_LeaveRequest] ADD CONSTRAINT [CK_Hr_T_LeaveRequest_HalfDayPart] CHECK ([HalfDayPart] IS NULL OR [HalfDayPart] IN ('Morning', 'Afternoon'))
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_LeaveRequest_Employee' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_LeaveRequest]'))
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_Hr_T_LeaveRequest_Employee] ON [dbo].[Hr_T_LeaveRequest] ([TenantId], [EmployeeId], [StartDate]) WHERE [IsDeleted] = 0
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Hr_T_LeaveRequest_SickLeave' AND object_id = OBJECT_ID(N'[dbo].[Hr_T_LeaveRequest]'))
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_Hr_T_LeaveRequest_SickLeave] ON [dbo].[Hr_T_LeaveRequest] ([SickLeaveId]) WHERE [SickLeaveId] IS NOT NULL
|
||||||
|
GO
|
||||||
|
|
@ -12,6 +12,7 @@ BEGIN
|
||||||
[DeductsFromAnnualLeave] bit NOT NULL DEFAULT 0,
|
[DeductsFromAnnualLeave] bit NOT NULL DEFAULT 0,
|
||||||
[RequiresDocument] bit NOT NULL DEFAULT 0,
|
[RequiresDocument] bit NOT NULL DEFAULT 0,
|
||||||
[AllowHalfDay] bit NOT NULL DEFAULT 0,
|
[AllowHalfDay] bit NOT NULL DEFAULT 0,
|
||||||
|
[BalanceExceedAction] nvarchar(16) NOT NULL DEFAULT 'Block',
|
||||||
[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,
|
||||||
|
|
@ -27,3 +28,12 @@ BEGIN
|
||||||
) ON [PRIMARY]
|
) ON [PRIMARY]
|
||||||
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
|
||||||
|
ALTER TABLE [dbo].[Hr_T_LeaveType] ADD CONSTRAINT [CK_Hr_T_LeaveType_BalanceExceedAction] CHECK ([BalanceExceedAction] IN ('Block', 'Warn'))
|
||||||
|
GO
|
||||||
|
|
|
||||||
114
configs/seeds/host/sql/object/Hr_V_LeaveBalanceYear.sql
Normal file
114
configs/seeds/host/sql/object/Hr_V_LeaveBalanceYear.sql
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
CREATE OR ALTER VIEW [dbo].[Hr_V_LeaveBalanceYear]
|
||||||
|
AS
|
||||||
|
-- Yıllık izin defteri: çalışan başına her hak ediş yılı bir satır (İş Kanunu md.53, kademeler
|
||||||
|
-- İnsan Kaynakları ayarlarından). YearNo = 0 satırı devir/düzeltmeleri ve ilk hak edişten önce
|
||||||
|
-- kullanılan izni toplar; böylece satırların toplamı bakiyeyi verir.
|
||||||
|
WITH TenantCfg AS (
|
||||||
|
SELECT t.TenantId,
|
||||||
|
COALESCE(TRY_CAST(dbo.Hr_F_HrSetting(t.TenantId, N'App.HrSettings.Leave.AnnualDays1To5') AS decimal(5, 1)), 14) AS Days1To5,
|
||||||
|
COALESCE(TRY_CAST(dbo.Hr_F_HrSetting(t.TenantId, N'App.HrSettings.Leave.AnnualDays5To15') AS decimal(5, 1)), 20) AS Days5To15,
|
||||||
|
COALESCE(TRY_CAST(dbo.Hr_F_HrSetting(t.TenantId, N'App.HrSettings.Leave.AnnualDays15Plus') AS decimal(5, 1)), 26) AS Days15Plus,
|
||||||
|
COALESCE(TRY_CAST(dbo.Hr_F_HrSetting(t.TenantId, N'App.HrSettings.Leave.MinDaysYoungOld') AS decimal(5, 1)), 20) AS MinDaysYoungOld
|
||||||
|
FROM (SELECT DISTINCT TenantId FROM AbpUsers WHERE IsDeleted = 0) t
|
||||||
|
),
|
||||||
|
Emp AS (
|
||||||
|
SELECT u.Id AS EmployeeId, u.TenantId,
|
||||||
|
CAST(COALESCE(u.SeniorityStartDate, u.HireDate) AS date) AS SeniorityStartDate,
|
||||||
|
CAST(u.BirthDate AS date) AS BirthDate,
|
||||||
|
CAST(u.TerminationDate AS date) AS TerminationDate,
|
||||||
|
c.Days1To5, c.Days5To15, c.Days15Plus, c.MinDaysYoungOld
|
||||||
|
FROM AbpUsers u
|
||||||
|
INNER JOIN TenantCfg c ON c.TenantId = u.TenantId OR (c.TenantId IS NULL AND u.TenantId IS NULL)
|
||||||
|
WHERE u.IsDeleted = 0
|
||||||
|
),
|
||||||
|
Years AS (
|
||||||
|
SELECT e.*, n.YearNo,
|
||||||
|
DATEADD(year, n.YearNo, e.SeniorityStartDate) AS AccrualDate,
|
||||||
|
DATEADD(year, n.YearNo + 1, e.SeniorityStartDate) AS NextPeriodDate
|
||||||
|
FROM Emp e
|
||||||
|
CROSS JOIN (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15),
|
||||||
|
(16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30),
|
||||||
|
(31), (32), (33), (34), (35), (36), (37), (38), (39), (40), (41), (42), (43), (44), (45),
|
||||||
|
(46), (47), (48), (49), (50)) n (YearNo)
|
||||||
|
WHERE e.SeniorityStartDate IS NOT NULL
|
||||||
|
),
|
||||||
|
Entitlement AS (
|
||||||
|
SELECT y.*,
|
||||||
|
CASE
|
||||||
|
WHEN y.YearNo <= 5 THEN y.Days1To5
|
||||||
|
WHEN y.YearNo < 15 THEN y.Days5To15
|
||||||
|
ELSE y.Days15Plus
|
||||||
|
END AS BaseDays,
|
||||||
|
CASE
|
||||||
|
WHEN y.BirthDate IS NULL THEN NULL
|
||||||
|
ELSE DATEDIFF(year, y.BirthDate, y.AccrualDate)
|
||||||
|
- CASE WHEN DATEADD(year, DATEDIFF(year, y.BirthDate, y.AccrualDate), y.BirthDate) > y.AccrualDate THEN 1 ELSE 0 END
|
||||||
|
END AS AgeAtAccrual
|
||||||
|
FROM Years y
|
||||||
|
),
|
||||||
|
Accrued AS (
|
||||||
|
SELECT e.EmployeeId, e.TenantId, e.YearNo, e.AccrualDate, e.NextPeriodDate,
|
||||||
|
CASE
|
||||||
|
WHEN (e.AgeAtAccrual <= 18 OR e.AgeAtAccrual >= 50) AND e.BaseDays < e.MinDaysYoungOld THEN e.MinDaysYoungOld
|
||||||
|
ELSE e.BaseDays
|
||||||
|
END AS EntitledDays,
|
||||||
|
CASE WHEN e.AccrualDate <= CAST(GETDATE() AS date)
|
||||||
|
AND (e.TerminationDate IS NULL OR e.AccrualDate <= e.TerminationDate) THEN 1 ELSE 0 END AS IsAccrued
|
||||||
|
FROM Entitlement e
|
||||||
|
),
|
||||||
|
NextAccrual AS (
|
||||||
|
SELECT a.EmployeeId, MIN(a.AccrualDate) AS NextAccrualDate
|
||||||
|
FROM Accrued a
|
||||||
|
WHERE a.IsAccrued = 0
|
||||||
|
GROUP BY a.EmployeeId
|
||||||
|
),
|
||||||
|
Requests AS (
|
||||||
|
-- Yalnız yıllık izinden düşen türler; reddedilen talep bakiyeye girmez.
|
||||||
|
SELECT r.EmployeeId, CAST(r.StartDate AS date) AS StartDate, r.Days,
|
||||||
|
CASE WHEN r.ApprovalStatus = N'Onaylandı' THEN 1 ELSE 0 END AS IsApproved
|
||||||
|
FROM Hr_T_LeaveRequest r
|
||||||
|
INNER JOIN Hr_T_LeaveType t ON t.Id = r.LeaveTypeId
|
||||||
|
WHERE r.IsDeleted = 0 AND t.DeductsFromAnnualLeave = 1
|
||||||
|
AND (r.ApprovalStatus IS NULL OR r.ApprovalStatus <> N'Reddedildi')
|
||||||
|
),
|
||||||
|
Ledger AS (
|
||||||
|
SELECT a.EmployeeId, a.TenantId, a.YearNo, a.AccrualDate, DATEADD(day, -1, a.NextPeriodDate) AS PeriodEndDate,
|
||||||
|
a.EntitledDays,
|
||||||
|
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = a.EmployeeId AND r.IsApproved = 1
|
||||||
|
AND r.StartDate >= a.AccrualDate AND r.StartDate < a.NextPeriodDate), 0) AS UsedDays,
|
||||||
|
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = a.EmployeeId AND r.IsApproved = 0
|
||||||
|
AND r.StartDate >= a.AccrualDate AND r.StartDate < a.NextPeriodDate), 0) AS PendingDays
|
||||||
|
FROM Accrued a
|
||||||
|
WHERE a.IsAccrued = 1
|
||||||
|
UNION ALL
|
||||||
|
SELECT e.EmployeeId, e.TenantId, 0, NULL, NULL,
|
||||||
|
COALESCE((SELECT SUM(x.Days) FROM Hr_T_LeaveBalanceAdjustment x
|
||||||
|
WHERE x.EmployeeId = e.EmployeeId AND x.IsDeleted = 0 AND x.IsActive = 1), 0),
|
||||||
|
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = e.EmployeeId AND r.IsApproved = 1
|
||||||
|
AND (e.SeniorityStartDate IS NULL OR r.StartDate < DATEADD(year, 1, e.SeniorityStartDate))), 0),
|
||||||
|
COALESCE((SELECT SUM(r.Days) FROM Requests r WHERE r.EmployeeId = e.EmployeeId AND r.IsApproved = 0
|
||||||
|
AND (e.SeniorityStartDate IS NULL OR r.StartDate < DATEADD(year, 1, e.SeniorityStartDate))), 0)
|
||||||
|
FROM Emp e
|
||||||
|
)
|
||||||
|
SELECT CONCAT(CONVERT(nvarchar(36), l.EmployeeId), N'-', l.YearNo) AS Id,
|
||||||
|
l.TenantId,
|
||||||
|
l.EmployeeId,
|
||||||
|
CONCAT(u.Name, N' ', u.Surname) AS EmployeeName,
|
||||||
|
u.DepartmentId,
|
||||||
|
u.JobPositionId,
|
||||||
|
l.YearNo,
|
||||||
|
l.AccrualDate,
|
||||||
|
l.PeriodEndDate,
|
||||||
|
l.EntitledDays,
|
||||||
|
l.UsedDays,
|
||||||
|
l.PendingDays,
|
||||||
|
l.EntitledDays - l.UsedDays AS RemainingDays,
|
||||||
|
SUM(l.EntitledDays - l.UsedDays) OVER (PARTITION BY l.EmployeeId ORDER BY l.YearNo
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CumulativeRemainingDays,
|
||||||
|
na.NextAccrualDate,
|
||||||
|
(SELECT a.EntitledDays FROM Accrued a WHERE a.EmployeeId = l.EmployeeId AND a.AccrualDate = na.NextAccrualDate) AS NextAccrualDays
|
||||||
|
FROM Ledger l
|
||||||
|
INNER JOIN AbpUsers u ON u.Id = l.EmployeeId
|
||||||
|
LEFT JOIN NextAccrual na ON na.EmployeeId = l.EmployeeId
|
||||||
|
WHERE l.YearNo > 0 OR l.EntitledDays <> 0 OR l.UsedDays <> 0 OR l.PendingDays <> 0
|
||||||
|
GO
|
||||||
32
configs/seeds/host/sql/object/Hr_V_LeaveSummary.sql
Normal file
32
configs/seeds/host/sql/object/Hr_V_LeaveSummary.sql
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
CREATE OR ALTER VIEW [dbo].[Hr_V_LeaveSummary]
|
||||||
|
AS
|
||||||
|
-- Çalışan başına yıllık izin bakiyesi; defterin (Hr_V_LeaveBalanceYear) toplamıdır.
|
||||||
|
-- Kalan = hak edilen + düzeltme − onaylı kullanılan; Kullanılabilir = kalan − onay bekleyen.
|
||||||
|
SELECT u.Id,
|
||||||
|
u.TenantId,
|
||||||
|
u.Id AS EmployeeId,
|
||||||
|
CONCAT(u.Name, N' ', u.Surname) AS EmployeeName,
|
||||||
|
u.DepartmentId,
|
||||||
|
u.JobPositionId,
|
||||||
|
CAST(COALESCE(u.SeniorityStartDate, u.HireDate) AS date) AS SeniorityStartDate,
|
||||||
|
CASE
|
||||||
|
WHEN COALESCE(u.SeniorityStartDate, u.HireDate) IS NULL THEN NULL
|
||||||
|
ELSE DATEDIFF(year, COALESCE(u.SeniorityStartDate, u.HireDate), GETDATE())
|
||||||
|
- CASE WHEN DATEADD(year, DATEDIFF(year, COALESCE(u.SeniorityStartDate, u.HireDate), GETDATE()),
|
||||||
|
COALESCE(u.SeniorityStartDate, u.HireDate)) > GETDATE() THEN 1 ELSE 0 END
|
||||||
|
END AS ServiceYears,
|
||||||
|
CAST(COALESCE(SUM(CASE WHEN l.YearNo > 0 THEN l.EntitledDays END), 0) AS decimal(9, 1)) AS EntitledDays,
|
||||||
|
CAST(COALESCE(SUM(CASE WHEN l.YearNo = 0 THEN l.EntitledDays END), 0) AS decimal(9, 1)) AS AdjustmentDays,
|
||||||
|
CAST(COALESCE(SUM(l.UsedDays), 0) AS decimal(9, 1)) AS UsedDays,
|
||||||
|
CAST(COALESCE(SUM(l.PendingDays), 0) AS decimal(9, 1)) AS PendingDays,
|
||||||
|
CAST(COALESCE(SUM(l.EntitledDays - l.UsedDays), 0) AS decimal(9, 1)) AS RemainingDays,
|
||||||
|
CAST(COALESCE(SUM(l.EntitledDays - l.UsedDays - l.PendingDays), 0) AS decimal(9, 1)) AS AvailableDays,
|
||||||
|
MAX(l.NextAccrualDate) AS NextAccrualDate,
|
||||||
|
MAX(l.NextAccrualDays) AS NextAccrualDays,
|
||||||
|
u.IsActive
|
||||||
|
FROM AbpUsers u
|
||||||
|
LEFT JOIN Hr_V_LeaveBalanceYear l ON l.EmployeeId = u.Id
|
||||||
|
WHERE u.IsDeleted = 0
|
||||||
|
GROUP BY u.Id, u.TenantId, u.Name, u.Surname, u.DepartmentId, u.JobPositionId,
|
||||||
|
u.SeniorityStartDate, u.HireDate, u.IsActive
|
||||||
|
GO
|
||||||
|
|
@ -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.\nNote: sick leave does not affect leave balances.",
|
"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.",
|
||||||
"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.\nDikkat: rapor izin bakiyesine yansımaz."
|
"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."
|
||||||
},
|
},
|
||||||
"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": null,
|
"DeleteAfterCommand": "UPDATE Hr_T_LeaveRequest SET IsDeleted = 1, DeletionTime = GETUTCDATE(), DeleterId = @DeleterId WHERE SickLeaveId IN @Id AND IsDeleted = 0",
|
||||||
"DeleteFieldsDefaultValueDto": [
|
"DeleteFieldsDefaultValueDto": [
|
||||||
{
|
{
|
||||||
"FieldName": "DeleterId",
|
"FieldName": "DeleterId",
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
],
|
],
|
||||||
"InsertCommand": null,
|
"InsertCommand": null,
|
||||||
"InsertBeforeCommand": null,
|
"InsertBeforeCommand": null,
|
||||||
"InsertAfterCommand": null,
|
"InsertAfterCommand": "EXEC dbo.Hr_S_LeaveSickLeaveSync @Id, @CreatorId",
|
||||||
"InsertFieldsDefaultValueDto": [
|
"InsertFieldsDefaultValueDto": [
|
||||||
{
|
{
|
||||||
"FieldName": "CreationTime",
|
"FieldName": "CreationTime",
|
||||||
|
|
@ -156,8 +156,23 @@
|
||||||
],
|
],
|
||||||
"UpdateCommand": null,
|
"UpdateCommand": null,
|
||||||
"UpdateBeforeCommand": null,
|
"UpdateBeforeCommand": null,
|
||||||
"UpdateAfterCommand": null,
|
"UpdateAfterCommand": "DECLARE @_id uniqueidentifier = (SELECT TOP 1 Id FROM Adm_T_UserSickLeave WHERE Id IN @Id); EXEC dbo.Hr_S_LeaveSickLeaveSync @_id, @LastModifierId",
|
||||||
"UpdateFieldsDefaultValueDto": [],
|
"UpdateFieldsDefaultValueDto": [
|
||||||
|
{
|
||||||
|
"FieldName": "LastModificationTime",
|
||||||
|
"FieldDbType": 6,
|
||||||
|
"Value": "@NOW",
|
||||||
|
"CustomValueType": 2,
|
||||||
|
"SqlQuery": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FieldName": "LastModifierId",
|
||||||
|
"FieldDbType": 9,
|
||||||
|
"Value": "@USERID",
|
||||||
|
"CustomValueType": 2,
|
||||||
|
"SqlQuery": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
"FormFieldsDefaultValueDto": [],
|
"FormFieldsDefaultValueDto": [],
|
||||||
"WidgetsDto": [],
|
"WidgetsDto": [],
|
||||||
"ExtraFilterEditDto": [],
|
"ExtraFilterEditDto": [],
|
||||||
|
|
|
||||||
2679
configs/seeds/host/wizard/LeaveBalance.json
Normal file
2679
configs/seeds/host/wizard/LeaveBalance.json
Normal file
File diff suppressed because it is too large
Load diff
1523
configs/seeds/host/wizard/LeaveBalanceAdjustment.json
Normal file
1523
configs/seeds/host/wizard/LeaveBalanceAdjustment.json
Normal file
File diff suppressed because it is too large
Load diff
2222
configs/seeds/host/wizard/LeaveBalanceYear.json
Normal file
2222
configs/seeds/host/wizard/LeaveBalanceYear.json
Normal file
File diff suppressed because it is too large
Load diff
3719
configs/seeds/host/wizard/LeaveRequest.json
Normal file
3719
configs/seeds/host/wizard/LeaveRequest.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -32,8 +32,8 @@
|
||||||
"MenuTr": "İzin Türleri",
|
"MenuTr": "İzin Türleri",
|
||||||
"TitleEn": "Leave Types",
|
"TitleEn": "Leave Types",
|
||||||
"TitleTr": "İzin Türleri",
|
"TitleTr": "İzin Türleri",
|
||||||
"DescEn": "Leave Types — kinds of leave and their rules (annual, excuse, unpaid, sick, maternity, paternity, marriage, bereavement, nursing).\nWhere: Human Resources › Definitions › Leave Types.\nFields: code, name, gender (All/Male/Female), max days per year, paid, deducts from annual leave, document required, half-day allowed, active.\nNote: not yet linked to a leave request screen; it is the source definition for a future leave process.",
|
"DescEn": "Leave Types — kinds of leave and their rules (annual, excuse, unpaid, sick, maternity, paternity, marriage, bereavement, nursing).\nWhere: Human Resources › Definitions › Leave Types. Used by Human Resources › Leave Management and the My Leaves widget on Intranet › Dashboard.\nFields: code, name, gender (All/Male/Female — the type is offered only to that gender), max days per year, paid, deducts from annual leave (the request uses the annual balance), document required (a document must be attached), half-day allowed, when balance is exceeded (Block / Warn and save), active.\nNote: the type with code Sick is the same record as Health Card › Sick Leaves.",
|
||||||
"DescTr": "İ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).\nNerede: İnsan Kaynakları › Tanımlamalar › İzin Türleri.\nAlanlar: kod, ad, cinsiyet (Tümü/Erkek/Kadın), yıllık en fazla gün, ücretli, yıllık izinden düşer, belge gerekir, yarım gün kullanılabilir, aktif.\nDikkat: henüz bir izin talep ekranına bağlı değildir; izin talep süreci kurulduğunda kaynak tanım olarak kullanılacaktır.",
|
"DescTr": "İ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).\nNerede: İnsan Kaynakları › Tanımlamalar › İzin Türleri. İnsan Kaynakları › İzin Yönetimi ve Intranet › Dashboard'daki İzinlerim widget'ı kullanır.\nAlanlar: kod, ad, cinsiyet (Tümü/Erkek/Kadın — tür yalnız o cinsiyete sunulur), yıllık en fazla gün, ücretli, yıllık izinden düşer (talep yıllık bakiyeden düşülür), belge gerekir (talepte belge zorunlu), yarım gün kullanılabilir, bakiye aşılırsa (Talebi engelle / Uyar ve kaydet), aktif.\nDikkat: kodu Sick olan tür Sağlık Kartı › İstirahatler ile aynı kayıttır.",
|
||||||
"Texts": [
|
"Texts": [
|
||||||
{
|
{
|
||||||
"Key": "App.Widget.Paid",
|
"Key": "App.Widget.Paid",
|
||||||
|
|
@ -44,6 +44,16 @@
|
||||||
"Key": "App.Widget.Unpaid",
|
"Key": "App.Widget.Unpaid",
|
||||||
"En": "Unpaid",
|
"En": "Unpaid",
|
||||||
"Tr": "Ücretsiz"
|
"Tr": "Ücretsiz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Key": "App.Hr.LeaveType.BalanceExceedAction.Block",
|
||||||
|
"En": "Block the request",
|
||||||
|
"Tr": "Talebi engelle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Key": "App.Hr.LeaveType.BalanceExceedAction.Warn",
|
||||||
|
"En": "Warn and save",
|
||||||
|
"Tr": "Uyar ve kaydet"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -104,6 +114,12 @@
|
||||||
"En": "Half Day Allowed",
|
"En": "Half Day Allowed",
|
||||||
"Tr": "Yarım Gün Kullanılabilir"
|
"Tr": "Yarım Gün Kullanılabilir"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"FieldName": "BalanceExceedAction",
|
||||||
|
"CaptionName": "App.Listform.ListformField.BalanceExceedAction",
|
||||||
|
"En": "When Balance Is Exceeded",
|
||||||
|
"Tr": "Bakiye Aşılırsa"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"FieldName": "IsActive",
|
"FieldName": "IsActive",
|
||||||
"CaptionName": "App.Listform.ListformField.IsActive",
|
"CaptionName": "App.Listform.ListformField.IsActive",
|
||||||
|
|
@ -225,6 +241,13 @@
|
||||||
"Value": "true",
|
"Value": "true",
|
||||||
"CustomValueType": 1,
|
"CustomValueType": 1,
|
||||||
"SqlQuery": ""
|
"SqlQuery": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FieldName": "BalanceExceedAction",
|
||||||
|
"FieldDbType": 16,
|
||||||
|
"Value": "Block",
|
||||||
|
"CustomValueType": 1,
|
||||||
|
"SqlQuery": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"WidgetsDto": [
|
"WidgetsDto": [
|
||||||
|
|
@ -1977,6 +2000,144 @@
|
||||||
"CreatorId": null,
|
"CreatorId": null,
|
||||||
"Id": "00000000-0000-0000-0000-000000000000"
|
"Id": "00000000-0000-0000-0000-000000000000"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"EditType": null,
|
||||||
|
"ListFormCode": "App.Hr.LeaveType",
|
||||||
|
"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": "BalanceExceedAction",
|
||||||
|
"CaptionName": "App.Listform.ListformField.BalanceExceedAction",
|
||||||
|
"PlaceHolder": null,
|
||||||
|
"ReadOnly": false,
|
||||||
|
"Visible": true,
|
||||||
|
"IsActive": true,
|
||||||
|
"Width": 0,
|
||||||
|
"ListOrderNo": 10,
|
||||||
|
"SourceDbType": 16,
|
||||||
|
"CultureName": "en",
|
||||||
|
"DataType": "string",
|
||||||
|
"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": 1,
|
||||||
|
"ValueExpr": "key",
|
||||||
|
"DisplayExpr": "name",
|
||||||
|
"CascadeRelationField": null,
|
||||||
|
"CascadeFilterOperator": "=",
|
||||||
|
"CascadeParentFields": null,
|
||||||
|
"CascadeEmptyFields": null,
|
||||||
|
"LookupQuery": "[{\"key\":\"Block\",\"name\":\"App.Hr.LeaveType.BalanceExceedAction.Block\"},{\"key\":\"Warn\",\"name\":\"App.Hr.LeaveType.BalanceExceedAction.Warn\"}]"
|
||||||
|
},
|
||||||
|
"ValidationRuleDto": [
|
||||||
|
{
|
||||||
|
"Type": "required",
|
||||||
|
"Message": null,
|
||||||
|
"IgnoreEmptyValue": false,
|
||||||
|
"Reevaluate": true,
|
||||||
|
"ComparisonType": "",
|
||||||
|
"Pattern": "",
|
||||||
|
"Max": null,
|
||||||
|
"Min": null,
|
||||||
|
"Trim": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ColumnStylingDto": [],
|
||||||
|
"PermissionDto": {
|
||||||
|
"Deny": false,
|
||||||
|
"C": "App.Hr.LeaveType.Create",
|
||||||
|
"R": "App.Hr.LeaveType",
|
||||||
|
"U": "App.Hr.LeaveType.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": null,
|
||||||
|
"Format": null,
|
||||||
|
"EditOrderNo": 9,
|
||||||
|
"EditGroupOrderNo": 1,
|
||||||
|
"EditorType2": "dxRadioGroup",
|
||||||
|
"ColSpan": 1,
|
||||||
|
"EditorOptions": "{\"layout\":\"horizontal\"}",
|
||||||
|
"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,
|
"EditType": null,
|
||||||
"ListFormCode": "App.Hr.LeaveType",
|
"ListFormCode": "App.Hr.LeaveType",
|
||||||
|
|
@ -2000,7 +2161,7 @@
|
||||||
"Visible": true,
|
"Visible": true,
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"Width": 0,
|
"Width": 0,
|
||||||
"ListOrderNo": 10,
|
"ListOrderNo": 11,
|
||||||
"SourceDbType": 3,
|
"SourceDbType": 3,
|
||||||
"CultureName": "en",
|
"CultureName": "en",
|
||||||
"DataType": "boolean",
|
"DataType": "boolean",
|
||||||
|
|
@ -2100,7 +2261,7 @@
|
||||||
},
|
},
|
||||||
"Alignment": null,
|
"Alignment": null,
|
||||||
"Format": null,
|
"Format": null,
|
||||||
"EditOrderNo": 9,
|
"EditOrderNo": 10,
|
||||||
"EditGroupOrderNo": 1,
|
"EditGroupOrderNo": 1,
|
||||||
"EditorType2": "dxCheckBox",
|
"EditorType2": "dxCheckBox",
|
||||||
"ColSpan": 1,
|
"ColSpan": 1,
|
||||||
|
|
@ -2129,7 +2290,10 @@
|
||||||
"App.Listform.ListformField.IsPaid",
|
"App.Listform.ListformField.IsPaid",
|
||||||
"App.Listform.ListformField.DeductsFromAnnualLeave",
|
"App.Listform.ListformField.DeductsFromAnnualLeave",
|
||||||
"App.Listform.ListformField.RequiresDocument",
|
"App.Listform.ListformField.RequiresDocument",
|
||||||
"App.Listform.ListformField.AllowHalfDay"
|
"App.Listform.ListformField.AllowHalfDay",
|
||||||
|
"App.Listform.ListformField.BalanceExceedAction",
|
||||||
|
"App.Hr.LeaveType.BalanceExceedAction.Block",
|
||||||
|
"App.Hr.LeaveType.BalanceExceedAction.Warn"
|
||||||
],
|
],
|
||||||
"PermissionGroupNames": [],
|
"PermissionGroupNames": [],
|
||||||
"PermissionNames": [
|
"PermissionNames": [
|
||||||
|
|
|
||||||
|
|
@ -1471,29 +1471,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.262016+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.My360FeedbackScore",
|
|
||||||
"App.Hr.My360FeedbackScore.Title",
|
|
||||||
"App.Hr.My360FeedbackScore.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.My360FeedbackScore",
|
|
||||||
"App.Hr.My360FeedbackScore.Create",
|
|
||||||
"App.Hr.My360FeedbackScore.Update",
|
|
||||||
"App.Hr.My360FeedbackScore.Delete",
|
|
||||||
"App.Hr.My360FeedbackScore.Export",
|
|
||||||
"App.Hr.My360FeedbackScore.Import",
|
|
||||||
"App.Hr.My360FeedbackScore.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2878,29 +2878,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.5541252+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.MyDevelopmentPlan",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Title",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.MyDevelopmentPlan",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Create",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Update",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Delete",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Export",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Import",
|
|
||||||
"App.Hr.MyDevelopmentPlan.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2214
configs/seeds/host/wizard/MyLeaveBalance.json
Normal file
2214
configs/seeds/host/wizard/MyLeaveBalance.json
Normal file
File diff suppressed because it is too large
Load diff
2875
configs/seeds/host/wizard/MyLeaveRequest.json
Normal file
2875
configs/seeds/host/wizard/MyLeaveRequest.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1999,29 +1999,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.5694024+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.MyPerformanceCompetency",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Title",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.MyPerformanceCompetency",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Create",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Update",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Delete",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Export",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Import",
|
|
||||||
"App.Hr.MyPerformanceCompetency.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2630,29 +2630,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.5823584+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.MyPerformanceGoal",
|
|
||||||
"App.Hr.MyPerformanceGoal.Title",
|
|
||||||
"App.Hr.MyPerformanceGoal.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.MyPerformanceGoal",
|
|
||||||
"App.Hr.MyPerformanceGoal.Create",
|
|
||||||
"App.Hr.MyPerformanceGoal.Update",
|
|
||||||
"App.Hr.MyPerformanceGoal.Delete",
|
|
||||||
"App.Hr.MyPerformanceGoal.Export",
|
|
||||||
"App.Hr.MyPerformanceGoal.Import",
|
|
||||||
"App.Hr.MyPerformanceGoal.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3665,31 +3665,5 @@
|
||||||
],
|
],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.6070208+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.PerformanceCalibration",
|
|
||||||
"App.Hr.PerformanceCalibration.Title",
|
|
||||||
"App.Hr.PerformanceCalibration.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.PerformanceCalibration",
|
|
||||||
"App.Hr.PerformanceCalibration.Create",
|
|
||||||
"App.Hr.PerformanceCalibration.Update",
|
|
||||||
"App.Hr.PerformanceCalibration.Delete",
|
|
||||||
"App.Hr.PerformanceCalibration.Export",
|
|
||||||
"App.Hr.PerformanceCalibration.Import",
|
|
||||||
"App.Hr.PerformanceCalibration.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [
|
|
||||||
"App.Hr.PerformanceCalibration"
|
|
||||||
],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1481,31 +1481,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.6309017+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.PerformanceFeedbackScore",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Title",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Desc",
|
|
||||||
"App.Listform.ListformField.FeedbackId",
|
|
||||||
"App.Listform.ListformField.LevelId"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.PerformanceFeedbackScore",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Create",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Update",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Delete",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Export",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Import",
|
|
||||||
"App.Hr.PerformanceFeedbackScore.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1915,34 +1915,5 @@
|
||||||
],
|
],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.6542592+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.PerformanceRating",
|
|
||||||
"App.Hr.PerformanceRating.Title",
|
|
||||||
"App.Hr.PerformanceRating.Desc",
|
|
||||||
"App.Listform.ListformField.MinScore",
|
|
||||||
"App.Listform.ListformField.MaxScore",
|
|
||||||
"App.Listform.ListformField.TargetDistribution"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.PerformanceRating",
|
|
||||||
"App.Hr.PerformanceRating.Create",
|
|
||||||
"App.Hr.PerformanceRating.Update",
|
|
||||||
"App.Hr.PerformanceRating.Delete",
|
|
||||||
"App.Hr.PerformanceRating.Export",
|
|
||||||
"App.Hr.PerformanceRating.Import",
|
|
||||||
"App.Hr.PerformanceRating.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [
|
|
||||||
"App.Hr.PerformanceRating"
|
|
||||||
],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2855,29 +2855,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.7032225+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.TeamDevelopmentPlan",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Title",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.TeamDevelopmentPlan",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Create",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Update",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Delete",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Export",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Import",
|
|
||||||
"App.Hr.TeamDevelopmentPlan.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3430
configs/seeds/host/wizard/TeamLeaveRequest.json
Normal file
3430
configs/seeds/host/wizard/TeamLeaveRequest.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2007,29 +2007,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.7146321+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.TeamPerformanceCompetency",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Title",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.TeamPerformanceCompetency",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Create",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Update",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Delete",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Export",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Import",
|
|
||||||
"App.Hr.TeamPerformanceCompetency.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2608,29 +2608,5 @@
|
||||||
"MenuCodes": [],
|
"MenuCodes": [],
|
||||||
"DataSourceCodes": [],
|
"DataSourceCodes": [],
|
||||||
"ModuleIds": []
|
"ModuleIds": []
|
||||||
},
|
|
||||||
"Pending": {
|
|
||||||
"Since": "2026-10-04T17:38:14.7265586+03:00",
|
|
||||||
"Replaced": {
|
|
||||||
"LanguageKeys": [
|
|
||||||
"App.Hr.TeamPerformanceGoal",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Title",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Desc"
|
|
||||||
],
|
|
||||||
"PermissionGroupNames": [],
|
|
||||||
"PermissionNames": [
|
|
||||||
"App.Hr.TeamPerformanceGoal",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Create",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Update",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Delete",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Export",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Import",
|
|
||||||
"App.Hr.TeamPerformanceGoal.Note"
|
|
||||||
],
|
|
||||||
"MenuCodes": [],
|
|
||||||
"DataSourceCodes": [],
|
|
||||||
"ModuleIds": []
|
|
||||||
},
|
|
||||||
"ListFormCodes": []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4498,6 +4498,7 @@ 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
|
||||||
|
|
@ -4512,6 +4513,7 @@ bg-gray-950
|
||||||
bg-gray-950/80
|
bg-gray-950/80
|
||||||
bg-green-700
|
bg-green-700
|
||||||
bg-indigo-50
|
bg-indigo-50
|
||||||
|
bg-orange-100
|
||||||
bg-purple-700
|
bg-purple-700
|
||||||
bg-red-50
|
bg-red-50
|
||||||
bg-red-600
|
bg-red-600
|
||||||
|
|
@ -4520,6 +4522,7 @@ bg-sky-600
|
||||||
bg-slate-100
|
bg-slate-100
|
||||||
bg-slate-300
|
bg-slate-300
|
||||||
bg-slate-50
|
bg-slate-50
|
||||||
|
bg-teal-600
|
||||||
bg-white
|
bg-white
|
||||||
bg-white/10
|
bg-white/10
|
||||||
bg-white/20
|
bg-white/20
|
||||||
|
|
@ -4534,6 +4537,7 @@ border-collapse
|
||||||
border-dashed
|
border-dashed
|
||||||
border-gray-200
|
border-gray-200
|
||||||
border-gray-200/50
|
border-gray-200/50
|
||||||
|
border-gray-300
|
||||||
border-indigo-200
|
border-indigo-200
|
||||||
border-l-4
|
border-l-4
|
||||||
border-slate-100
|
border-slate-100
|
||||||
|
|
@ -4552,12 +4556,14 @@ dark:bg-gray-900/40
|
||||||
dark:bg-gray-950
|
dark:bg-gray-950
|
||||||
dark:bg-gray-950/45
|
dark:bg-gray-950/45
|
||||||
dark:bg-indigo-900/30
|
dark:bg-indigo-900/30
|
||||||
|
dark:bg-orange-900/40
|
||||||
dark:bg-red-950
|
dark:bg-red-950
|
||||||
dark:bg-slate-700
|
dark:bg-slate-700
|
||||||
dark:bg-slate-800
|
dark:bg-slate-800
|
||||||
dark:bg-slate-900
|
dark:bg-slate-900
|
||||||
dark:block
|
dark:block
|
||||||
dark:border-amber-800
|
dark:border-amber-800
|
||||||
|
dark:border-gray-600
|
||||||
dark:border-gray-700
|
dark:border-gray-700
|
||||||
dark:border-gray-700/50
|
dark:border-gray-700/50
|
||||||
dark:border-gray-800
|
dark:border-gray-800
|
||||||
|
|
@ -4568,6 +4574,7 @@ dark:divide-gray-700
|
||||||
dark:from-gray-950
|
dark:from-gray-950
|
||||||
dark:hidden
|
dark:hidden
|
||||||
dark:hover:!bg-transparent
|
dark:hover:!bg-transparent
|
||||||
|
dark:hover:bg-gray-700
|
||||||
dark:hover:bg-slate-800
|
dark:hover:bg-slate-800
|
||||||
dark:hover:bg-slate-800/70
|
dark:hover:bg-slate-800/70
|
||||||
dark:hover:text-gray-300
|
dark:hover:text-gray-300
|
||||||
|
|
@ -4583,6 +4590,7 @@ dark:text-gray-400
|
||||||
dark:text-green-400
|
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-red-200
|
dark:text-red-200
|
||||||
dark:text-red-400
|
dark:text-red-400
|
||||||
dark:text-slate-100
|
dark:text-slate-100
|
||||||
|
|
@ -4628,9 +4636,11 @@ h-full
|
||||||
hidden
|
hidden
|
||||||
hover:!bg-transparent
|
hover:!bg-transparent
|
||||||
hover:bg-blue-50
|
hover:bg-blue-50
|
||||||
|
hover:bg-gray-50
|
||||||
hover:bg-red-700
|
hover:bg-red-700
|
||||||
hover:bg-sky-700
|
hover:bg-sky-700
|
||||||
hover:bg-slate-50
|
hover:bg-slate-50
|
||||||
|
hover:bg-teal-700
|
||||||
hover:bg-white/10
|
hover:bg-white/10
|
||||||
hover:bg-white/20
|
hover:bg-white/20
|
||||||
hover:border-sky-400
|
hover:border-sky-400
|
||||||
|
|
@ -4700,6 +4710,7 @@ object-contain
|
||||||
opacity-20
|
opacity-20
|
||||||
overflow-auto
|
overflow-auto
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
|
p-2
|
||||||
p-3
|
p-3
|
||||||
p-4
|
p-4
|
||||||
p-5
|
p-5
|
||||||
|
|
@ -4714,10 +4725,14 @@ pt-20
|
||||||
pt-3
|
pt-3
|
||||||
pt-40
|
pt-40
|
||||||
pt-6
|
pt-6
|
||||||
|
px-1.5
|
||||||
|
px-2
|
||||||
px-3
|
px-3
|
||||||
px-4
|
px-4
|
||||||
px-6
|
px-6
|
||||||
px-8
|
px-8
|
||||||
|
py-0.5
|
||||||
|
py-1
|
||||||
py-1.5
|
py-1.5
|
||||||
py-10
|
py-10
|
||||||
py-12
|
py-12
|
||||||
|
|
@ -4728,6 +4743,7 @@ py-3
|
||||||
py-4
|
py-4
|
||||||
py-6
|
py-6
|
||||||
relative
|
relative
|
||||||
|
rounded
|
||||||
rounded-2xl
|
rounded-2xl
|
||||||
rounded-lg
|
rounded-lg
|
||||||
rounded-md
|
rounded-md
|
||||||
|
|
@ -4738,11 +4754,13 @@ shadow-lg
|
||||||
shadow-md
|
shadow-md
|
||||||
shadow-sm
|
shadow-sm
|
||||||
shadow-xl
|
shadow-xl
|
||||||
|
shrink-0
|
||||||
sm:grid-cols-2
|
sm:grid-cols-2
|
||||||
space-x-2
|
space-x-2
|
||||||
space-x-3
|
space-x-3
|
||||||
space-x-4
|
space-x-4
|
||||||
space-x-6
|
space-x-6
|
||||||
|
space-y-1
|
||||||
space-y-2
|
space-y-2
|
||||||
space-y-3
|
space-y-3
|
||||||
space-y-4
|
space-y-4
|
||||||
|
|
@ -4770,6 +4788,8 @@ text-indigo-500
|
||||||
text-indigo-600
|
text-indigo-600
|
||||||
text-left
|
text-left
|
||||||
text-lg
|
text-lg
|
||||||
|
text-orange-500
|
||||||
|
text-orange-700
|
||||||
text-purple-500
|
text-purple-500
|
||||||
text-purple-600
|
text-purple-600
|
||||||
text-red-500
|
text-red-500
|
||||||
|
|
@ -4781,6 +4801,7 @@ text-slate-600
|
||||||
text-slate-700
|
text-slate-700
|
||||||
text-slate-800
|
text-slate-800
|
||||||
text-sm
|
text-sm
|
||||||
|
text-teal-500
|
||||||
text-white
|
text-white
|
||||||
text-xl
|
text-xl
|
||||||
text-xs
|
text-xs
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ type NotificationListItem = {
|
||||||
creatorId: string
|
creatorId: string
|
||||||
tenantId?: string
|
tenantId?: string
|
||||||
notificationType: string
|
notificationType: string
|
||||||
|
/** Satır başlığı: kaydın çevrilmiş konusu, yoksa tip adı. */
|
||||||
|
title: string
|
||||||
message: string
|
message: string
|
||||||
date: string
|
date: string
|
||||||
readed: boolean
|
readed: boolean
|
||||||
|
|
@ -113,6 +115,7 @@ const groupNotifications = (items: NotificationDto[]): NotificationListItem[] =>
|
||||||
ids: [item.id],
|
ids: [item.id],
|
||||||
channels: [item.notificationChannel],
|
channels: [item.notificationChannel],
|
||||||
notificationType: item.notificationType,
|
notificationType: item.notificationType,
|
||||||
|
title: item.subject || item.notificationType,
|
||||||
message: item.message,
|
message: item.message,
|
||||||
date,
|
date,
|
||||||
creatorId: item.creatorId as string,
|
creatorId: item.creatorId as string,
|
||||||
|
|
@ -239,7 +242,7 @@ const NotificationDropdown = ({ className }: { className?: string }) => {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = notification.notificationType || APP_NAME
|
const title = notification.subject || notification.notificationType || APP_NAME
|
||||||
const options: NotificationOptions = {
|
const options: NotificationOptions = {
|
||||||
body: notification.message,
|
body: notification.message,
|
||||||
dir: 'ltr',
|
dir: 'ltr',
|
||||||
|
|
@ -425,8 +428,8 @@ const NotificationDropdown = ({ className }: { className?: string }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="ltr:ml-3 rtl:mr-3 ltr:mr-6 rtl:ml-6 min-w-0">
|
<div className="ltr:ml-3 rtl:mr-3 ltr:mr-6 rtl:ml-6 min-w-0">
|
||||||
<div>
|
<div>
|
||||||
{item.notificationType && (
|
{item.title && (
|
||||||
<span className="font-semibold heading-text">{item.notificationType} </span>
|
<span className="font-semibold heading-text">{item.title} </span>
|
||||||
)}
|
)}
|
||||||
<div>{item.message}</div>
|
<div>{item.message}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ export interface NotificationDto {
|
||||||
id: string
|
id: string
|
||||||
notificationChannel: string
|
notificationChannel: string
|
||||||
notificationType: string
|
notificationType: string
|
||||||
|
/** Çevrilmiş başlık; boşsa tip adı gösterilir. */
|
||||||
|
subject?: string | null
|
||||||
message: string
|
message: string
|
||||||
isRead: boolean
|
isRead: boolean
|
||||||
/** Kullanıcıya iletildi mi; okundu işareti yalnızca iletilmiş kayıtta yazılabilir. */
|
/** Kullanıcıya iletildi mi; okundu işareti yalnızca iletilmiş kayıtta yazılabilir. */
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* yeniden derlenir.
|
* yeniden derlenir.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import apiService from '@/services/api.service'
|
||||||
import { getLocalization } from '@/services/localization.service'
|
import { getLocalization } from '@/services/localization.service'
|
||||||
import { store } from '@/store'
|
import { store } from '@/store'
|
||||||
|
|
||||||
|
|
@ -120,9 +121,16 @@ const buildHelpers = ({
|
||||||
data[resolveKey(data, field) ?? field] = e.value
|
data[resolveKey(data, field) ?? field] = e.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lookup satırı değişen editörün seçimidir. Form olayları (`onFieldDataChanged`, form sayfası)
|
||||||
|
// bileşen olarak formu verir; formda `selectedItem` olmadığı için seçim alanın editöründen okunur,
|
||||||
|
// yoksa `copy` / `selected()` sessizce boş kalırdı.
|
||||||
let selectedItem: any = null
|
let selectedItem: any = null
|
||||||
try {
|
try {
|
||||||
selectedItem = e?.component?.option ? e.component.option('selectedItem') : null
|
const component = e?.component
|
||||||
|
selectedItem =
|
||||||
|
component?.option?.('selectedItem') ??
|
||||||
|
(field ? component?.getEditor?.(field)?.option?.('selectedItem') : null) ??
|
||||||
|
null
|
||||||
} catch {
|
} catch {
|
||||||
selectedItem = null
|
selectedItem = null
|
||||||
}
|
}
|
||||||
|
|
@ -248,7 +256,20 @@ const buildHelpers = ({
|
||||||
const openUrl = (url: string, target: string = '_blank') => window.open(tpl(url), target)
|
const openUrl = (url: string, target: string = '_blank') => window.open(tpl(url), target)
|
||||||
|
|
||||||
const api = async (url: string, responsePath?: string, options?: Parameters<typeof fetch>[1]) => {
|
const api = async (url: string, responsePath?: string, options?: Parameters<typeof fetch>[1]) => {
|
||||||
const response = await fetch(tpl(url), options)
|
const target = tpl(url)
|
||||||
|
// Uygulamanın kendi ucu oturum ve kiracı başlığı ister; fetch bunları taşımadığı için
|
||||||
|
// istek platform istemcisinden geçer (ör. ekranın lookup ucu: /api/app/list-form-select/lookup).
|
||||||
|
if (target.startsWith('/api/')) {
|
||||||
|
const body = typeof options?.body === 'string' ? JSON.parse(options.body) : options?.body
|
||||||
|
const response = await apiService.fetchData({
|
||||||
|
url: target,
|
||||||
|
method: options?.method ?? 'GET',
|
||||||
|
data: body as Record<string, unknown> | undefined,
|
||||||
|
})
|
||||||
|
return responsePath ? pickPath(response.data, responsePath) : response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(target, options)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
return responsePath ? pickPath(json, responsePath) : json
|
return responsePath ? pickPath(json, responsePath) : json
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ const Event = ({ data }: EventProps) => {
|
||||||
<>
|
<>
|
||||||
<div className="my-1 flex flex-wrap items-center">
|
<div className="my-1 flex flex-wrap items-center">
|
||||||
<div>
|
<div>
|
||||||
<HighlightedText>{data.notificationType}</HighlightedText>{' '}
|
<HighlightedText>{data.subject || data.notificationType}</HighlightedText>{' '}
|
||||||
{translate('::Abp.Identity.ActivityLogs.SentNotification')}
|
{translate('::Abp.Identity.ActivityLogs.SentNotification')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,18 @@ export function WorkflowCriteria({
|
||||||
)
|
)
|
||||||
const defaultCompareColumn =
|
const defaultCompareColumn =
|
||||||
numericCompareColumn?.columnName ?? compareColumnOptions[0]?.value ?? 'Price'
|
numericCompareColumn?.columnName ?? compareColumnOptions[0]?.value ?? 'Price'
|
||||||
|
// Onaycı kayda göre değişiyorsa (ör. çalışanın departman müdürü) düğüme kullanıcı yerine
|
||||||
|
// kaydın bir alanı "@Alan" olarak yazılır; motor onaycıyı o alandan okur.
|
||||||
|
const approverOptions = useMemo(
|
||||||
|
() => [
|
||||||
|
...userList,
|
||||||
|
...selectCommandColumns.map((column) => ({
|
||||||
|
value: `@${column.columnName}`,
|
||||||
|
label: translate('::App.ListFormWorkflow.ApproverField', { field: column.columnName }),
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
[selectCommandColumns, translate, userList],
|
||||||
|
)
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (formValues.kind !== 'Compare' || !compareColumnOptions.length) {
|
if (formValues.kind !== 'Compare' || !compareColumnOptions.length) {
|
||||||
|
|
@ -273,7 +285,7 @@ export function WorkflowCriteria({
|
||||||
<FormItem asterisk label={translate('::App.Listform.ListformField.Approver')}>
|
<FormItem asterisk label={translate('::App.Listform.ListformField.Approver')}>
|
||||||
<MultiSelectField
|
<MultiSelectField
|
||||||
required
|
required
|
||||||
options={userList}
|
options={approverOptions}
|
||||||
value={formValues.approver}
|
value={formValues.approver}
|
||||||
onChange={(value) => setField('approver', value)}
|
onChange={(value) => setField('approver', value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ import {
|
||||||
FaPercent,
|
FaPercent,
|
||||||
FaUpload,
|
FaUpload,
|
||||||
FaHourglassHalf,
|
FaHourglassHalf,
|
||||||
|
FaUmbrellaBeach,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import {
|
import {
|
||||||
CircleStencil,
|
CircleStencil,
|
||||||
|
|
@ -96,6 +97,7 @@ import HealthCardTab from './HealthCardTab'
|
||||||
import EducationSkillsTab from './EducationSkillsTab'
|
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 {
|
import {
|
||||||
CheckboxField,
|
CheckboxField,
|
||||||
DateField,
|
DateField,
|
||||||
|
|
@ -335,6 +337,9 @@ function UserDetails() {
|
||||||
<TabNav value="health" icon={<FaHeartbeat className="text-sm" />}>
|
<TabNav value="health" icon={<FaHeartbeat className="text-sm" />}>
|
||||||
{translate('::Abp.Identity.User.HealthCard')}
|
{translate('::Abp.Identity.User.HealthCard')}
|
||||||
</TabNav>
|
</TabNav>
|
||||||
|
<TabNav value="leaves" icon={<FaUmbrellaBeach className="text-sm" />}>
|
||||||
|
{translate('::Abp.Identity.User.Leaves')}
|
||||||
|
</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>
|
||||||
|
|
@ -1054,6 +1059,12 @@ function UserDetails() {
|
||||||
</div>
|
</div>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
|
|
||||||
|
<TabContent value="leaves">
|
||||||
|
<div className="px-4 py-2">
|
||||||
|
<LeaveTab userId={userDetails.id!} />
|
||||||
|
</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} />
|
||||||
|
|
|
||||||
110
ui/src/views/admin/user-management/LeaveTab.tsx
Normal file
110
ui/src/views/admin/user-management/LeaveTab.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
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 BALANCE = 'App.Hr.LeaveBalance'
|
||||||
|
const REQUESTS = 'App.Hr.LeaveRequest'
|
||||||
|
const LEDGER = 'App.Hr.LeaveBalanceYear'
|
||||||
|
|
||||||
|
type LeaveSummary = {
|
||||||
|
EntitledDays?: number
|
||||||
|
AdjustmentDays?: number
|
||||||
|
UsedDays?: number
|
||||||
|
PendingDays?: number
|
||||||
|
RemainingDays?: number
|
||||||
|
AvailableDays?: number
|
||||||
|
ServiceYears?: number
|
||||||
|
NextAccrualDate?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDays = (value?: number) => {
|
||||||
|
const number = Number(value ?? 0)
|
||||||
|
return Number.isInteger(number) ? String(number) : number.toFixed(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** İzin özeti İzin Bakiyeleri ekranının sorgusundan okunur; yetki ve kiracı süzmesi ListForm'da kalır. */
|
||||||
|
function LeaveTab({ userId }: { userId: string }) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
|
const { checkPermission } = usePermission()
|
||||||
|
const [summary, setSummary] = useState<LeaveSummary>()
|
||||||
|
const canSeeBalance = checkPermission(BALANCE)
|
||||||
|
|
||||||
|
// Yeni izin 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 (!canSeeBalance) return
|
||||||
|
let active = true
|
||||||
|
apiService
|
||||||
|
.fetchData<{ data?: LeaveSummary[] }>({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/app/list-form-select/select',
|
||||||
|
params: { listFormCode: BALANCE, filter: JSON.stringify(['Id', '=', userId]), take: 1 },
|
||||||
|
})
|
||||||
|
.then((response) => active && setSummary(response.data?.data?.[0]))
|
||||||
|
.catch(() => active && setSummary(undefined))
|
||||||
|
return () => {
|
||||||
|
active = false
|
||||||
|
}
|
||||||
|
}, [canSeeBalance, userId])
|
||||||
|
|
||||||
|
const field = (name: string) => translate(`::App.Listform.ListformField.${name}`)
|
||||||
|
const cards: [string, number | undefined, string][] = [
|
||||||
|
['EntitledDays', summary?.EntitledDays, 'text-gray-900 dark:text-gray-100'],
|
||||||
|
['AdjustmentDays', summary?.AdjustmentDays, 'text-gray-900 dark:text-gray-100'],
|
||||||
|
['UsedDays', summary?.UsedDays, 'text-gray-900 dark:text-gray-100'],
|
||||||
|
['PendingDays', summary?.PendingDays, 'text-orange-500'],
|
||||||
|
[
|
||||||
|
'RemainingDays',
|
||||||
|
summary?.RemainingDays,
|
||||||
|
Number(summary?.RemainingDays ?? 0) < 0 ? 'text-red-600' : 'text-teal-600',
|
||||||
|
],
|
||||||
|
['AvailableDays', summary?.AvailableDays, 'text-indigo-600'],
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
{canSeeBalance && (
|
||||||
|
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-6">
|
||||||
|
{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}`}>{formatDays(value)}</div>
|
||||||
|
<div className="text-xs text-gray-500 dark:text-gray-400">{field(name)}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{checkPermission(REQUESTS) && (
|
||||||
|
<div>
|
||||||
|
<h6 className="mb-2">{translate(`::${REQUESTS}`)}</h6>
|
||||||
|
<PlatformViewHost
|
||||||
|
view="List"
|
||||||
|
listFormCode={REQUESTS}
|
||||||
|
height="360px"
|
||||||
|
searchParams={employeeSearchParams}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{checkPermission(LEDGER) && (
|
||||||
|
<div>
|
||||||
|
<h6 className="mb-2">{translate(`::${LEDGER}`)}</h6>
|
||||||
|
<PlatformViewHost
|
||||||
|
view="List"
|
||||||
|
listFormCode={LEDGER}
|
||||||
|
height="320px"
|
||||||
|
searchParams={employeeSearchParams}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LeaveTab
|
||||||
|
|
@ -419,6 +419,11 @@ const FormDevExpress = (props: {
|
||||||
onFieldDataChanged={(e: FieldDataChangedEvent) => {
|
onFieldDataChanged={(e: FieldDataChangedEvent) => {
|
||||||
if (!e.dataField) return
|
if (!e.dataField) return
|
||||||
|
|
||||||
|
// DevExtreme değeri formData nesnesine yerinde yazar; o durumda hasChanges false kalır ve
|
||||||
|
// state yenilenmez. Script'ler formDataRef'ten çalıştığı için ref her değişimde güncellenir,
|
||||||
|
// yoksa sonraki commit script'siz alanların değerini (ör. lookup seçimi) eski kopyayla ezerdi.
|
||||||
|
formDataRef.current = { ...formDataRef.current, [e.dataField]: e.value }
|
||||||
|
|
||||||
const newFormData = { ...formData, [e.dataField]: e.value }
|
const newFormData = { ...formData, [e.dataField]: e.value }
|
||||||
let hasChanges = !Object.is(formData?.[e.dataField], e.value)
|
let hasChanges = !Object.is(formData?.[e.dataField], e.value)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue