From f3ba2241242f3f80c7b88aefda1e29579b8ee74c Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Fri, 7 Aug 2020 01:20:26 +0200 Subject: [PATCH] Add missing organization/person/equipment routes --- .../docspell/backend/ops/OEquipment.scala | 5 ++ .../docspell/backend/ops/OOrganization.scala | 13 +++++ .../src/main/resources/docspell-openapi.yml | 17 ++++++ .../restserver/routes/EquipmentRoutes.scala | 7 +++ .../routes/OrganizationRoutes.scala | 7 +++ .../restserver/routes/PersonRoutes.scala | 7 +++ .../store/queries/QOrganization.scala | 56 +++++++++++++++++++ .../docspell/store/records/TagItemName.scala | 4 +- 8 files changed, 115 insertions(+), 1 deletion(-) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OEquipment.scala b/modules/backend/src/main/scala/docspell/backend/ops/OEquipment.scala index bfb8537d..9457e6a6 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OEquipment.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OEquipment.scala @@ -11,6 +11,8 @@ trait OEquipment[F[_]] { def findAll(account: AccountId, nameQuery: Option[String]): F[Vector[REquipment]] + def find(account: AccountId, id: Ident): F[Option[REquipment]] + def add(s: REquipment): F[AddResult] def update(s: REquipment): F[AddResult] @@ -25,6 +27,9 @@ object OEquipment { def findAll(account: AccountId, nameQuery: Option[String]): F[Vector[REquipment]] = store.transact(REquipment.findAll(account.collective, nameQuery, _.name)) + def find(account: AccountId, id: Ident): F[Option[REquipment]] = + store.transact(REquipment.findById(id)).map(_.filter(_.cid == account.collective)) + def add(e: REquipment): F[AddResult] = { def insert = REquipment.insert(e) def exists = REquipment.existsByName(e.cid, e.name) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OOrganization.scala b/modules/backend/src/main/scala/docspell/backend/ops/OOrganization.scala index ca192b97..e007b1af 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OOrganization.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OOrganization.scala @@ -11,6 +11,7 @@ import docspell.store.records._ trait OOrganization[F[_]] { def findAllOrg(account: AccountId, query: Option[String]): F[Vector[OrgAndContacts]] + def findOrg(account: AccountId, orgId: Ident): F[Option[OrgAndContacts]] def findAllOrgRefs(account: AccountId, nameQuery: Option[String]): F[Vector[IdRef]] @@ -23,6 +24,8 @@ trait OOrganization[F[_]] { query: Option[String] ): F[Vector[PersonAndContacts]] + def findPerson(account: AccountId, persId: Ident): F[Option[PersonAndContacts]] + def findAllPersonRefs(account: AccountId, nameQuery: Option[String]): F[Vector[IdRef]] def addPerson(s: PersonAndContacts): F[AddResult] @@ -53,6 +56,11 @@ object OOrganization { .compile .toVector + def findOrg(account: AccountId, orgId: Ident): F[Option[OrgAndContacts]] = + store + .transact(QOrganization.getOrgAndContact(account.collective, orgId)) + .map(_.map({ case (org, cont) => OrgAndContacts(org, cont) })) + def findAllOrgRefs( account: AccountId, nameQuery: Option[String] @@ -75,6 +83,11 @@ object OOrganization { .compile .toVector + def findPerson(account: AccountId, persId: Ident): F[Option[PersonAndContacts]] = + store + .transact(QOrganization.getPersonAndContact(account.collective, persId)) + .map(_.map({ case (org, cont) => PersonAndContacts(org, cont) })) + def findAllPersonRefs( account: AccountId, nameQuery: Option[String] diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index 96f66c07..2b23aab9 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -778,6 +778,23 @@ paths: schema: $ref: "#/components/schemas/BasicResult" /sec/equipment/{id}: + get: + tags: [ Equipment ] + summary: Get details about a single equipment. + description: | + Loads one equipment by its id. + security: + - authTokenHeader: [] + parameters: + - $ref: "#/components/parameters/id" + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/Equipment" + delete: tags: [ Equipment ] summary: Delete a equipment. diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala index a7699115..edfc7521 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala @@ -1,5 +1,6 @@ package docspell.restserver.routes +import cats.data.OptionT import cats.effect._ import cats.implicits._ @@ -49,6 +50,12 @@ object EquipmentRoutes { del <- backend.equipment.delete(id, user.account.collective) resp <- Ok(basicResult(del, "Equipment deleted.")) } yield resp + + case GET -> Root / Ident(id) => + (for { + equip <- OptionT(backend.equipment.find(user.account, id)) + resp <- OptionT.liftF(Ok(mkEquipment(equip))) + } yield resp).getOrElseF(NotFound()) } } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala index 59d17017..4bed90e4 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala @@ -1,5 +1,6 @@ package docspell.restserver.routes +import cats.data.OptionT import cats.effect._ import cats.implicits._ @@ -55,6 +56,12 @@ object OrganizationRoutes { delOrg <- backend.organization.deleteOrg(id, user.account.collective) resp <- Ok(basicResult(delOrg, "Organization deleted.")) } yield resp + + case GET -> Root / Ident(id) => + (for { + org <- OptionT(backend.organization.findOrg(user.account, id)) + resp <- OptionT.liftF(Ok(mkOrg(org))) + } yield resp).getOrElseF(NotFound()) } } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala index 2e90a9b4..a37ac536 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala @@ -1,5 +1,6 @@ package docspell.restserver.routes +import cats.data.OptionT import cats.effect._ import cats.implicits._ @@ -59,6 +60,12 @@ object PersonRoutes { delOrg <- backend.organization.deletePerson(id, user.account.collective) resp <- Ok(basicResult(delOrg, "Person deleted.")) } yield resp + + case GET -> Root / Ident(id) => + (for { + org <- OptionT(backend.organization.findPerson(user.account, id)) + resp <- OptionT.liftF(Ok(mkPerson(org))) + } yield resp).getOrElseF(NotFound()) } } diff --git a/modules/store/src/main/scala/docspell/store/queries/QOrganization.scala b/modules/store/src/main/scala/docspell/store/queries/QOrganization.scala index 159f423c..55ed5259 100644 --- a/modules/store/src/main/scala/docspell/store/queries/QOrganization.scala +++ b/modules/store/src/main/scala/docspell/store/queries/QOrganization.scala @@ -52,6 +52,34 @@ object QOrganization { }) } + def getOrgAndContact( + coll: Ident, + orgId: Ident + ): ConnectionIO[Option[(ROrganization, Vector[RContact])]] = { + val oColl = ROrganization.Columns.cid.prefix("o") + val oId = ROrganization.Columns.oid.prefix("o") + val cOrg = RContact.Columns.orgId.prefix("c") + + val cols = ROrganization.Columns.all.map(_.prefix("o")) ++ RContact.Columns.all + .map(_.prefix("c")) + val from = ROrganization.table ++ fr"o LEFT JOIN" ++ + RContact.table ++ fr"c ON" ++ cOrg.is(oId) + + val q = and(oColl.is(coll), oId.is(orgId)) + + selectSimple(cols, from, q) + .query[(ROrganization, Option[RContact])] + .stream + .groupAdjacentBy(_._1) + .map({ + case (ro, chunk) => + val cs = chunk.toVector.flatMap(_._2) + (ro, cs) + }) + .compile + .last + } + def findPersonAndContact( coll: Ident, query: Option[String], @@ -88,6 +116,34 @@ object QOrganization { }) } + def getPersonAndContact( + coll: Ident, + persId: Ident + ): ConnectionIO[Option[(RPerson, Vector[RContact])]] = { + val pColl = PC.cid.prefix("p") + val pId = RPerson.Columns.pid.prefix("p") + val cPers = RContact.Columns.personId.prefix("c") + + val cols = RPerson.Columns.all.map(_.prefix("p")) ++ RContact.Columns.all + .map(_.prefix("c")) + val from = RPerson.table ++ fr"p LEFT JOIN" ++ + RContact.table ++ fr"c ON" ++ cPers.is(pId) + + val q = and(pColl.is(coll), pId.is(persId)) + + selectSimple(cols, from, q) + .query[(RPerson, Option[RContact])] + .stream + .groupAdjacentBy(_._1) + .map({ + case (ro, chunk) => + val cs = chunk.toVector.flatMap(_._2) + (ro, cs) + }) + .compile + .last + } + def findPersonByContact( coll: Ident, value: String, diff --git a/modules/store/src/main/scala/docspell/store/records/TagItemName.scala b/modules/store/src/main/scala/docspell/store/records/TagItemName.scala index 05689ffd..fffa1f61 100644 --- a/modules/store/src/main/scala/docspell/store/records/TagItemName.scala +++ b/modules/store/src/main/scala/docspell/store/records/TagItemName.scala @@ -1,8 +1,10 @@ package docspell.store.records +import cats.data.NonEmptyList + import docspell.common._ import docspell.store.impl.Implicits._ -import cats.data.NonEmptyList + import doobie._ import doobie.implicits._