diff --git a/modules/joex/src/main/scala/docspell/joex/process/SetGivenData.scala b/modules/joex/src/main/scala/docspell/joex/process/SetGivenData.scala index 3618c3d7..53162af2 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/SetGivenData.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/SetGivenData.scala @@ -12,6 +12,7 @@ import cats.implicits._ import docspell.backend.ops.OItem import docspell.common._ import docspell.joex.scheduler.Task +import docspell.store.UpdateResult object SetGivenData { type Args = ProcessItemArgs @@ -46,7 +47,12 @@ object SetGivenData { e <- ops.setFolder(itemId, folderId, collective).attempt _ <- e.fold( ex => ctx.logger.warn(s"Error setting folder: ${ex.getMessage}"), - _ => ().pure[F] + res => + res match { + case UpdateResult.Failure(ex) => + ctx.logger.warn(s"Error setting folder: ${ex.getMessage}") + case _ => ().pure[F] + } ) } yield data } 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