diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala index 5d1e816c..ff27b29a 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala @@ -63,19 +63,35 @@ trait OItem[F[_]] { collective: Ident ): F[UpdateResult] - def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult] + def setCorrOrg( + items: NonEmptyList[Ident], + org: Option[Ident], + collective: Ident + ): F[UpdateResult] def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult] - def setCorrPerson(item: Ident, person: Option[Ident], collective: Ident): F[AddResult] + def setCorrPerson( + items: NonEmptyList[Ident], + person: Option[Ident], + collective: Ident + ): F[UpdateResult] def addCorrPerson(item: Ident, person: OOrganization.PersonAndContacts): F[AddResult] - def setConcPerson(item: Ident, person: Option[Ident], collective: Ident): F[AddResult] + def setConcPerson( + items: NonEmptyList[Ident], + person: Option[Ident], + collective: Ident + ): F[UpdateResult] def addConcPerson(item: Ident, person: OOrganization.PersonAndContacts): F[AddResult] - def setConcEquip(item: Ident, equip: Option[Ident], collective: Ident): F[AddResult] + def setConcEquip( + items: NonEmptyList[Ident], + equip: Option[Ident], + collective: Ident + ): F[UpdateResult] def addConcEquip(item: Ident, equip: REquipment): F[AddResult] @@ -304,11 +320,15 @@ object OItem { else UpdateResult.success } yield res - def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult] = - store - .transact(RItem.updateCorrOrg(item, collective, org)) - .attempt - .map(AddResult.fromUpdate) + def setCorrOrg( + items: NonEmptyList[Ident], + org: Option[Ident], + collective: Ident + ): F[UpdateResult] = + UpdateResult.fromUpdate( + store + .transact(RItem.updateCorrOrg(items, collective, org)) + ) def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult] = (for { @@ -319,7 +339,11 @@ object OItem { case AddResult.Success => OptionT.liftF( store.transact( - RItem.updateCorrOrg(item, org.org.cid, Some(org.org.oid)) + RItem.updateCorrOrg( + NonEmptyList.of(item), + org.org.cid, + Some(org.org.oid) + ) ) ) case AddResult.EntityExists(_) => @@ -331,14 +355,14 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setCorrPerson( - item: Ident, + items: NonEmptyList[Ident], person: Option[Ident], collective: Ident - ): F[AddResult] = - store - .transact(RItem.updateCorrPerson(item, collective, person)) - .attempt - .map(AddResult.fromUpdate) + ): F[UpdateResult] = + UpdateResult.fromUpdate( + store + .transact(RItem.updateCorrPerson(items, collective, person)) + ) def addCorrPerson( item: Ident, @@ -353,7 +377,11 @@ object OItem { OptionT.liftF( store.transact( RItem - .updateCorrPerson(item, person.person.cid, Some(person.person.pid)) + .updateCorrPerson( + NonEmptyList.of(item), + person.person.cid, + Some(person.person.pid) + ) ) ) case AddResult.EntityExists(_) => @@ -365,14 +393,14 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setConcPerson( - item: Ident, + items: NonEmptyList[Ident], person: Option[Ident], collective: Ident - ): F[AddResult] = - store - .transact(RItem.updateConcPerson(item, collective, person)) - .attempt - .map(AddResult.fromUpdate) + ): F[UpdateResult] = + UpdateResult.fromUpdate( + store + .transact(RItem.updateConcPerson(items, collective, person)) + ) def addConcPerson( item: Ident, @@ -387,7 +415,11 @@ object OItem { OptionT.liftF( store.transact( RItem - .updateConcPerson(item, person.person.cid, Some(person.person.pid)) + .updateConcPerson( + NonEmptyList.of(item), + person.person.cid, + Some(person.person.pid) + ) ) ) case AddResult.EntityExists(_) => @@ -399,14 +431,14 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setConcEquip( - item: Ident, + items: NonEmptyList[Ident], equip: Option[Ident], collective: Ident - ): F[AddResult] = - store - .transact(RItem.updateConcEquip(item, collective, equip)) - .attempt - .map(AddResult.fromUpdate) + ): F[UpdateResult] = + UpdateResult.fromUpdate( + store + .transact(RItem.updateConcEquip(items, collective, equip)) + ) def addConcEquip(item: Ident, equip: REquipment): F[AddResult] = (for { @@ -417,7 +449,8 @@ object OItem { case AddResult.Success => OptionT.liftF( store.transact( - RItem.updateConcEquip(item, equip.cid, Some(equip.eid)) + RItem + .updateConcEquip(NonEmptyList.of(item), equip.cid, Some(equip.eid)) ) ) case AddResult.EntityExists(_) => diff --git a/modules/joex/src/main/scala/docspell/joex/process/LinkProposal.scala b/modules/joex/src/main/scala/docspell/joex/process/LinkProposal.scala index 8d4fc493..58df16ac 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/LinkProposal.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/LinkProposal.scala @@ -66,22 +66,38 @@ object LinkProposal { case MetaProposalType.CorrOrg => ctx.logger.debug(s"Updating item organization with: ${value.id}") *> ctx.store.transact( - RItem.updateCorrOrg(itemId, ctx.args.meta.collective, Some(value)) + RItem.updateCorrOrg( + NonEmptyList.of(itemId), + ctx.args.meta.collective, + Some(value) + ) ) case MetaProposalType.ConcPerson => ctx.logger.debug(s"Updating item concerning person with: $value") *> ctx.store.transact( - RItem.updateConcPerson(itemId, ctx.args.meta.collective, Some(value)) + RItem.updateConcPerson( + NonEmptyList.of(itemId), + ctx.args.meta.collective, + Some(value) + ) ) case MetaProposalType.CorrPerson => ctx.logger.debug(s"Updating item correspondent person with: $value") *> ctx.store.transact( - RItem.updateCorrPerson(itemId, ctx.args.meta.collective, Some(value)) + RItem.updateCorrPerson( + NonEmptyList.of(itemId), + ctx.args.meta.collective, + Some(value) + ) ) case MetaProposalType.ConcEquip => ctx.logger.debug(s"Updating item concerning equipment with: $value") *> ctx.store.transact( - RItem.updateConcEquip(itemId, ctx.args.meta.collective, Some(value)) + RItem.updateConcEquip( + NonEmptyList.of(itemId), + ctx.args.meta.collective, + Some(value) + ) ) case MetaProposalType.DocDate => MetaProposal.parseDate(value) match { diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala index 6239d0a3..860db77d 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala @@ -19,7 +19,6 @@ import org.http4s.circe.CirceEntityEncoder._ import org.http4s.dsl.Http4sDsl object ItemMultiRoutes { -// private[this] val logger = getLogger def apply[F[_]: Effect]( backend: BackendApp[F], @@ -118,33 +117,37 @@ object ItemMultiRoutes { resp <- Ok(Conversions.basicResult(res, "Item due date updated")) } yield resp - // case req @ PUT -> Root / "corrOrg" => - // for { - // idref <- req.as[OptionalId] - // res <- backend.item.setCorrOrg(id, idref.id, user.account.collective) - // resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) - // } yield resp + case req @ PUT -> Root / "corrOrg" => + for { + json <- req.as[ItemsAndRef] + items <- readIds[F](json.items) + res <- backend.item.setCorrOrg(items, json.ref, user.account.collective) + resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) + } yield resp - // case req @ PUT -> Root / "corrPerson" => - // for { - // idref <- req.as[OptionalId] - // res <- backend.item.setCorrPerson(id, idref.id, user.account.collective) - // resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) - // } yield resp + case req @ PUT -> Root / "corrPerson" => + for { + json <- req.as[ItemsAndRef] + items <- readIds[F](json.items) + res <- backend.item.setCorrPerson(items, json.ref, user.account.collective) + resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) + } yield resp - // case req @ PUT -> Root / "concPerson" => - // for { - // idref <- req.as[OptionalId] - // res <- backend.item.setConcPerson(id, idref.id, user.account.collective) - // resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) - // } yield resp + case req @ PUT -> Root / "concPerson" => + for { + json <- req.as[ItemsAndRef] + items <- readIds[F](json.items) + res <- backend.item.setConcPerson(items, json.ref, user.account.collective) + resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) + } yield resp - // case req @ PUT -> Root / "concEquipment" => - // for { - // idref <- req.as[OptionalId] - // res <- backend.item.setConcEquip(id, idref.id, user.account.collective) - // resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) - // } yield resp + case req @ PUT -> Root / "concEquipment" => + for { + json <- req.as[ItemsAndRef] + items <- readIds[F](json.items) + res <- backend.item.setConcEquip(items, json.ref, user.account.collective) + resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) + } yield resp // case req @ POST -> Root / "reprocess" => // for { diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala index 9fa473cf..1966a6f1 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala @@ -185,8 +185,12 @@ object ItemRoutes { case req @ PUT -> Root / Ident(id) / "corrOrg" => for { idref <- req.as[OptionalId] - res <- backend.item.setCorrOrg(id, idref.id, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) + res <- backend.item.setCorrOrg( + NonEmptyList.of(id), + idref.id, + user.account.collective + ) + resp <- Ok(Conversions.basicResult(res, "Correspondent organization updated")) } yield resp case req @ POST -> Root / Ident(id) / "corrOrg" => @@ -200,8 +204,12 @@ object ItemRoutes { case req @ PUT -> Root / Ident(id) / "corrPerson" => for { idref <- req.as[OptionalId] - res <- backend.item.setCorrPerson(id, idref.id, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) + res <- backend.item.setCorrPerson( + NonEmptyList.of(id), + idref.id, + user.account.collective + ) + resp <- Ok(Conversions.basicResult(res, "Correspondent person updated")) } yield resp case req @ POST -> Root / Ident(id) / "corrPerson" => @@ -215,8 +223,12 @@ object ItemRoutes { case req @ PUT -> Root / Ident(id) / "concPerson" => for { idref <- req.as[OptionalId] - res <- backend.item.setConcPerson(id, idref.id, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) + res <- backend.item.setConcPerson( + NonEmptyList.of(id), + idref.id, + user.account.collective + ) + resp <- Ok(Conversions.basicResult(res, "Concerned person updated")) } yield resp case req @ POST -> Root / Ident(id) / "concPerson" => @@ -230,8 +242,12 @@ object ItemRoutes { case req @ PUT -> Root / Ident(id) / "concEquipment" => for { idref <- req.as[OptionalId] - res <- backend.item.setConcEquip(id, idref.id, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) + res <- backend.item.setConcEquip( + NonEmptyList.of(id), + idref.id, + user.account.collective + ) + resp <- Ok(Conversions.basicResult(res, "Concerned equipment updated")) } yield resp case req @ POST -> Root / Ident(id) / "concEquipment" => 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 dbb15dfd..a023e136 100644 --- a/modules/store/src/main/scala/docspell/store/records/RItem.scala +++ b/modules/store/src/main/scala/docspell/store/records/RItem.scala @@ -159,12 +159,16 @@ object RItem { ).update.run } yield n - def updateCorrOrg(itemId: Ident, coll: Ident, org: Option[Ident]): ConnectionIO[Int] = + def updateCorrOrg( + itemIds: NonEmptyList[Ident], + coll: Ident, + org: Option[Ident] + ): ConnectionIO[Int] = for { t <- currentTime n <- updateRow( table, - and(id.is(itemId), cid.is(coll)), + and(id.isIn(itemIds), cid.is(coll)), commas(corrOrg.setTo(org), updated.setTo(t)) ).update.run } yield n @@ -180,7 +184,7 @@ object RItem { } yield n def updateCorrPerson( - itemId: Ident, + itemIds: NonEmptyList[Ident], coll: Ident, person: Option[Ident] ): ConnectionIO[Int] = @@ -188,7 +192,7 @@ object RItem { t <- currentTime n <- updateRow( table, - and(id.is(itemId), cid.is(coll)), + and(id.isIn(itemIds), cid.is(coll)), commas(corrPerson.setTo(person), updated.setTo(t)) ).update.run } yield n @@ -204,7 +208,7 @@ object RItem { } yield n def updateConcPerson( - itemId: Ident, + itemIds: NonEmptyList[Ident], coll: Ident, person: Option[Ident] ): ConnectionIO[Int] = @@ -212,7 +216,7 @@ object RItem { t <- currentTime n <- updateRow( table, - and(id.is(itemId), cid.is(coll)), + and(id.isIn(itemIds), cid.is(coll)), commas(concPerson.setTo(person), updated.setTo(t)) ).update.run } yield n @@ -228,7 +232,7 @@ object RItem { } yield n def updateConcEquip( - itemId: Ident, + itemIds: NonEmptyList[Ident], coll: Ident, equip: Option[Ident] ): ConnectionIO[Int] = @@ -236,7 +240,7 @@ object RItem { t <- currentTime n <- updateRow( table, - and(id.is(itemId), cid.is(coll)), + and(id.isIn(itemIds), cid.is(coll)), commas(concEquipment.setTo(equip), updated.setTo(t)) ).update.run } yield n diff --git a/modules/webapp/src/main/elm/Api.elm b/modules/webapp/src/main/elm/Api.elm index 39f36b7e..d6a8edbb 100644 --- a/modules/webapp/src/main/elm/Api.elm +++ b/modules/webapp/src/main/elm/Api.elm @@ -77,10 +77,14 @@ module Api exposing , setAttachmentName , setCollectiveSettings , setConcEquip + , setConcEquipmentMultiple , setConcPerson + , setConcPersonMultiple , setConfirmed , setCorrOrg + , setCorrOrgMultiple , setCorrPerson + , setCorrPersonMultiple , setDateMultiple , setDirection , setDirectionMultiple @@ -1375,6 +1379,62 @@ setDueDateMultiple flags data receive = } +setCorrOrgMultiple : + Flags + -> ItemsAndRef + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +setCorrOrgMultiple flags data receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/items/corrOrg" + , account = getAccount flags + , body = Http.jsonBody (Api.Model.ItemsAndRef.encode data) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +setCorrPersonMultiple : + Flags + -> ItemsAndRef + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +setCorrPersonMultiple flags data receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/items/corrPerson" + , account = getAccount flags + , body = Http.jsonBody (Api.Model.ItemsAndRef.encode data) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +setConcPersonMultiple : + Flags + -> ItemsAndRef + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +setConcPersonMultiple flags data receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/items/concPerson" + , account = getAccount flags + , body = Http.jsonBody (Api.Model.ItemsAndRef.encode data) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +setConcEquipmentMultiple : + Flags + -> ItemsAndRef + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +setConcEquipmentMultiple flags data receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/items/concEquipment" + , account = getAccount flags + , body = Http.jsonBody (Api.Model.ItemsAndRef.encode data) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + --- Item diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/FormChange.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/FormChange.elm index 5edd9da8..c6dc36dc 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/FormChange.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/FormChange.elm @@ -86,5 +86,33 @@ multiUpdate flags ids change receive = in Api.setDueDateMultiple flags data receive + OrgChange ref -> + let + data = + ItemsAndRef items (Maybe.map .id ref) + in + Api.setCorrOrgMultiple flags data receive + + CorrPersonChange ref -> + let + data = + ItemsAndRef items (Maybe.map .id ref) + in + Api.setCorrPersonMultiple flags data receive + + ConcPersonChange ref -> + let + data = + ItemsAndRef items (Maybe.map .id ref) + in + Api.setConcPersonMultiple flags data receive + + EquipChange ref -> + let + data = + ItemsAndRef items (Maybe.map .id ref) + in + Api.setConcEquipmentMultiple flags data receive + _ -> Cmd.none