From d95a78f4957a9caf52ebffbb3d32ab39a63cec87 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Sat, 17 Jul 2021 15:10:19 +0200
Subject: [PATCH] Allow to set folder by id or name

---
 .../src/main/resources/docspell-openapi.yml   |  3 ++-
 .../docspell/store/records/RFolder.scala      | 19 +++++++++++++++++++
 .../scala/docspell/store/records/RItem.scala  |  6 +++++-
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml
index e3880347..29c5e5e7 100644
--- a/modules/restapi/src/main/resources/docspell-openapi.yml
+++ b/modules/restapi/src/main/resources/docspell-openapi.yml
@@ -5073,7 +5073,8 @@ components:
         A direction can be given, `Incoming` is used if not specified.
 
         A folderId can be given, the item is placed into this folder
-        after creation.
+        after creation. It may be the exact id of the folder or its
+        name.
 
         The `fileFilter` is an optional glob for filtering files to
         import. Only applicable if archive files are uploaded. It
diff --git a/modules/store/src/main/scala/docspell/store/records/RFolder.scala b/modules/store/src/main/scala/docspell/store/records/RFolder.scala
index 1a6db3f6..f4e48a39 100644
--- a/modules/store/src/main/scala/docspell/store/records/RFolder.scala
+++ b/modules/store/src/main/scala/docspell/store/records/RFolder.scala
@@ -74,6 +74,25 @@ object RFolder {
     sql.query[RFolder].option
   }
 
+  def requireIdByIdOrName(
+      folderId: Ident,
+      name: String,
+      collective: Ident
+  ): ConnectionIO[Ident] = {
+    val sql = run(
+      select(T.id),
+      from(T),
+      T.id === folderId || (T.name === name && T.collective === collective)
+    )
+    sql.query[Ident].option.flatMap {
+      case Some(id) => id.pure[ConnectionIO]
+      case None =>
+        Sync[ConnectionIO].raiseError(
+          new Exception(s"No folder found for: id=${folderId.id} or name=${name}")
+        )
+    }
+  }
+
   def findAll(
       coll: Ident,
       nameQ: Option[String],
diff --git a/modules/store/src/main/scala/docspell/store/records/RItem.scala b/modules/store/src/main/scala/docspell/store/records/RItem.scala
index 1592bb66..1dd977cc 100644
--- a/modules/store/src/main/scala/docspell/store/records/RItem.scala
+++ b/modules/store/src/main/scala/docspell/store/records/RItem.scala
@@ -274,10 +274,14 @@ object RItem {
   ): ConnectionIO[Int] =
     for {
       t <- currentTime
+      fid <- folderId match {
+        case Some(f) => RFolder.requireIdByIdOrName(f, f.id, coll).map(_.some)
+        case None    => None.pure[ConnectionIO]
+      }
       n <- DML.update(
         T,
         T.cid === coll && T.id === itemId,
-        DML.set(T.folder.setTo(folderId), T.updated.setTo(t))
+        DML.set(T.folder.setTo(fid), T.updated.setTo(t))
       )
     } yield n