From 60119c884a83f8240f9bc56f30bf899683a8e6c6 Mon Sep 17 00:00:00 2001 From: Florian M Date: Thu, 24 Jan 2019 11:57:36 +0100 Subject: [PATCH] Separate Statistics per Organization (#3663) * [WIP] query statistics per orga * separate statistics per organization * scalafmt + changelog --- CHANGELOG.md | 2 +- app/controllers/StatisticsController.scala | 11 ++++++----- app/models/annotation/Annotation.scala | 8 ++++++++ app/models/binary/DataSet.scala | 7 +++++++ app/models/task/Task.scala | 6 ++++-- app/models/user/User.scala | 7 +++++++ app/models/user/time/TimeSpan.scala | 13 +++++++------ app/models/user/time/TimeSpanService.scala | 5 +++-- 8 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f739ef64d0e..e839bcd3125 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md). ### Changed -- +- Statistics are now separated by organization, rather than showing the webKnossos instance’s totals. [#3663](https://github.com/scalableminds/webknossos/pull/3663) ### Fixed diff --git a/app/controllers/StatisticsController.scala b/app/controllers/StatisticsController.scala index 31131b89e74..a6861ef6b80 100644 --- a/app/controllers/StatisticsController.scala +++ b/app/controllers/StatisticsController.scala @@ -44,11 +44,12 @@ class StatisticsController @Inject()(timeSpanService: TimeSpanService, intervalHandler.get(interval) match { case Some(handler) => for { - times <- timeSpanService.loggedTimePerInterval(handler, start, end) - numberOfUsers <- userDAO.countAll - numberOfDatasets <- dataSetDAO.countAll - numberOfAnnotations <- annotationDAO.countAll - numberOfAssignments <- taskDAO.countAllOpenInstances + organizationId <- Fox.successful(request.identity._organization) + times <- timeSpanService.loggedTimePerInterval(handler, start, end, organizationId) + numberOfUsers <- userDAO.countAllForOrganization(organizationId) + numberOfDatasets <- dataSetDAO.countAllForOrganization(organizationId) + numberOfAnnotations <- annotationDAO.countAllForOrganization(organizationId) + numberOfAssignments <- taskDAO.countAllOpenInstancesForOrganization(organizationId) } yield { Ok( Json.obj( diff --git a/app/models/annotation/Annotation.scala b/app/models/annotation/Annotation.scala index 67bb3fab3a2..c9d3ebe6fbe 100755 --- a/app/models/annotation/Annotation.scala +++ b/app/models/annotation/Annotation.scala @@ -208,6 +208,14 @@ class AnnotationDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContex count <- countList.headOption } yield count + def countAllForOrganization(organizationId: ObjectId)(implicit ctx: DBAccessContext): Fox[Int] = + for { + countList <- run( + sql"select count(*) from (select a._id from #${existingCollectionName} a join webknossos.users_ u on a._user = u._id where u._organization = ${organizationId}) q" + .as[Int]) + count <- countList.headOption + } yield count + // update operations def insertOne(a: Annotation): Fox[Unit] = diff --git a/app/models/binary/DataSet.scala b/app/models/binary/DataSet.scala index 1e01517865d..27c0d4c7ca7 100755 --- a/app/models/binary/DataSet.scala +++ b/app/models/binary/DataSet.scala @@ -134,6 +134,13 @@ class DataSetDAO @Inject()(sqlClient: SQLClient, parsed <- Fox.combined(r.toList.map(parse)) } yield parsed + def countAllForOrganization(organizationId: ObjectId)(implicit ctx: DBAccessContext): Fox[Int] = + for { + rList <- run( + sql"select count(_id) from #${existingCollectionName} where _organization = ${organizationId}".as[Int]) + r <- rList.headOption + } yield r + def findOneByNameAndOrganizationName(name: String, organizationName: String)( implicit ctx: DBAccessContext): Fox[DataSet] = for { diff --git a/app/models/task/Task.scala b/app/models/task/Task.scala index 51c7c14beca..d969eef7220 100755 --- a/app/models/task/Task.scala +++ b/app/models/task/Task.scala @@ -287,9 +287,11 @@ class TaskDAO @Inject()(sqlClient: SQLClient, projectDAO: ProjectDAO)(implicit e firstResult <- result.headOption.toFox } yield firstResult - def countAllOpenInstances(implicit ctx: DBAccessContext): Fox[Int] = + def countAllOpenInstancesForOrganization(organizationId: ObjectId)(implicit ctx: DBAccessContext): Fox[Int] = for { - result <- run(sql"select sum(openInstances) from webknossos.tasks_".as[Int]) + result <- run( + sql"select sum(t.openInstances) from webknossos.tasks_ t join webknossos.projects_ p on t._project = p._id where ${organizationId} in (select _organization from webknossos.users_ where _id = p._owner)" + .as[Int]) firstResult <- result.headOption } yield firstResult diff --git a/app/models/user/User.scala b/app/models/user/User.scala index 7fdb77c0758..2292a323a79 100755 --- a/app/models/user/User.scala +++ b/app/models/user/User.scala @@ -135,6 +135,13 @@ class UserDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext) parsed <- Fox.combined(r.toList.map(parse)) } yield parsed + def countAllForOrganization(organizationId: ObjectId): Fox[Int] = + for { + resultList <- run( + sql"select count(_id) from #${existingCollectionName} where _organization = ${organizationId}".as[Int]) + result <- resultList.headOption + } yield result + def insertOne(u: User)(implicit ctx: DBAccessContext): Fox[Unit] = for { _ <- run( diff --git a/app/models/user/time/TimeSpan.scala b/app/models/user/time/TimeSpan.scala index 7aa97f0619c..122645d0e7b 100755 --- a/app/models/user/time/TimeSpan.scala +++ b/app/models/user/time/TimeSpan.scala @@ -137,13 +137,14 @@ class TimeSpanDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext) parsed <- Fox.combined(r.toList.map(parse)) } yield parsed - def findAll(start: Option[Long], end: Option[Long]): Fox[List[TimeSpan]] = + def findAll(start: Option[Long], end: Option[Long], organizationId: ObjectId): Fox[List[TimeSpan]] = for { - r <- run(Timespans - .filter(r => - notdel(r) && (r.created >= new java.sql.Timestamp(start.getOrElse(0))) && r.created <= new java.sql.Timestamp( - end.getOrElse(MAX_TIMESTAMP))) - .result) + r <- run(sql"""select #${columnsWithPrefix("t.")} from #${existingCollectionName} t + join webknossos.users u on t._user = u._id + where t.created >= ${new java.sql.Timestamp(start.getOrElse(0))} and t.created <= ${new java.sql.Timestamp( + end.getOrElse(MAX_TIMESTAMP))} + and u._organization = ${organizationId} + """.as[TimespansRow]) parsed <- Fox.combined(r.toList.map(parse)) } yield parsed diff --git a/app/models/user/time/TimeSpanService.scala b/app/models/user/time/TimeSpanService.scala index 46469bc7b8d..fbaf2256dcb 100644 --- a/app/models/user/time/TimeSpanService.scala +++ b/app/models/user/time/TimeSpanService.scala @@ -86,9 +86,10 @@ class TimeSpanService @Inject()(annotationDAO: AnnotationDAO, def loggedTimePerInterval[T](groupingF: TimeSpan => T, start: Option[Long] = None, - end: Option[Long] = None): Fox[Map[T, Duration]] = + end: Option[Long] = None, + organizationId: ObjectId): Fox[Map[T, Duration]] = for { - timeTrackingOpt <- timeSpanDAO.findAll(start, end).futureBox + timeTrackingOpt <- timeSpanDAO.findAll(start, end, organizationId).futureBox } yield { timeTrackingOpt match { case Full(timeSpans) =>