meta-edc 0.3.28__py3-none-any.whl → 0.3.30__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. meta_ae/action_items.py +2 -2
  2. meta_edc/settings/defaults.py +0 -1
  3. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/METADATA +2 -2
  4. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/RECORD +63 -39
  5. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/WHEEL +1 -1
  6. meta_reports/admin/__init__.py +5 -3
  7. meta_reports/admin/{unmanaged → dbviews}/__init__.py +2 -0
  8. meta_reports/admin/dbviews/on_study_missing_lab_values_admin/__init__.py +1 -0
  9. meta_reports/admin/dbviews/on_study_missing_lab_values_admin/unmanaged_model_admin.py +13 -0
  10. meta_reports/admin/dbviews/on_study_missing_values_admin/__init__.py +1 -0
  11. meta_reports/admin/dbviews/on_study_missing_values_admin/unmanaged_model_admin.py +13 -0
  12. meta_reports/admin/modeladmin_mixins.py +1 -5
  13. meta_reports/migrations/0039_onstudymissingvalues.py +44 -0
  14. meta_reports/migrations/0040_auto_20240824_0412.py +282 -0
  15. meta_reports/migrations/0041_auto_20240828_2229.py +14 -0
  16. meta_reports/migrations/0042_onstudymissinglabvalues.py +43 -0
  17. meta_reports/migrations/0043_auto_20240828_2309.py +87 -0
  18. meta_reports/migrations/0044_auto_20240828_2323.py +93 -0
  19. meta_reports/migrations/0045_auto_20240829_0248.py +54 -0
  20. meta_reports/migrations/0046_auto_20240829_0250.py +54 -0
  21. meta_reports/models/__init__.py +2 -0
  22. meta_reports/models/dbviews/__init__.py +2 -0
  23. meta_reports/models/dbviews/glucose_summary/view_definition.py +14 -59
  24. meta_reports/models/dbviews/missing_screening_ogtt/view_definition.py +14 -49
  25. meta_reports/models/dbviews/on_study_missing_lab_values/__init__.py +1 -0
  26. meta_reports/models/dbviews/on_study_missing_lab_values/qa_cases.py +53 -0
  27. meta_reports/models/dbviews/on_study_missing_lab_values/unmanged_model.py +20 -0
  28. meta_reports/models/dbviews/on_study_missing_lab_values/view_definition.py +17 -0
  29. meta_reports/models/dbviews/on_study_missing_values/__init__.py +1 -0
  30. meta_reports/models/dbviews/on_study_missing_values/qa_cases.py +55 -0
  31. meta_reports/models/dbviews/on_study_missing_values/unmanged_model.py +20 -0
  32. meta_reports/models/dbviews/on_study_missing_values/view_definition.py +17 -0
  33. meta_reports/models/dbviews/patient_history_missing_baseline_cd4/view_definition.py +13 -47
  34. meta_reports/models/dbviews/unattended_three_in_row/view_definition.py +20 -67
  35. meta_reports/models/dbviews/unattended_three_in_row2/view_definition.py +44 -128
  36. meta_reports/models/dbviews/unattended_two_in_row/view_definition.py +25 -72
  37. meta_reports/tests/test_sql_gen.py +5 -0
  38. meta_reports/utils.py +0 -0
  39. meta_subject/action_items.py +2 -2
  40. meta_subject/admin/__init__.py +1 -0
  41. meta_subject/admin/blood_results/__init__.py +1 -1
  42. meta_subject/admin/blood_results/{blood_results_lipid_admin.py → blood_results_lipids_admin.py} +7 -7
  43. meta_subject/forms/__init__.py +1 -1
  44. meta_subject/forms/blood_results/__init__.py +1 -1
  45. meta_subject/forms/blood_results/{blood_results_lipid_form.py → blood_results_lipids_form.py} +5 -5
  46. meta_subject/migrations/0212_auto_20240827_2222.py +23 -0
  47. meta_subject/migrations/0213_rename_bloodresultslipid_bloodresultslipids_and_more.py +35 -0
  48. meta_subject/model_mixins/arv_history_model_mixin.py +3 -3
  49. meta_subject/models/__init__.py +1 -1
  50. meta_subject/models/blood_results/__init__.py +1 -1
  51. meta_subject/models/blood_results/{blood_results_lipid.py → blood_results_lipids.py} +3 -3
  52. meta_visit_schedule/visit_schedules/phase_three/crfs.py +6 -6
  53. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/AUTHORS +0 -0
  54. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/LICENSE +0 -0
  55. {meta_edc-0.3.28.dist-info → meta_edc-0.3.30.dist-info}/top_level.txt +0 -0
  56. /meta_reports/admin/{unmanaged → dbviews}/glucose_summary_admin.py +0 -0
  57. /meta_reports/admin/{unmanaged → dbviews}/missing_screening_ogtt_admin/__init__.py +0 -0
  58. /meta_reports/admin/{unmanaged → dbviews}/missing_screening_ogtt_admin/note_model_admin.py +0 -0
  59. /meta_reports/admin/{unmanaged → dbviews}/missing_screening_ogtt_admin/unmanaged_model_admin.py +0 -0
  60. /meta_reports/admin/{unmanaged → dbviews}/patient_history_missing_baseline_cd4_admin.py +0 -0
  61. /meta_reports/admin/{unmanaged → dbviews}/unattended_three_in_row2_admin.py +0 -0
  62. /meta_reports/admin/{unmanaged → dbviews}/unattended_three_in_row_admin.py +0 -0
  63. /meta_reports/admin/{unmanaged → dbviews}/unattended_two_in_row_admin.py +0 -0
