From eca51fa2507ddbdc7a7715dda3cc939c8f2b421c Mon Sep 17 00:00:00 2001
From: Megan Henning <meganhenning@flywheel.io>
Date: Wed, 12 Oct 2016 14:45:22 -0500
Subject: [PATCH] Add non-compliant session count to stats

---
 api/api.py                       |  2 +-
 api/dao/containerstorage.py      |  7 +++---
 api/dao/containerutil.py         | 37 +++++++++++++++++++++++++-------
 api/handlers/containerhandler.py |  1 +
 4 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/api/api.py b/api/api.py
index 454490bd..98d74f11 100644
--- a/api/api.py
+++ b/api/api.py
@@ -174,7 +174,7 @@ routes = [
     webapp2.Route(r'/api/projects/groups',                                              containerhandler.ContainerHandler, handler_method='get_groups_with_project', methods=['GET']),
     webapp2.Route(r'/api/projects/recalc',                                              containerhandler.ContainerHandler, handler_method='calculate_project_compliance', methods=['POST']),
     webapp2.Route(_format(r'/api/projects/<cid:{cid_re}>/template'),                    containerhandler.ContainerHandler, handler_method='set_project_template', methods=['POST']),
-    webapp2.Route(_format(r'/api/projects/<cid:{cid_re}>/template/recalc'),             containerhandler.ContainerHandler, handler_method='calculate_project_compliance', methods=['POST']),
+    webapp2.Route(_format(r'/api/projects/<cid:{cid_re}>/recalc'),             containerhandler.ContainerHandler, handler_method='calculate_project_compliance', methods=['POST']),
 
     webapp2.Route(_format(r'/api/<par_cont_name:groups>/<par_id:{group_id_re}>/<cont_name:projects>'),          containerhandler.ContainerHandler, name='cont_sublist_groups', handler_method='get_all', methods=['GET']),
     webapp2.Route(_format(r'/api/<par_cont_name:{cont_name_re}>/<par_id:{cid_re}>/<cont_name:{cont_name_re}>'), containerhandler.ContainerHandler, name='cont_sublist', handler_method='get_all', methods=['GET']),
diff --git a/api/dao/containerstorage.py b/api/dao/containerstorage.py
index 7e9047c6..1110927b 100644
--- a/api/dao/containerstorage.py
+++ b/api/dao/containerstorage.py
@@ -194,7 +194,7 @@ class ProjectStorage(ContainerStorage):
             # Recalc all projects
             projects = self.get_all_el({'template': {'$exists': True}}, None, None)
         else:
-            project = self.get_container(project_id, get_children=True)
+            project = self.get_container(project_id)
             if project:
                 projects = [project]
             else:
@@ -204,10 +204,11 @@ class ProjectStorage(ContainerStorage):
         for project in projects:
             template = project.get('template',{})
             if not template:
-                return
+                continue
             else:
                 session_storage = SessionStorage()
-                for s in project.get('sessions', []):
+                sessions = session_storage.get_all_el({'project': project['_id']}, None, None)
+                for s in sessions:
                     changed = session_storage.recalc_session_compliance(s['_id'], session=s, template=template)
                     if changed:
                         changed_sessions.append(s['_id'])
diff --git a/api/dao/containerutil.py b/api/dao/containerutil.py
index c79fc0f6..f0bcbddb 100644
--- a/api/dao/containerutil.py
+++ b/api/dao/containerutil.py
@@ -39,22 +39,46 @@ def add_id_to_subject(subject, pid):
 
 def get_stats(cont, cont_type):
     """
-    Add a session and attachment count to a project or collection
+    Add a session, subject, non-compliant session and attachment count to a project or collection
     """
 
     if cont_type not in ['projects', 'collections']:
         return cont
 
-    session_ids = []
+    # Get attachment count from file array length
+    cont['attachment_count'] = len(cont.get('files', []))
+
+    # Get session and non-compliant session count
+    match_q = {}
     if cont_type == 'projects':
-        result = list(config.db.sessions.find({'project': cont['_id']}, {'_id': 1}))
-        session_ids = [s['_id'] for s in result]
+        match_q = {'project': cont['_id']}
     elif cont_type == 'collections':
         result = config.db.acquisitions.find({'collections': cont['_id']}, {'session': 1})
         session_ids = list(set([s['session'] for s in result]))
+        match_q = {'_id': {'$in': session_ids}}
+
+    pipeline = [
+        {'$match': match_q},
+        {'$project': {'_id': 1, 'non_compliant':  {'$cond': [{'$eq': ['$satisfies_template', False]}, 1, 0]}}},
+        {'$group': {'_id': 1, 'noncompliant_count': {'$sum': '$non_compliant'}, 'total': {'$sum': 1}}}
+    ]
+
+    result = config.db.command('aggregate', 'sessions', pipeline=pipeline).get('result', [])
 
+    if len(result) > 0:
+        cont['session_count'] = result[0].get('total', 0)
+        cont['noncompliant_session_count'] = result[0].get('noncompliant_count', 0)
+    else:
+        # If there are no sessions, return zero'd out stats
+        cont['session_count'] = 0
+        cont['noncompliant_session_count'] = 0
+        cont['subject_count'] = 0
+        return cont
+
+    # Get subject count
+    match_q['subject._id'] = {'$ne': None}
     pipeline = [
-        {'$match': {'_id': {'$in': session_ids}, 'subject._id': {'$ne': None}}},
+        {'$match': match_q},
         {'$group': {'_id': '$subject._id'}},
         {'$group': {'_id': 1, 'count': { '$sum': 1 }}}
     ]
@@ -66,9 +90,6 @@ def get_stats(cont, cont_type):
     else:
         cont['subject_count'] = 0
 
-    cont['attachment_count'] = len(cont.get('files', []))
-    cont['session_count'] = len(session_ids)
-
     return cont
 
 
diff --git a/api/handlers/containerhandler.py b/api/handlers/containerhandler.py
index 5f9be5b7..cdcb4866 100644
--- a/api/handlers/containerhandler.py
+++ b/api/handlers/containerhandler.py
@@ -507,6 +507,7 @@ class ContainerHandler(base.RequestHandler):
 
     def calculate_project_compliance(self, **kwargs):
         project_id = kwargs.pop('cid', None)
+        log.debug("project_id is {}".format(project_id))
         self.config = self.container_handler_configurations['projects']
         self.storage = self.config['storage']
         return {'sessions_changed': self.storage.recalc_sessions_compliance(project_id=project_id)}
-- 
GitLab