From 03c3fcd6f04adb672702c5d09adac91e37eea25c Mon Sep 17 00:00:00 2001 From: sanjeok77 Date: Thu, 12 Mar 2026 21:25:55 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=97=B0=EC=B0=A8=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(AnnualLeave=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0,=20DAO,=20Repository)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- .../com/example/shiftalarm/AppDatabase.kt | 2 +- .../java/com/example/shiftalarm/Entities.kt | 12 +++++- .../java/com/example/shiftalarm/ShiftDao.kt | 20 ++++++++- .../com/example/shiftalarm/ShiftRepository.kt | 43 +++++++++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/shiftalarm/AppDatabase.kt b/app/src/main/java/com/example/shiftalarm/AppDatabase.kt index 3ce0004..c629728 100644 --- a/app/src/main/java/com/example/shiftalarm/AppDatabase.kt +++ b/app/src/main/java/com/example/shiftalarm/AppDatabase.kt @@ -3,7 +3,7 @@ package com.example.shiftalarm import android.content.Context import androidx.room.* -@Database(entities = [ShiftOverride::class, DailyMemo::class, CustomAlarm::class], version = 3, exportSchema = false) +@Database(entities = [ShiftOverride::class, DailyMemo::class, CustomAlarm::class, AnnualLeave::class], version = 4, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun shiftDao(): ShiftDao diff --git a/app/src/main/java/com/example/shiftalarm/Entities.kt b/app/src/main/java/com/example/shiftalarm/Entities.kt index 5c6256f..21f217a 100644 --- a/app/src/main/java/com/example/shiftalarm/Entities.kt +++ b/app/src/main/java/com/example/shiftalarm/Entities.kt @@ -1,6 +1,7 @@ package com.example.shiftalarm -import androidx.room.* +import androidx.room.Entity +import androidx.room.PrimaryKey @Entity(tableName = "shift_overrides", primaryKeys = ["factory", "team", "date"]) data class ShiftOverride( @@ -28,3 +29,12 @@ data class CustomAlarm( val snoozeInterval: Int = 5, val snoozeRepeat: Int = 3 ) + +@Entity(tableName = "annual_leave") +data class AnnualLeave( + @PrimaryKey + val id: Int = 1, // Single row for app-wide annual leave + val totalDays: Float, // 총 연차 (1~25) + val remainingDays: Float, // 남은 연차 + val updatedAt: Long = System.currentTimeMillis() +) diff --git a/app/src/main/java/com/example/shiftalarm/ShiftDao.kt b/app/src/main/java/com/example/shiftalarm/ShiftDao.kt index a21d925..218f103 100644 --- a/app/src/main/java/com/example/shiftalarm/ShiftDao.kt +++ b/app/src/main/java/com/example/shiftalarm/ShiftDao.kt @@ -1,6 +1,11 @@ package com.example.shiftalarm -import androidx.room.* +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update @Dao interface ShiftDao { @@ -57,4 +62,17 @@ interface ShiftDao { @Query("DELETE FROM custom_alarms") suspend fun clearCustomAlarms() + + // Annual Leave Queries + @Query("SELECT * FROM annual_leave WHERE id = 1") + suspend fun getAnnualLeave(): AnnualLeave? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAnnualLeave(annualLeave: AnnualLeave) + + @Query("UPDATE annual_leave SET remainingDays = :remainingDays, updatedAt = :timestamp WHERE id = 1") + suspend fun updateRemainingDays(remainingDays: Float, timestamp: Long = System.currentTimeMillis()) + + @Query("DELETE FROM annual_leave") + suspend fun clearAnnualLeave() } diff --git a/app/src/main/java/com/example/shiftalarm/ShiftRepository.kt b/app/src/main/java/com/example/shiftalarm/ShiftRepository.kt index a771389..12c29a0 100644 --- a/app/src/main/java/com/example/shiftalarm/ShiftRepository.kt +++ b/app/src/main/java/com/example/shiftalarm/ShiftRepository.kt @@ -57,4 +57,47 @@ class ShiftRepository(private val context: Context) { suspend fun clearAllCustomAlarms() = withContext(Dispatchers.IO) { dao.clearCustomAlarms() } + + // Annual Leave + suspend fun calculateUsedAnnualLeave(): Float = withContext(Dispatchers.IO) { + val currentYear = java.time.Year.now().toString() + val overrides = dao.getAllOverrides() + + var usedDays = 0f + + for (override in overrides) { + if (override.date.startsWith(currentYear)) { + when (override.shift) { + "연차" -> usedDays += 1f + "반년" -> usedDays += 0.5f + } + } + } + + usedDays + } + + suspend fun getAnnualLeave(): AnnualLeave? = withContext(Dispatchers.IO) { + dao.getAnnualLeave() + } + + suspend fun recalculateAndSaveAnnualLeave(totalDays: Float) { + val usedDays = calculateUsedAnnualLeave() + val remainingDays = totalDays - usedDays + + dao.insertAnnualLeave(AnnualLeave( + id = 1, + totalDays = totalDays, + remainingDays = remainingDays + )) + } + + suspend fun updateRemainingAnnualLeave() { + val annualLeave = dao.getAnnualLeave() + annualLeave?.let { + val usedDays = calculateUsedAnnualLeave() + val remainingDays = it.totalDays - usedDays + dao.insertAnnualLeave(it.copy(remainingDays = remainingDays)) + } + } }