@@ -1,8 +1,12 @@
1
- mysql_view = """ # noqa
2
- select *, uuid() as id, now() as created, 'meta_reports.unattendedthreeinrow' as `report_model` from (
3
- select subject_identifier, site_id, appt_datetime, `first_value`, `second_value`, `third_value`,
4
- datediff(third_date, first_date) as `interval_days`,
5
- datediff(now(), first_date) as `from_now_days`
1
+ from edc_qareports.sql_generator import SqlViewGenerator
2
+
3
+
4
+ def get_view_definition() -> dict:
5
+ subquery = """
6
+ select subject_identifier, site_id, appt_datetime, `first_value`,
7
+ `second_value`, `third_value`,
8
+ datediff(`third_date`, `first_date`) as `interval_days`,
9
+ datediff(now(), `first_date`) as `from_now_days`
6
10
  from (
7
11
  select subject_identifier, site_id, appt_datetime,
8
12
  FIRST_VALUE(visit_code) OVER w as `first_value`,
@@ -10,69 +14,18 @@ mysql_view = """ # noqa
10
14
  NTH_VALUE(visit_code, 3) OVER w as `third_value`,
11
15
  FIRST_VALUE(appt_datetime) OVER w as `first_date`,
12
16
  NTH_VALUE(appt_datetime, 3) OVER w as `third_date`
13
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
17
+ from edc_appointment_appointment where visit_code_sequence=0 and appt_status="New"
14
18
  and appt_datetime <= now()
15
19
  WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
16
- ) as A
17
- where `second_value` is not null and `third_value` is not null
18
- ) as B
19
- order by site_id, from_now_days desc
20
- """
21
-
22
- pg_view = """ # noqa
23
- select *, gen_random_uuid() as id, now() as created,
24
- 'meta_reports.unattendedthreeinrow' as report_model
25
- from (
26
- select subject_identifier, site_id, appt_datetime, first_value, second_value, third_value,
27
- EXTRACT(DAY FROM third_date - first_date) as interval_days,
28
- EXTRACT(DAY FROM now() - first_date) as from_now_days
29
- from (
30
- select subject_identifier,site_id,appt_datetime,
31
- FIRST_VALUE(visit_code) OVER w as first_value,
32
- NTH_VALUE(visit_code, 2) OVER w as second_value,
33
- NTH_VALUE(visit_code, 3) OVER w as third_value,
34
- FIRST_VALUE(appt_datetime) OVER w as first_date,
35
- NTH_VALUE(appt_datetime, 3) OVER w as third_date
36
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
37
- and appt_datetime <= now()
38
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
39
- ) as A
40
- where second_value is not null and third_value is not null
41
- ) as B
42
- order by site_id, from_now_days desc
43
- """
44
-
45
- sqlite3_view = """ # noqa
46
- SELECT *, lower(
47
- hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
48
- substr(hex( randomblob(2)), 2) || '-' ||
49
- substr('AB89', 1 + (abs(random()) % 4) , 1) ||
50
- substr(hex(randomblob(2)), 2) || '-' ||
51
- hex(randomblob(6))
52
- ) as id, datetime() as created,'meta_reports.unattendedthreeinrow' as report_model from (
53
- select subject_identifier, site_id, appt_datetime, first_value, second_value, third_value,
54
- CAST(JulianDay(third_date) - JulianDay(first_date) AS INTEGER) as interval_days,
55
- CAST(JulianDay(datetime()) - JulianDay(first_date) AS INTEGER) as from_now_days
56
- from (
57
- select subject_identifier, site_id, appt_datetime,
58
- FIRST_VALUE(visit_code) OVER w as first_value,
59
- NTH_VALUE(visit_code, 2) OVER w as second_value,
60
- NTH_VALUE(visit_code, 3) OVER w as third_value,
61
- FIRST_VALUE(appt_datetime) OVER w as first_date,
62
- NTH_VALUE(appt_datetime, 3) OVER w as third_date
63
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
64
- and appt_datetime <= datetime()
65
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
66
- ) as A
67
- where second_value is not null and third_value is not null
68
- ) as B
69
- order by site_id, from_now_days desc
70
- """
71
-
72
-
73
- def get_view_definition() -> dict:
20
+ ) as B
21
+ where `second_value` is not null and `third_value` is not null
22
+ """ # noqa
23
+ sql_view = SqlViewGenerator(
24
+ report_model="meta_reports.unattendedthreeinrow",
25
+ ordering=["subject_identifier", "site_id"],
26
+ )
74
27
  return {
75
- "django.db.backends.mysql": mysql_view,
76
- "django.db.backends.postgresql": pg_view,
77
- "django.db.backends.sqlite3": sqlite3_view,
28
+ "django.db.backends.mysql": sql_view.as_mysql(subquery),
29
+ "django.db.backends.postgresql": sql_view.as_postgres(subquery),
30
+ "django.db.backends.sqlite3": sql_view.as_sqlite(subquery),
78
31
  }
@@ -1,134 +1,50 @@
1
- mysql_view = """ # noqa
2
- with appointments as (
3
- select subject_identifier, site_id, visit_code, visit_code_sequence, appt_datetime,
4
- case when appt_timing='missed' then 'New' else appt_status end as `appt_status`,
5
- case when appt_timing='missed' then 1 else 0 end as `missed`
6
- from edc_appointment_appointment
7
- where visit_code_sequence=0 and appt_datetime<=now()
8
- order by subject_identifier, appt_datetime
9
- )
10
- select *, uuid() as `id`, now() as `created`, 'meta_reports.unattendedthreeinrow2' as `report_model` from (
11
- select distinct subject_identifier, site_id, `first_value`, `second_value`, `third_value`,
12
- datediff(third_date, first_date) as `interval_days`,
13
- datediff(now(), first_date) as `from_now_days`,
14
- `first_status`, `second_status`, `third_status`, sum(missed) as `missed_count`
15
- from (
16
- select subject_identifier,site_id,appt_datetime, missed,
17
- FIRST_VALUE(appt_status) OVER w as `third_status`,
18
- NTH_VALUE(appt_status, 2) OVER w as `second_status`,
19
- NTH_VALUE(appt_status, 3) OVER w as `first_status`,
20
- FIRST_VALUE(visit_code) OVER w as `third_value`,
21
- NTH_VALUE(visit_code, 2) OVER w as `second_value`,
22
- NTH_VALUE(visit_code, 3) OVER w as `first_value`,
23
- FIRST_VALUE(appt_datetime) OVER w as `third_date`,
24
- NTH_VALUE(appt_datetime, 2) OVER w as `second_date`,
25
- NTH_VALUE(appt_datetime, 3) OVER w as `first_date`
26
- from appointments
27
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime desc ROWS UNBOUNDED PRECEDING)
28
- ) as A
29
- where `second_value` is not null and `third_value` is not null
30
- and `first_status`='New'
31
- and `second_status`='New'
32
- and `third_status`='New'
33
- group by subject_identifier, site_id, `first_value`, `second_value`, `third_value`,
34
- datediff(`third_date`, `first_date`),
35
- datediff(now(), `first_date`),
36
- `first_status`, `second_status`, `third_status`
37
- order by subject_identifier, site_id
38
- ) as B
39
- """
1
+ from edc_qareports.sql_generator import SqlViewGenerator
40
2
 
41
- pg_view = """ # noqa
42
- with appointments as (
43
- select subject_identifier, site_id, visit_code, visit_code_sequence, appt_datetime,
44
- case when appt_timing='missed' then 'New' else appt_status end as appt_status,
45
- case when appt_timing='missed' then 1 else 0 end as missed
46
- from edc_appointment_appointment
47
- where visit_code_sequence=0 and appt_datetime<=now()
48
- order by subject_identifier, appt_datetime
49
- )
50
- select *, gen_random_uuid() as id, now() as created, 'meta_reports.unattendedthreeinrow2' as report_model
51
- from (
52
- select distinct subject_identifier, site_id, first_value, second_value, third_value,
53
- EXTRACT(DAY FROM third_date - first_date) as interval_days,
54
- EXTRACT(DAY FROM now() - first_date) as from_now_days,
55
- first_status, second_status, third_status, sum(missed) as missed_count
56
- from (
57
- select subject_identifier,site_id,appt_datetime, missed,
58
- FIRST_VALUE(appt_status) OVER w as third_status,
59
- NTH_VALUE(appt_status, 2) OVER w as second_status,
60
- NTH_VALUE(appt_status, 3) OVER w as first_status,
61
- FIRST_VALUE(visit_code) OVER w as third_value,
62
- NTH_VALUE(visit_code, 2) OVER w as second_value,
63
- NTH_VALUE(visit_code, 3) OVER w as first_value,
64
- FIRST_VALUE(appt_datetime) OVER w as third_date,
65
- NTH_VALUE(appt_datetime, 2) OVER w as second_date,
66
- NTH_VALUE(appt_datetime, 3) OVER w as first_date
67
- from appointments
68
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime desc ROWS UNBOUNDED PRECEDING)
69
- ) as A
70
- where second_value is not null and third_value is not null
71
- and first_status='New'
72
- and second_status='New'
73
- and third_status='New'
74
- group by subject_identifier, site_id, first_value, second_value, third_value,
75
- EXTRACT(DAY FROM third_date - first_date),
76
- EXTRACT(DAY FROM now() - first_date),
77
- first_status, second_status, third_status
78
- order by subject_identifier, site_id
79
- ) as B
80
- """
81
3
 
82
- sqlite3_view = """ # noqa
83
- with appointments as (
84
- select subject_identifier, site_id, visit_code, visit_code_sequence, appt_datetime,
85
- case when appt_timing='missed' then 'New' else appt_status end as `appt_status`,
86
- case when appt_timing='missed' then 1 else 0 end as `missed`
87
- from edc_appointment_appointment
88
- where visit_code_sequence=0 and appt_datetime<=now()
89
- order by subject_identifier, appt_datetime
90
- )
91
- SELECT *, lower(
92
- hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
93
- substr(hex( randomblob(2)), 2) || '-' ||
94
- substr('AB89', 1 + (abs(random()) % 4) , 1) ||
95
- substr(hex(randomblob(2)), 2) || '-' ||
96
- hex(randomblob(6))
97
- ) as id, datetime() as created, 'meta_reports.unattendedthreeinrow2' as report_model from (
98
- select distinct subject_identifier, site_id, first_value, second_value, third_value,
99
- CAST(JulianDay(third_date) - JulianDay(first_date) AS Integer) as interval_days,
100
- CAST(JulianDay(datetime()) - JulianDay(first_date) AS Integer) as from_now_days,
101
- first_status, second_status, third_status, sum(missed) as missed_count
102
- from (
103
- select subject_identifier,site_id,appt_datetime, missed,
104
- FIRST_VALUE(appt_status) OVER w as third_status,
105
- NTH_VALUE(appt_status, 2) OVER w as second_status,
106
- NTH_VALUE(appt_status, 3) OVER w as first_status,
107
- FIRST_VALUE(visit_code) OVER w as third_value,
108
- NTH_VALUE(visit_code, 2) OVER w as second_value,
109
- NTH_VALUE(visit_code, 3) OVER w as first_value,
110
- FIRST_VALUE(appt_datetime) OVER w as third_date,
111
- NTH_VALUE(appt_datetime, 2) OVER w as second_date,
112
- NTH_VALUE(appt_datetime, 3) OVER w as first_date
113
- from appointments
114
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime desc ROWS UNBOUNDED PRECEDING)
115
- ) as A
116
- where second_value is not null and third_value is not null
117
- and first_status='New'
118
- and second_status='New'
119
- and third_status='New'
120
- group by subject_identifier, site_id, first_value, second_value, third_value,
121
- CAST(JulianDay(third_date) - JulianDay(first_date) AS Integer),
122
- CAST(JulianDay(datetime()) - JulianDay(first_date) AS Integer),
123
- first_status, second_status, third_status
124
- order by subject_identifier, site_id
125
- ) as B
126
- """
4
+ def get_view_definition() -> dict:
5
+ subquery = """select distinct subject_identifier, site_id, `first_value`, `second_value`, `third_value`,
6
+ datediff(`third_date`, `first_date`) as interval_days,
7
+ datediff(now(), `first_date`) as from_now_days,
8
+ `first_status`, `second_status`, `third_status`, sum(missed) as missed_count
9
+ from (
10
+ select subject_identifier,site_id,appt_datetime, `missed`,
11
+ FIRST_VALUE(appt_status) OVER w as `third_status`,
12
+ NTH_VALUE(appt_status, 2) OVER w as `second_status`,
13
+ NTH_VALUE(appt_status, 3) OVER w as `first_status`,
14
+ FIRST_VALUE(visit_code) OVER w as `third_value`,
15
+ NTH_VALUE(visit_code, 2) OVER w as `second_value`,
16
+ NTH_VALUE(visit_code, 3) OVER w as `first_value`,
17
+ FIRST_VALUE(appt_datetime) OVER w as `third_date`,
18
+ NTH_VALUE(appt_datetime, 2) OVER w as `second_date`,
19
+ NTH_VALUE(appt_datetime, 3) OVER w as `first_date`
20
+ from appointments
21
+ WINDOW w as (PARTITION BY subject_identifier order by appt_datetime desc ROWS UNBOUNDED PRECEDING)
22
+ ) as B
23
+ where `second_value` is not null and `third_value` is not null
24
+ and `first_status`="New"
25
+ and `second_status`="New"
26
+ and `third_status` ="New"
27
+ group by subject_identifier, site_id, `first_value`, `second_value`, `third_value`,
28
+ datediff(`third_date`, `first_date`),
29
+ datediff(now(), `first_date`),
30
+ `first_status`, `second_status`, `third_status`
31
+ order by subject_identifier, site_id""" # noqa
127
32
 
33
+ with_stmt = """with appointments as (select subject_identifier, site_id, visit_code, visit_code_sequence,
34
+ appt_datetime, case when appt_timing="missed" then "New" else appt_status end as `appt_status`,
35
+ case when appt_timing="missed" then 1 else 0 end as `missed`
36
+ from edc_appointment_appointment
37
+ where visit_code_sequence=0 and appt_datetime<=now()
38
+ order by subject_identifier, appt_datetime)""" # noqa
39
+
40
+ sql_view = SqlViewGenerator(
41
+ with_stmt=with_stmt,
42
+ report_model="meta_reports.unattendedthreeinrow2",
43
+ ordering=["subject_identifier", "site_id"],
44
+ )
128
45
 
129
- def get_view_definition() -> dict:
130
46
  return {
131
- "django.db.backends.mysql": mysql_view,
132
- "django.db.backends.postgresql": pg_view,
133
- "django.db.backends.sqlite3": sqlite3_view,
47
+ "django.db.backends.mysql": sql_view.as_mysql(subquery),
48
+ "django.db.backends.postgresql": sql_view.as_postgres(subquery),
49
+ "django.db.backends.sqlite3": sql_view.as_sqlite(subquery),
134
50
  }
@@ -1,77 +1,30 @@
1
- mysql_view = """ # noqa
2
- select *, uuid() as `id`, now() as `created`, 'meta_reports.unattendedtwoinrow' as report_model from (
3
- select subject_identifier, site_id, appt_datetime, `first_value`, `second_value`,
4
- datediff(`second_date`, `first_date`) as `interval_days`,
5
- datediff(now(), `first_date`) as `from_now_days`
6
- from (
7
- select subject_identifier ,site_id, appt_datetime,
8
- FIRST_VALUE(`visit_code`) OVER w as `first_value`,
9
- NTH_VALUE(`visit_code`, 2) OVER w as `second_value`,
10
- NTH_VALUE(`visit_code`, 3) OVER w as `third_value`,
11
- FIRST_VALUE(`appt_datetime`) OVER w as `first_date`,
12
- NTH_VALUE(`appt_datetime`, 2) OVER w as `second_date`
13
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
14
- and appt_datetime <= now()
15
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
16
- ) as A1
17
- where `second_value` is not null and `third_value` is null
18
- ) as A2
19
- order by site_id, `from_now_days` desc
20
- """
21
-
22
- pg_view = """ # noqa
23
- select *, gen_random_uuid() as id, now() as created, 'meta_reports.unattendedtwoinrow' as report_model
24
- from (
25
- select subject_identifier, site_id, appt_datetime, first_value, second_value,
26
- EXTRACT(DAY FROM second_date - first_date) as interval_days,
27
- EXTRACT(DAY FROM now() - first_date) as from_now_days
28
- from (
29
- select subject_identifier, site_id, appt_datetime,
30
- FIRST_VALUE(visit_code) OVER w as first_value,
31
- NTH_VALUE(visit_code, 2) OVER w as second_value,
32
- NTH_VALUE(visit_code, 3) OVER w as third_value,
33
- FIRST_VALUE(appt_datetime) OVER w as first_date,
34
- NTH_VALUE(appt_datetime, 2) OVER w as second_date
35
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
36
- and appt_datetime <= now()
37
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
38
- ) as A1
39
- where second_value is not null and third_value is null
40
- ) as A2
41
- order by site_id, from_now_days desc
42
- """
43
-
44
- sqlite3_view = """ # noqa
45
- SELECT *, lower(
46
- hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
47
- substr(hex( randomblob(2)), 2) || '-' ||
48
- substr('AB89', 1 + (abs(random()) % 4) , 1) ||
49
- substr(hex(randomblob(2)), 2) || '-' ||
50
- hex(randomblob(6))
51
- ) as id, datetime() as created, 'meta_reports.unattendedtwoinrow' as report_model from (
52
- select subject_identifier, site_id, appt_datetime, first_value, second_value,
53
- CAST(JulianDay(second_date) - JulianDay(first_date) AS Integer) as interval_days,
54
- CAST(JulianDay(datetime()) - JulianDay(first_date) AS Integer) as from_now_days
55
- from (
56
- select subject_identifier ,site_id, appt_datetime,
57
- FIRST_VALUE(visit_code) OVER w as first_value,
58
- NTH_VALUE(visit_code, 2) OVER w as second_value,
59
- NTH_VALUE(visit_code, 3) OVER w as third_value,
60
- FIRST_VALUE(appt_datetime) OVER w as first_date,
61
- NTH_VALUE(appt_datetime, 2) OVER w as second_date
62
- from edc_appointment_appointment where visit_code_sequence=0 and appt_status='New'
63
- and appt_datetime <= datetime()
64
- WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
65
- ) as A1
66
- where second_value is not null and third_value is null
67
- ) as A2
68
- order by site_id, from_now_days desc
69
- """
1
+ from edc_qareports.sql_generator import SqlViewGenerator
70
2
 
71
3
 
72
4
  def get_view_definition() -> dict:
5
+ subquery = """
6
+ select subject_identifier, site_id, appt_datetime, `first_value`, `second_value`,
7
+ datediff(`second_date`, `first_date`) as interval_days,
8
+ datediff(now(), `first_date`) as from_now_days
9
+ from (
10
+ select subject_identifier ,site_id, appt_datetime,
11
+ FIRST_VALUE(visit_code) OVER w as `first_value`,
12
+ NTH_VALUE(visit_code, 2) OVER w as `second_value`,
13
+ NTH_VALUE(visit_code, 3) OVER w as `third_value`,
14
+ FIRST_VALUE(appt_datetime) OVER w as `first_date`,
15
+ NTH_VALUE(appt_datetime, 2) OVER w as `second_date`
16
+ from edc_appointment_appointment where visit_code_sequence=0 and appt_status="New"
17
+ and appt_datetime <= now()
18
+ WINDOW w as (PARTITION BY subject_identifier order by appt_datetime ROWS UNBOUNDED PRECEDING)
19
+ ) as B
20
+ where `second_value` is not null and `third_value` is null""" # noqa
21
+
22
+ sql_view = SqlViewGenerator(
23
+ report_model="meta_reports.unattendedtwoinrow",
24
+ ordering=["site_id", "~from_now_days"],
25
+ )
73
26
  return {
74
- "django.db.backends.mysql": mysql_view,
75
- "django.db.backends.postgresql": pg_view,
76
- "django.db.backends.sqlite3": sqlite3_view,
27
+ "django.db.backends.mysql": sql_view.as_mysql(subquery),
28
+ "django.db.backends.postgresql": sql_view.as_postgres(subquery),
29
+ "django.db.backends.sqlite3": sql_view.as_sqlite(subquery),
77
30
  }
@@ -0,0 +1,5 @@
1
+ from django.test import TestCase
2
+
3
+
4
+ class TestSqlGen(TestCase):
5
+ pass
meta_reports/utils.py ADDED
File without changes
@@ -8,7 +8,7 @@ from edc_lab_results.action_items import (
8
8
  BloodResultsFbcAction,
9
9
  BloodResultsHba1cAction,
10
10
  BloodResultsLftAction,
11
- BloodResultsLipidAction,
11
+ BloodResultsLipidsAction,
12
12
  )
13
13
  from edc_lab_results.action_items import (
14
14
  BloodResultsRftAction as BaseBloodResultsRftAction,
@@ -175,7 +175,7 @@ class DmFollowAction(ActionWithNotification):
175
175
  def register_actions():
176
176
  for action_item_cls in [
177
177
  BloodResultsFbcAction,
178
- BloodResultsLipidAction,
178
+ BloodResultsLipidsAction,
179
179
  BloodResultsLftAction,
180
180
  BloodResultsRftAction,
181
181
  BloodResultsHba1cAction,
@@ -3,6 +3,7 @@ from .birth_outcome_admin import BirthOutcomesAdmin
3
3
  from .blood_results import (
4
4
  BloodResultsFbcAdmin,
5
5
  BloodResultsLftAdmin,
6
+ BloodResultsLipidsAdmin,
6
7
  BloodResultsRftAdmin,
7
8
  )
8
9
  from .complications_admin import ComplicationsAdmin
@@ -2,5 +2,5 @@ from .blood_results_fbc_admin import BloodResultsFbcAdmin
2
2
  from .blood_results_hba1c_admin import BloodResultsHba1cAdmin
3
3
  from .blood_results_ins_admin import BloodResultsInsAdmin
4
4
  from .blood_results_lft_admin import BloodResultsLftAdmin
5
- from .blood_results_lipid_admin import BloodResultsLipidAdmin
5
+ from .blood_results_lipids_admin import BloodResultsLipidsAdmin
6
6
  from .blood_results_rft_admin import BloodResultsRftAdmin
@@ -5,19 +5,19 @@ from edc_lab_results.fieldsets import BloodResultFieldset
5
5
  from edc_model_admin.history import SimpleHistoryAdmin
6
6
 
7
7
  from ...admin_site import meta_subject_admin
8
- from ...forms import BloodResultsLipidForm
9
- from ...models import BloodResultsLipid
8
+ from ...forms import BloodResultsLipidsForm
9
+ from ...models import BloodResultsLipids
10
10
  from ..modeladmin import CrfModelAdminMixin
11
11
 
12
12
 
13
- @admin.register(BloodResultsLipid, site=meta_subject_admin)
14
- class BloodResultsLipidAdmin(
13
+ @admin.register(BloodResultsLipids, site=meta_subject_admin)
14
+ class BloodResultsLipidsAdmin(
15
15
  BloodResultsModelAdminMixin, CrfModelAdminMixin, SimpleHistoryAdmin
16
16
  ):
17
- form = BloodResultsLipidForm
17
+ form = BloodResultsLipidsForm
18
18
  fieldsets = BloodResultFieldset(
19
- BloodResultsLipid.lab_panel,
20
- model_cls=BloodResultsLipid,
19
+ BloodResultsLipids.lab_panel,
20
+ model_cls=BloodResultsLipids,
21
21
  extra_fieldsets=[
22
22
  (-1, action_fieldset_tuple),
23
23
  ],
@@ -4,7 +4,7 @@ from .blood_results import (
4
4
  BloodResultsHba1cForm,
5
5
  BloodResultsInsForm,
6
6
  BloodResultsLftForm,
7
- BloodResultsLipidForm,
7
+ BloodResultsLipidsForm,
8
8
  BloodResultsRftForm,
9
9
  )
10
10
  from .complications_glycemia_form import ComplicationsGlycemiaForm
@@ -2,5 +2,5 @@ from .blood_results_fbc_form import BloodResultsFbcForm
2
2
  from .blood_results_hba1c_form import BloodResultsHba1cForm
3
3
  from .blood_results_ins_form import BloodResultsInsForm
4
4
  from .blood_results_lft_form import BloodResultsLftForm
5
- from .blood_results_lipid_form import BloodResultsLipidForm
5
+ from .blood_results_lipids_form import BloodResultsLipidsForm
6
6
  from .blood_results_rft_form import BloodResultsRftForm
@@ -5,16 +5,16 @@ from edc_crf.modelform_mixins import CrfModelFormMixin
5
5
  from edc_lab_panel.panels import lipids_panel
6
6
  from edc_lab_results.form_validator_mixins import BloodResultsFormValidatorMixin
7
7
 
8
- from ...models import BloodResultsLipid
8
+ from ...models import BloodResultsLipids
9
9
 
10
10
 
11
- class BloodResultsLipidFormValidator(BloodResultsFormValidatorMixin, CrfFormValidator):
11
+ class BloodResultsLipidsFormValidator(BloodResultsFormValidatorMixin, CrfFormValidator):
12
12
  panel = lipids_panel
13
13
 
14
14
 
15
- class BloodResultsLipidForm(ActionItemCrfFormMixin, CrfModelFormMixin, forms.ModelForm):
16
- form_validator_cls = BloodResultsLipidFormValidator
15
+ class BloodResultsLipidsForm(ActionItemCrfFormMixin, CrfModelFormMixin, forms.ModelForm):
16
+ form_validator_cls = BloodResultsLipidsFormValidator
17
17
 
18
18
  class Meta(ActionItemCrfFormMixin.Meta):
19
- model = BloodResultsLipid
19
+ model = BloodResultsLipids
20
20
  fields = "__all__"
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.0.8 on 2024-08-27 19:22
2
+
3
+ from django.db import migrations
4
+ from django.db.migrations import RunPython
5
+ from edc_constants.constants import NO, YES
6
+
7
+
8
+ def update_old_fasting_choices(apps, schema_editor):
9
+ result = {"fasting": 0, "non_fasting": 0}
10
+ model_cls = apps.get_model("meta_subject.glucosefbg")
11
+ result["fasting"] = model_cls.objects.filter(fasting="fasting").update(fasting=YES)
12
+ result["non_fasting"] = model_cls.objects.filter(fasting="non_fasting").update(fasting=NO)
13
+ print(f"Updated: results are {result}")
14
+ print("Done.")
15
+
16
+
17
+ class Migration(migrations.Migration):
18
+
19
+ dependencies = [
20
+ ("meta_subject", "0211_dmendpoint_endpoint_reached_and_more"),
21
+ ]
22
+
23
+ operations = [RunPython(update_old_fasting_choices)]
@@ -0,0 +1,35 @@
1
+ # Generated by Django 5.0.8 on 2024-08-28 19:54
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("edc_action_item", "0037_remove_actionitem_reference_model_and_more"),
11
+ ("meta_subject", "0212_auto_20240827_2222"),
12
+ ("sites", "0002_alter_domain_unique"),
13
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14
+ ]
15
+
16
+ operations = [
17
+ migrations.RenameModel(
18
+ old_name="BloodResultsLipid",
19
+ new_name="BloodResultsLipids",
20
+ ),
21
+ migrations.RenameModel(
22
+ old_name="HistoricalBloodResultsLipid",
23
+ new_name="HistoricalBloodResultsLipids",
24
+ ),
25
+ migrations.RenameIndex(
26
+ model_name="bloodresultslipids",
27
+ new_name="meta_subjec_subject_eff3e6_idx",
28
+ old_name="meta_subjec_subject_296de9_idx",
29
+ ),
30
+ migrations.RenameIndex(
31
+ model_name="bloodresultslipids",
32
+ new_name="meta_subjec_subject_49b971_idx",
33
+ old_name="meta_subjec_subject_9692a2_idx",
34
+ ),
35
+ ]
@@ -44,7 +44,7 @@ class ArvHistoryModelMixin(models.Model):
44
44
  ArvRegimens,
45
45
  on_delete=models.PROTECT,
46
46
  related_name="current_arv_regimen",
47
- verbose_name=("Which antiretroviral therapy regimen is the patient currently on?"),
47
+ verbose_name="Which antiretroviral therapy regimen is the patient currently on?",
48
48
  null=True,
49
49
  blank=False,
50
50
  )
@@ -69,7 +69,7 @@ class ArvHistoryModelMixin(models.Model):
69
69
  ArvRegimens,
70
70
  on_delete=models.PROTECT,
71
71
  related_name="previous_arv_regimen",
72
- verbose_name=("Which antiretroviral therapy regimen was the patient previously on?"),
72
+ verbose_name="Which antiretroviral therapy regimen was the patient previously on?",
73
73
  null=True,
74
74
  blank=True,
75
75
  )
@@ -77,7 +77,7 @@ class ArvHistoryModelMixin(models.Model):
77
77
  other_previous_arv_regimen = OtherCharField(null=True, blank=True)
78
78
 
79
79
  on_oi_prophylaxis = models.CharField(
80
- verbose_name=("Is the patient on any prophylaxis against opportunistic infections?"),
80
+ verbose_name="Is the patient on any prophylaxis against opportunistic infections?",
81
81
  max_length=15,
82
82
  choices=YES_NO,
83
83
  )
@@ -4,7 +4,7 @@ from .blood_results import (
4
4
  BloodResultsHba1c,
5
5
  BloodResultsIns,
6
6
  BloodResultsLft,
7
- BloodResultsLipid,
7
+ BloodResultsLipids,
8
8
  BloodResultsRft,
9
9
  )
10
10
  from .complications import Complications
@@ -2,5 +2,5 @@ from .blood_results_fbc import BloodResultsFbc
2
2
  from .blood_results_hba1c import BloodResultsHba1c
3
3
  from .blood_results_ins import BloodResultsIns
4
4
  from .blood_results_lft import BloodResultsLft
5
- from .blood_results_lipid import BloodResultsLipid
5
+ from .blood_results_lipids import BloodResultsLipids
6
6
  from .blood_results_rft import BloodResultsRft
@@ -2,7 +2,7 @@ from django.db import models
2
2
  from edc_crf.model_mixins import CrfStatusModelMixin
3
3
  from edc_lab.model_mixins import CrfWithRequisitionModelMixin, requisition_fk_options
4
4
  from edc_lab_panel.panels import lipids_panel
5
- from edc_lab_results import BLOOD_RESULTS_LIPID_ACTION
5
+ from edc_lab_results import BLOOD_RESULTS_LIPIDS_ACTION
6
6
  from edc_lab_results.model_mixins import (
7
7
  BloodResultsModelMixin,
8
8
  CholModelMixin,
@@ -15,7 +15,7 @@ from edc_model.models import BaseUuidModel
15
15
  from ...model_mixins import CrfWithActionModelMixin
16
16
 
17
17
 
18
- class BloodResultsLipid(
18
+ class BloodResultsLipids(
19
19
  CrfWithActionModelMixin,
20
20
  HdlModelMixin,
21
21
  LdlModelMixin,
@@ -26,7 +26,7 @@ class BloodResultsLipid(
26
26
  CrfStatusModelMixin,
27
27
  BaseUuidModel,
28
28
  ):
29
- action_name = BLOOD_RESULTS_LIPID_ACTION
29
+ action_name = BLOOD_RESULTS_LIPIDS_ACTION
30
30
  tracking_identifier_prefix = "LP"
31
31
  lab_panel = lipids_panel
32
32