From e698be43cbab3da66c97fbf2d9d7ec6718da141f Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Sun, 22 Feb 2026 06:40:47 -0800 Subject: [PATCH 1/3] Add qcState to getScheduledTimelinesForSpecies API --- .../SNPRC_schedulerService.java | 2 +- .../SNPRC_schedulerController.java | 3 +- .../services/SNPRC_schedulerServiceImpl.java | 37 ++++++++++++++++--- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/snprc_scheduler/api-src/org/labkey/api/snprc_scheduler/SNPRC_schedulerService.java b/snprc_scheduler/api-src/org/labkey/api/snprc_scheduler/SNPRC_schedulerService.java index 035846843..ec3eb7f42 100644 --- a/snprc_scheduler/api-src/org/labkey/api/snprc_scheduler/SNPRC_schedulerService.java +++ b/snprc_scheduler/api-src/org/labkey/api/snprc_scheduler/SNPRC_schedulerService.java @@ -27,7 +27,7 @@ static SNPRC_schedulerService get() } List getActiveTimelines(Container c, User u, String ProjectObjectId, BatchValidationException errors); - List getScheduledTimelinesForSpecies(Container c, User u, String species, Date date, BatchValidationException errors); + List getScheduledTimelinesForSpecies(Container c, User u, String species, Date date, String qcState, BatchValidationException errors); List> getActiveProjects(Container c, User u, ArrayList filters, Boolean activeProjectItemsOnly, Date eventDate); JSONObject saveTimelineData(Container c, User u, JSONObject json, BatchValidationException errors); } diff --git a/snprc_scheduler/src/org/labkey/snprc_scheduler/SNPRC_schedulerController.java b/snprc_scheduler/src/org/labkey/snprc_scheduler/SNPRC_schedulerController.java index 711a267ba..51ff7e5c8 100644 --- a/snprc_scheduler/src/org/labkey/snprc_scheduler/SNPRC_schedulerController.java +++ b/snprc_scheduler/src/org/labkey/snprc_scheduler/SNPRC_schedulerController.java @@ -118,13 +118,14 @@ public ApiResponse execute(SimpleApiJsonForm form, BindException errors) { species = url.getParameter("species"); dateString = url.getParameter("date"); + String qcState = url.getParameter("qcState"); // assume current date if date is not passed in date = (dateString == null ? new Date() : DateUtil.parseDateTime(dateString, Timeline.TIMELINE_DATE_FORMAT)); if (species != null && date != null) { timelines = SNPRC_schedulerService.get().getScheduledTimelinesForSpecies(getContainer(), getUser(), - species, date, new BatchValidationException()); + species, date, qcState, new BatchValidationException()); props.put("success", true); props.put("rows", timelines); diff --git a/snprc_scheduler/src/org/labkey/snprc_scheduler/services/SNPRC_schedulerServiceImpl.java b/snprc_scheduler/src/org/labkey/snprc_scheduler/services/SNPRC_schedulerServiceImpl.java index c74bb1bfd..8490b3f09 100644 --- a/snprc_scheduler/src/org/labkey/snprc_scheduler/services/SNPRC_schedulerServiceImpl.java +++ b/snprc_scheduler/src/org/labkey/snprc_scheduler/services/SNPRC_schedulerServiceImpl.java @@ -25,12 +25,15 @@ import org.labkey.snprc_scheduler.domains.TimelineAnimalJunction; import org.labkey.snprc_scheduler.domains.TimelineItem; import org.labkey.snprc_scheduler.domains.TimelineProjectItem; +import org.labkey.snprc_scheduler.security.QCStateEnum; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; +import static org.apache.commons.lang3.StringUtils.isNotBlank; + /** * Created by thawkins on 10/21/2018 */ @@ -87,9 +90,20 @@ public List getActiveTimelines(Container c, User u, String projectOb } - //TODO: need to add scheduleDate criteria + /** + * Retrieves timelines for a given species that have procedures scheduled on a specific date. + * Optionally filters by QC state. + * + * @param c = Container object + * @param u = User object + * @param species = species identifier to filter timelines + * @param date = schedule date to match against timeline items + * @param qcState = optional QC state name to further filter timelines + * @param errors = exception object for collecting validation errors + * @return list of timeline JSON objects matching the criteria + */ @Override - public List getScheduledTimelinesForSpecies(Container c, User u, String species, Date date, BatchValidationException errors) throws ApiUsageException + public List getScheduledTimelinesForSpecies(Container c, User u, String species, Date date, String qcState, BatchValidationException errors) throws ApiUsageException { List timelinesJson = new ArrayList<>(); try @@ -97,7 +111,7 @@ public List getScheduledTimelinesForSpecies(Container c, User u, Str SNPRC_schedulerUserSchema schema = SNPRC_schedulerManager.getSNPRC_schedulerUserSchema(c, u); TableInfo timelineTable = schema.getTable(SNPRC_schedulerSchema.TABLE_NAME_TIMELINE, schema.getDefaultContainerFilter(), false, false); - // only return timelines with procedures scheduled on specified date + // Query for timeline ObjectIds that have items scheduled on the given date SQLFragment sql = new SQLFragment(); sql.append("SELECT DISTINCT t." + Timeline.TIMELINE_OBJECTID); sql.append(" FROM "); @@ -105,19 +119,30 @@ public List getScheduledTimelinesForSpecies(Container c, User u, Str sql.append(" JOIN "); sql.append(SNPRC_schedulerSchema.getInstance().getTableInfoTimelineItem(), "ti"); sql.append(" ON t." + Timeline.TIMELINE_OBJECTID + " = ti." + TimelineItem.TIMELINEITEM_TIMELINE_OBJECT_ID); - sql.append(" WHERE " + "ti." + TimelineItem.TIMELINEITEM_SCHEDULE_DATE + " = ?" ).add(date); + sql.append(" WHERE ti." + TimelineItem.TIMELINEITEM_SCHEDULE_DATE + " = ?").add(date); SqlSelector selector = new SqlSelector(SNPRC_schedulerSchema.getInstance().getSchema(), sql); List objectIds = new ArrayList<>(); selector.forEachMap(row -> objectIds.add( (String) row.get(Timeline.TIMELINE_OBJECTID))); - //SimpleFilter filter = new SimpleFilter(FieldKey.fromParts(Timeline.TIMELINE_SPECIES, "referenceId", "species"), species, CompareType.EQUAL); + // Build filter for species, matching ObjectIds, and optional QC state SimpleFilter filter = new SimpleFilter(FieldKey.fromParts("sndProject", "referenceId", "species"), species, CompareType.EQUAL); - filter.addInClause(FieldKey.fromParts(Timeline.TIMELINE_OBJECTID), objectIds ); + filter.addInClause(FieldKey.fromParts(Timeline.TIMELINE_OBJECTID), objectIds); + + if (isNotBlank(qcState)) + { + Integer qcStateId = QCStateEnum.getQCStateEnumId(c, u, + QCStateEnum.getQCStateEnumByName(qcState)); + if (qcStateId != null) + { + filter.addCondition(FieldKey.fromParts(Timeline.TIMELINE_QCSTATE), qcStateId, CompareType.EQUAL); + } + } List timelines = new TableSelector(timelineTable, filter, null).getArrayList(Timeline.class); + // Populate nested collections for each timeline and convert to JSON for (Timeline timeline : timelines) { timeline.setTimelineItems(SNPRC_schedulerManager.get().getTimelineItems(c, u, timeline.getObjectId(), date)); From 998455bc120594709033642296c1db52324651f1 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Sun, 22 Feb 2026 06:41:01 -0800 Subject: [PATCH 2/3] Update current location query --- .../resources/queries/study/demographicsCurLocation.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/snprc_ehr/resources/queries/study/demographicsCurLocation.sql b/snprc_ehr/resources/queries/study/demographicsCurLocation.sql index 3f69f9999..f47befeec 100644 --- a/snprc_ehr/resources/queries/study/demographicsCurLocation.sql +++ b/snprc_ehr/resources/queries/study/demographicsCurLocation.sql @@ -22,5 +22,11 @@ SELECT d2.id, coalesce(d2.cage, '') AS cage_order, d2.cage_sortValue @hidden FROM study.housing d2 +INNER JOIN (SELECT d3.id, MAX(d3.date) AS maxDate + FROM study.housing d3 + WHERE d3.enddate IS NULL + AND d3.qcstate.publicdata = true + GROUP BY d3.id) latest + ON d2.id = latest.id AND d2.date = latest.maxDate WHERE d2.enddate IS NULL AND d2.qcstate.publicdata = true; \ No newline at end of file From b7ea888e06ad16382d9c7771ad15ac6205ac6ff3 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Thu, 26 Feb 2026 08:12:14 -0800 Subject: [PATCH 3/3] Revert "Update current location query" This reverts commit 998455bc120594709033642296c1db52324651f1. --- .../resources/queries/study/demographicsCurLocation.sql | 6 ------ 1 file changed, 6 deletions(-) diff --git a/snprc_ehr/resources/queries/study/demographicsCurLocation.sql b/snprc_ehr/resources/queries/study/demographicsCurLocation.sql index f47befeec..3f69f9999 100644 --- a/snprc_ehr/resources/queries/study/demographicsCurLocation.sql +++ b/snprc_ehr/resources/queries/study/demographicsCurLocation.sql @@ -22,11 +22,5 @@ SELECT d2.id, coalesce(d2.cage, '') AS cage_order, d2.cage_sortValue @hidden FROM study.housing d2 -INNER JOIN (SELECT d3.id, MAX(d3.date) AS maxDate - FROM study.housing d3 - WHERE d3.enddate IS NULL - AND d3.qcstate.publicdata = true - GROUP BY d3.id) latest - ON d2.id = latest.id AND d2.date = latest.maxDate WHERE d2.enddate IS NULL AND d2.qcstate.publicdata = true; \ No newline at end of file