@@ -78,6 +78,82 @@ def test_refresh_statistics_rebuilds_counters_from_records(mock_enqueue_task, te
7878 assert statistics .feature_models_downloaded == 1
7979
8080
81+ # ─── DOI filter on refresh_statistics ──────────────────────────────────────
82+
83+
84+ @patch ("core.managers.task_queue_manager.TaskQueueManager.enqueue_task" )
85+ def test_refresh_statistics_excludes_private_datasets (mock_enqueue_task , test_client , clean_database ):
86+ """Views and downloads for datasets without a DOI must not be counted,
87+ otherwise the `/statistics` summary cards disagree with the top-N tables.
88+ """
89+ user = UserRepository ().create (email = "stats-private@example.com" , password = "test1234" )
90+
91+ public_meta = DSMetaDataRepository ().create (
92+ title = "Public" ,
93+ description = "Public" ,
94+ publication_type = PublicationType .BOOK ,
95+ dataset_doi = "10.1234/public" ,
96+ )
97+ public_ds = DataSetRepository ().create (user_id = user .id , ds_meta_data_id = public_meta .id )
98+ public_fm = FeatureModelRepository ().create (dataset_id = public_ds .id )
99+ public_hubfile = HubfileRepository ().create (
100+ name = "public.uvl" , checksum = "pub" , size = 1 , feature_model_id = public_fm .id
101+ )
102+ DSViewRecordRepository ().create (dataset_id = public_ds .id , view_cookie = "pub-v" )
103+ DSDownloadRecordRepository ().create (dataset_id = public_ds .id , download_cookie = "pub-d" )
104+ HubfileViewRecordRepository ().create (file_id = public_hubfile .id , view_cookie = "pub-fv" )
105+ HubfileDownloadRecordRepository ().create (file_id = public_hubfile .id , download_cookie = "pub-fd" )
106+
107+ private_meta = DSMetaDataRepository ().create (
108+ title = "Private" ,
109+ description = "Private" ,
110+ publication_type = PublicationType .BOOK ,
111+ dataset_doi = None ,
112+ )
113+ private_ds = DataSetRepository ().create (user_id = user .id , ds_meta_data_id = private_meta .id )
114+ private_fm = FeatureModelRepository ().create (dataset_id = private_ds .id )
115+ private_hubfile = HubfileRepository ().create (
116+ name = "priv.uvl" , checksum = "priv" , size = 1 , feature_model_id = private_fm .id
117+ )
118+ DSViewRecordRepository ().create (dataset_id = private_ds .id , view_cookie = "priv-v" )
119+ DSDownloadRecordRepository ().create (dataset_id = private_ds .id , download_cookie = "priv-d" )
120+ HubfileViewRecordRepository ().create (file_id = private_hubfile .id , view_cookie = "priv-fv" )
121+ HubfileDownloadRecordRepository ().create (file_id = private_hubfile .id , download_cookie = "priv-fd" )
122+
123+ stats = StatisticsService ().refresh_statistics ()
124+
125+ assert stats .datasets_counter == 1
126+ assert stats .feature_models_counter == 1
127+ assert stats .datasets_viewed == 1
128+ assert stats .datasets_downloaded == 1
129+ assert stats .feature_models_viewed == 1
130+ assert stats .feature_models_downloaded == 1
131+
132+
133+ def test_preview_refresh_returns_before_after_tuples (test_client , clean_database ):
134+ user = UserRepository ().create (email = "preview@example.com" , password = "test1234" )
135+ meta = DSMetaDataRepository ().create (
136+ title = "Preview" ,
137+ description = "Preview" ,
138+ publication_type = PublicationType .BOOK ,
139+ dataset_doi = "10.9999/preview" ,
140+ )
141+ ds = DataSetRepository ().create (user_id = user .id , ds_meta_data_id = meta .id )
142+ FeatureModelRepository ().create (dataset_id = ds .id )
143+
144+ service = StatisticsService ()
145+ diff = service .preview_refresh ()
146+
147+ # Snapshot is untouched by a dry-run preview.
148+ persisted = service .get_statistics ()
149+ assert persisted .datasets_counter == 0
150+ assert persisted .feature_models_counter == 0
151+
152+ # The diff maps each field to (before, after).
153+ assert diff ["datasets_counter" ] == (0 , 1 )
154+ assert diff ["feature_models_counter" ] == (0 , 1 )
155+
156+
81157# ─── Dashboard ──────────────────────────────────────────────────────────────
82158
83159
0 commit comments