api: new formdef popularity count method (#47889)
This commit is contained in:
parent
cb13232405
commit
18d9fea6ff
|
@ -420,6 +420,43 @@ def test_formdef_list(pub):
|
|||
assert resp1.json['err'] == 0
|
||||
assert len(resp1.json['data']) == 0
|
||||
|
||||
formdef.data_class().wipe()
|
||||
|
||||
# a draft
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {}
|
||||
formdata.just_created()
|
||||
formdata.status = 'draft'
|
||||
formdata.store()
|
||||
|
||||
other_formdef = FormDef()
|
||||
other_formdef.name = 'test 2'
|
||||
other_formdef.fields = []
|
||||
other_formdef.store()
|
||||
other_formdata = other_formdef.data_class()()
|
||||
other_formdata.data = {}
|
||||
other_formdata.just_created()
|
||||
other_formdata.store()
|
||||
|
||||
# formdata created:
|
||||
# - 1 day ago (=3*4)
|
||||
# - 7 days ago (=2*2)
|
||||
# - 29 days ago (=1*1)
|
||||
# - 31 days ago (=0)
|
||||
for days in [1, 1, 1, 7, 7, 29, 31]:
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {}
|
||||
formdata.just_created()
|
||||
formdata.receipt_time = (datetime.datetime.now() - datetime.timedelta(days=days)).timetuple()
|
||||
formdata.store()
|
||||
|
||||
resp = get_app(pub).get(sign_uri('/api/formdefs/?include-count=on'))
|
||||
if not pub.is_using_postgresql():
|
||||
assert resp.json['data'][0]['count'] == 8
|
||||
else:
|
||||
# 3*4 + 2*2 + 1*1
|
||||
assert resp.json['data'][0]['count'] == 17
|
||||
|
||||
|
||||
def test_limited_formdef_list(pub, local_user):
|
||||
Role.wipe()
|
||||
|
|
27
wcs/api.py
27
wcs/api.py
|
@ -14,12 +14,13 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
|
||||
from quixote import get_request, get_publisher, get_response, get_session
|
||||
from quixote.errors import MethodNotAllowedError, QueryError
|
||||
from quixote.errors import MethodNotAllowedError
|
||||
from quixote.directory import Directory
|
||||
|
||||
from django.utils.encoding import force_text
|
||||
|
@ -574,7 +575,29 @@ class ApiFormdefsDirectory(Directory):
|
|||
if include_count:
|
||||
# we include the count of submitted forms so it's possible to sort
|
||||
# them by "popularity"
|
||||
formdict['count'] = formdef.data_class().count()
|
||||
if get_publisher().is_using_postgresql():
|
||||
from wcs import sql
|
||||
# 4 * number of submitted forms of last 2 days
|
||||
# + 2 * number of submitted forms of last 8 days
|
||||
# + 1 * number of submitted forms of last 30 days
|
||||
# exclude drafts
|
||||
criterias = [Equal('formdef_id', formdef.id), NotEqual('status', 'draft')]
|
||||
d_now = datetime.datetime.now()
|
||||
count = 4 * sql.get_period_total(
|
||||
period_start=d_now - datetime.timedelta(days=2), include_start=True,
|
||||
criterias=criterias)
|
||||
count += 2 * sql.get_period_total(
|
||||
period_start=d_now - datetime.timedelta(days=8), include_start=True,
|
||||
period_end=d_now - datetime.timedelta(days=2), include_end=False,
|
||||
criterias=criterias)
|
||||
count += sql.get_period_total(
|
||||
period_start=d_now - datetime.timedelta(days=30), include_start=True,
|
||||
period_end=d_now - datetime.timedelta(days=8), include_end=False,
|
||||
criterias=criterias)
|
||||
else:
|
||||
# naive count
|
||||
count = formdef.data_class().count()
|
||||
formdict['count'] = count
|
||||
|
||||
formdict['functions'] = {}
|
||||
formdef_workflow_roles = formdef.workflow_roles or {}
|
||||
|
|
39
wcs/sql.py
39
wcs/sql.py
|
@ -2525,7 +2525,7 @@ class AnyFormData(SqlMixin):
|
|||
formdatas[0].load_all_evolutions(formdatas)
|
||||
|
||||
|
||||
def get_period_query(period_start=None, period_end=None, criterias=None, parameters=None):
|
||||
def get_period_query(period_start=None, include_start=True, period_end=None, include_end=True, criterias=None, parameters=None):
|
||||
clause = [NotNull('receipt_time')]
|
||||
table_name = 'wcs_all_forms'
|
||||
if criterias:
|
||||
|
@ -2539,9 +2539,15 @@ def get_period_query(period_start=None, period_end=None, criterias=None, paramet
|
|||
continue
|
||||
clause.append(criteria)
|
||||
if period_start:
|
||||
clause.append(GreaterOrEqual('receipt_time', period_start))
|
||||
if include_start:
|
||||
clause.append(GreaterOrEqual('receipt_time', period_start))
|
||||
else:
|
||||
clause.append(Greater('receipt_time', period_start))
|
||||
if period_end:
|
||||
clause.append(LessOrEqual('receipt_time', period_end))
|
||||
if include_end:
|
||||
clause.append(LessOrEqual('receipt_time', period_end))
|
||||
else:
|
||||
clause.append(Less('receipt_time', period_end))
|
||||
where_clauses, params, func_clause = parse_clause(clause)
|
||||
parameters.update(params)
|
||||
statement = ' FROM %s ' % table_name
|
||||
|
@ -2589,7 +2595,7 @@ def get_weekday_totals(period_start=None, period_end=None, criterias=None):
|
|||
conn, cur = get_connection_and_cursor()
|
||||
statement = '''SELECT DATE_PART('dow', receipt_time) AS weekday, COUNT(*)'''
|
||||
parameters = {}
|
||||
statement += get_period_query(period_start, period_end, criterias, parameters)
|
||||
statement += get_period_query(period_start=period_start, period_end=period_end, criterias=criterias, parameters=parameters)
|
||||
statement += ' GROUP BY weekday ORDER BY weekday'''
|
||||
cur.execute(statement, parameters)
|
||||
|
||||
|
@ -2612,7 +2618,7 @@ def get_hour_totals(period_start=None, period_end=None, criterias=None):
|
|||
conn, cur = get_connection_and_cursor()
|
||||
statement = '''SELECT DATE_PART('hour', receipt_time) AS hour, COUNT(*)'''
|
||||
parameters = {}
|
||||
statement += get_period_query(period_start, period_end, criterias, parameters)
|
||||
statement += get_period_query(period_start=period_start, period_end=period_end, criterias=criterias, parameters=parameters)
|
||||
statement += ' GROUP BY hour ORDER BY hour'
|
||||
cur.execute(statement, parameters)
|
||||
|
||||
|
@ -2636,7 +2642,7 @@ def get_monthly_totals(period_start=None, period_end=None, criterias=None):
|
|||
conn, cur = get_connection_and_cursor()
|
||||
statement = '''SELECT DATE_TRUNC('month', receipt_time) AS month, COUNT(*) '''
|
||||
parameters = {}
|
||||
statement += get_period_query(period_start, period_end, criterias, parameters)
|
||||
statement += get_period_query(period_start=period_start, period_end=period_end, criterias=criterias, parameters=parameters)
|
||||
statement += ' GROUP BY month ORDER BY month'''
|
||||
cur.execute(statement, parameters)
|
||||
|
||||
|
@ -2665,7 +2671,7 @@ def get_yearly_totals(period_start=None, period_end=None, criterias=None):
|
|||
conn, cur = get_connection_and_cursor()
|
||||
statement = '''SELECT DATE_TRUNC('year', receipt_time) AS year, COUNT(*)'''
|
||||
parameters = {}
|
||||
statement += get_period_query(period_start, period_end, criterias, parameters)
|
||||
statement += get_period_query(period_start=period_start, period_end=period_end, criterias=criterias, parameters=parameters)
|
||||
statement += ' GROUP BY year ORDER BY year'
|
||||
cur.execute(statement, parameters)
|
||||
|
||||
|
@ -2688,6 +2694,25 @@ def get_yearly_totals(period_start=None, period_end=None, criterias=None):
|
|||
return result
|
||||
|
||||
|
||||
@guard_postgres
|
||||
def get_period_total(period_start=None, include_start=True, period_end=None, include_end=True, criterias=None):
|
||||
conn, cur = get_connection_and_cursor()
|
||||
statement = '''SELECT COUNT(*)'''
|
||||
parameters = {}
|
||||
statement += get_period_query(
|
||||
period_start=period_start, include_start=include_start,
|
||||
period_end=period_end, include_end=include_end,
|
||||
criterias=criterias, parameters=parameters)
|
||||
cur.execute(statement, parameters)
|
||||
|
||||
result = int(cur.fetchone()[0])
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# latest migration, number + description (description is not used
|
||||
# programmaticaly but will make sure git conflicts if two migrations are
|
||||
# separately added with the same number)
|
||||
|
|
Loading…
Reference in New Issue