Repository navigation
Conversation
RunHelper::getUserDetailExportPdoStatement() computed seconds_stayed as IF(ended > 0, ended - created, NOW() - created). A unit session that expired rather than ended has `ended` NULL, so every expired row fell into the NOW() branch and reported "time since the participant entered this unit, as of the moment of export" instead of a duration. The value therefore grew on every re-export and disagreed with the raw timestamps rendered by the admin web view, which selects created/ended/expired unmodified via getUserDetailTable(). Observed on an ESM run: a Wait that actually lasted 1 s exported as 424 s, and all nine expired rows in the CSV resolved to the same wall-clock instant (entered + seconds_stayed == export time). Fall back to `expired` before NOW(), so NOW() applies only to sessions that are still genuinely open. Rows with `ended` set are unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CSV export carried only created/ended/expired, while the admin web view (templates/admin/run/user_detail.php) also renders `expires` — bolded while `queued > 0` — and `result` with `result_log` as tooltip. That gap made a whole class of bug undiagnosable from an export. A Pause/Wait's computed deadline lives only in `expires`, so an export showing a 10-minute Wait that ended after 1 second gave no way to tell whether the deadline was miscomputed or a correct deadline was ignored. Answering that required a PDF print of the web view. Columns are appended after the existing nine so positional parsers of the old format keep working. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Discrepancy see here:
formr admin.pdf
esm_user_detail.csv
Liebe Grüße!
Tim
The bug
RunHelper::getUserDetailExportPdoStatement()computed the exportedseconds_stayedas:A unit session that expired rather than ended has
endedNULL, soevery expired row fell into the
NOW()branch. The column then reported"time since the participant entered this unit, as of the moment you clicked
Export" rather than a duration.
Consequences:
property of the data.
created/ended/expiredunmodified viagetUserDetailTable()and therefore shows thetruth.
exactly the units whose timing you would export a user detail CSV to
investigate.
Evidence
From an ESM run on a real study (CSV export + printed web view of the same
session, both attached to the issue):
seconds_stayedAll nine expired rows in that export resolve to the same wall-clock instant:
entered + seconds_stayed == 13:56:55for every one of them — the moment theexport ran. That is the fingerprint of the
NOW()branch. The web view forthe same rows correctly shows "a moment" / "1 minute".
The fix
Fall back to
expiredbeforeNOW():UNIX_TIMESTAMP( CASE WHEN ended > 0 THEN ended WHEN expired > 0 THEN expired ELSE NOW() END ) - UNIX_TIMESTAMP(created) AS 'seconds_stayed'NOW()now applies only to sessions that are still genuinely open (neitherended nor expired), where "elapsed so far" is the intended meaning. Rows with
endedset are unaffected — no change to existing correct output.Also: four columns added to the export
The CSV carried only
created/ended/expired, whiletemplates/admin/run/user_detail.phpadditionally rendersexpires(boldedwhile
queued > 0) andresultwithresult_logas its tooltip.That gap made this class of bug undiagnosable from an export alone: a
Pause/Wait's computed deadline lives only in
expires, so an export showinga 10-minute Wait that ended after 1 second gives no way to tell whether the
deadline was miscomputed or a correct deadline was ignored. Answering that
question here required a PDF print of the web view.
expires,queued,result,result_logare appended after the existingnine columns, so positional parsers of the old format keep working.