implement adding/removing variant status in DAO

Sun, 02 Feb 2025 14:12:02 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 02 Feb 2025 14:12:02 +0100
changeset 350
c676c200534d
parent 349
41cf84e10aeb
child 351
3720c7375146

implement adding/removing variant status in DAO

relates to #491

setup/postgres/psql_create_tables.sql file | annotate | diff | comparison | revisions
setup/postgres/psql_patch_1.5.0.sql file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt file | annotate | diff | comparison | revisions
--- a/setup/postgres/psql_create_tables.sql	Sun Feb 02 13:13:27 2025 +0100
+++ b/setup/postgres/psql_create_tables.sql	Sun Feb 02 14:12:02 2025 +0100
@@ -198,5 +198,6 @@
     issueid   integer        not null references lpit_issue (issueid),
     variant   integer        not null references lpit_variant (id),
     status    issue_status   not null default 'InSpecification',
+    outdated  boolean        not null default false,
     primary key (issueid, variant)
 );
--- a/setup/postgres/psql_patch_1.5.0.sql	Sun Feb 02 13:13:27 2025 +0100
+++ b/setup/postgres/psql_patch_1.5.0.sql	Sun Feb 02 14:12:02 2025 +0100
@@ -22,5 +22,6 @@
     issueid   integer        not null references lpit_issue (issueid),
     variant   integer        not null references lpit_variant (id),
     status    issue_status   not null default 'InSpecification',
+    outdated  boolean        not null default false,
     primary key (issueid, variant)
 );
--- a/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Sun Feb 02 13:13:27 2025 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Sun Feb 02 14:12:02 2025 +0100
@@ -729,7 +729,7 @@
                     // this loop uses that both queries ordered their results by issue id
                     while (true) {
                         if (issue.id == issueid) {
-                            issue.setVariantStatus(variant, status)
+                            issue.setStatusForVariant(variant, status)
                             break
                         }
                         if (!issueIter.hasNext()) break
@@ -822,11 +822,82 @@
         return issues
     }
 
-    override fun findIssue(id: Int): Issue? =
-        withStatement("$issueQuery where issueid = ?") {
+    override fun findIssue(id: Int): Issue? {
+        val issue = withStatement("$issueQuery where issueid = ?") {
             setInt(1, id)
             querySingle { it.extractIssue() }
         }
+        if (issue == null) return null
+        return withStatement(
+            """
+            select s.status,
+                v.id, v.project, v.name, v.node, v.color, v.ordinal, v.description, v.active
+            from lpit_issue_variant_status s
+            join lpit_variant v on v.id = s.variant
+            where issueid = ?
+            """.trimIndent()
+        ) {
+            setInt(1, issue.id)
+            executeQuery().let {rs ->
+                while (rs.next()) {
+                    issue.setStatusForVariant(rs.extractVariant(), rs.getEnum("status"))
+                }
+            }
+            issue
+        }
+    }
+
+    private fun updateVariantStatus(issueid: Int, statusMap: Map<Variant, IssueStatus>, newIssue: Boolean = false) {
+        // different strategy when there are no status entries (anymore) - just delete all existing
+        if (statusMap.isEmpty()) {
+            if (!newIssue) {
+                withStatement("delete from lpit_issue_variant_status where issueid = ?") {
+                    setInt(1, issueid)
+                    executeUpdate()
+                }
+            }
+            return
+        }
+
+
+        // don't need to erase previous status entries when this is a new issue
+        if (!newIssue) {
+            withStatement(
+                """
+                update lpit_issue_variant_status
+                set outdated = true where issueid = ?
+                """.trimIndent()
+            ) {
+                setInt(1, issueid)
+                executeUpdate()
+            }
+        }
+
+        // upsert the status entries
+        statusMap.forEach { (variant, status) ->
+            withStatement(
+                """
+                insert into lpit_issue_variant_status (issueid, variant, status)
+                values (?, ?, ?::issue_status)
+                on conflict do update
+                set status = ?::issue_status, outdated = false
+                """.trimIndent()
+            ) {
+                setInt(1, issueid)
+                setInt(2, variant.id)
+                setEnum(3, status)
+                setEnum(4, status)
+                executeUpdate()
+            }
+        }
+
+        if (!newIssue) {
+            withStatement("delete from lpit_issue_variant_status where outdated and issueid = ?") {
+                setInt(1, issueid)
+                executeUpdate()
+            }
+        }
+    }
 
     override fun insertIssue(issue: Issue): Int {
         val id = withStatement(
@@ -840,6 +911,7 @@
             setInt(col, issue.project.id)
             querySingle { it.getInt(1) }!!
         }
+        updateVariantStatus(id, issue.variantStatus, true)
         return id
     }
 
@@ -856,6 +928,7 @@
             setInt(col, issue.id)
             executeUpdate()
         }
+        updateVariantStatus(issue.id, issue.variantStatus)
     }
 
     override fun insertHistoryEvent(author: User?, issue: Issue, newId: Int) {
--- a/src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt	Sun Feb 02 13:13:27 2025 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/entities/Issue.kt	Sun Feb 02 14:12:02 2025 +0100
@@ -49,16 +49,16 @@
     var resolved: Version? = null
 
     val isTrackingVariantStatus get() = variantStatus.isNotEmpty()
-    fun setVariantStatus(variant: Variant, status: IssueStatus) {
+    fun setStatusForVariant(variant: Variant, status: IssueStatus) {
         variantStatus[variant] = status
     }
     fun removeVariant(variant: Variant) {
         variantStatus.remove(variant)
     }
-    fun getVariantStatus(variant: Variant): IssueStatus? {
+    fun getStatusForVariant(variant: Variant): IssueStatus? {
         return variantStatus[variant]
     }
-    private val variantStatus = mutableMapOf<Variant, IssueStatus>()
+    val variantStatus = mutableMapOf<Variant, IssueStatus>()
 
     /**
      * An issue is overdue, if it is not done and the ETA is before the current time.

mercurial