Skip to content

Commit f855508

Browse files
committed
TreatmentManager container scoping
1 parent b29668a commit f855508

1 file changed

Lines changed: 74 additions & 3 deletions

File tree

studydesign/src/org/labkey/studydesign/model/TreatmentManager.java

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,10 @@ public void deleteStudyProduct(Container container, User user, int rowId)
318318
deleteProductAntigens(container, user, rowId);
319319

320320
// delete the associated doses and routes for this product
321-
Table.delete(StudyDesignSchema.getInstance().getTableInfoDoseAndRoute(), new SimpleFilter(FieldKey.fromParts("ProductId"), rowId));
321+
// GitHub Kanban #1929: scope to the container in addition to ProductId
322+
SimpleFilter doseAndRouteFilter = SimpleFilter.createContainerFilter(container);
323+
doseAndRouteFilter.addCondition(FieldKey.fromParts("ProductId"), rowId);
324+
Table.delete(StudyDesignSchema.getInstance().getTableInfoDoseAndRoute(), doseAndRouteFilter);
322325

323326
// delete the associated treatment study product mappings (provision table)
324327
SimpleFilter filter = SimpleFilter.createContainerFilter(container);
@@ -368,14 +371,18 @@ public DoseAndRoute saveStudyProductDoseAndRoute(Container container, User user,
368371

369372
public Collection<DoseAndRoute> getStudyProductsDoseAndRoute(Container container, User user, int productId)
370373
{
371-
SimpleFilter filter = new SimpleFilter(FieldKey.fromParts("ProductId"), productId);
374+
// GitHub Kanban #1929: scope to the container in addition to ProductId
375+
SimpleFilter filter = SimpleFilter.createContainerFilter(container);
376+
filter.addCondition(FieldKey.fromParts("ProductId"), productId);
372377
return new TableSelector(StudyDesignSchema.getInstance().getTableInfoDoseAndRoute(), filter, null).getCollection(DoseAndRoute.class);
373378
}
374379

375380
@Nullable
376381
public DoseAndRoute getDoseAndRoute(Container container, String dose, String route, int productId)
377382
{
378-
SimpleFilter filter = new SimpleFilter(FieldKey.fromParts("ProductId"), productId);
383+
// GitHub Kanban #1929: scope to the container in addition to ProductId
384+
SimpleFilter filter = SimpleFilter.createContainerFilter(container);
385+
filter.addCondition(FieldKey.fromParts("ProductId"), productId);
379386
if (dose != null)
380387
filter.addCondition(FieldKey.fromParts("Dose"), dose);
381388
else
@@ -989,6 +996,70 @@ private void tearDown()
989996
assertTrue(ContainerManager.delete(_junitStudy.getContainer(), _context.getUser()));
990997
}
991998
}
999+
1000+
// GitHub Kanban #1929: getStudyProductsDoseAndRoute / getDoseAndRoute / deleteStudyProduct container scoping checks
1001+
@Test
1002+
public void testDoseAndRouteContainerScoping() throws Exception
1003+
{
1004+
TestContext context = TestContext.get();
1005+
User user = context.getUser();
1006+
Container containerA = null;
1007+
Container containerB = null;
1008+
try
1009+
{
1010+
containerA = createStudyContainer(context, GUID.makeHash());
1011+
containerB = createStudyContainer(context, GUID.makeHash());
1012+
1013+
int productIdA = insertStudyProduct(containerA, user, "Immunogen A", "Immunogen");
1014+
int productIdB = insertStudyProduct(containerB, user, "Immunogen B", "Immunogen");
1015+
1016+
_manager.saveStudyProductDoseAndRoute(containerA, user, new DoseAndRoute("Dose A", "Route A", productIdA, containerA));
1017+
_manager.saveStudyProductDoseAndRoute(containerB, user, new DoseAndRoute("Dose B", "Route B", productIdB, containerB));
1018+
1019+
// getStudyProductsDoseAndRoute: scoped by container, not ProductId alone
1020+
assertEquals("Dose/route should be returned within its own container", 1,
1021+
_manager.getStudyProductsDoseAndRoute(containerB, user, productIdB).size());
1022+
assertEquals("Dose/route must not be returned from another container", 0,
1023+
_manager.getStudyProductsDoseAndRoute(containerA, user, productIdB).size());
1024+
1025+
// getDoseAndRoute: same scoping
1026+
assertNotNull("getDoseAndRoute should find the row within its own container",
1027+
_manager.getDoseAndRoute(containerB, "Dose B", "Route B", productIdB));
1028+
assertNull("getDoseAndRoute must not find the row from another container",
1029+
_manager.getDoseAndRoute(containerA, "Dose B", "Route B", productIdB));
1030+
1031+
// deleteStudyProduct's dose/route delete is now container scoped; deleting the product in its own
1032+
// container removes its dose/route (the cross-container case is unreachable since ProductId is unique).
1033+
_manager.deleteStudyProduct(containerB, user, productIdB);
1034+
assertEquals("deleteStudyProduct should remove the dose/route within its own container", 0,
1035+
_manager.getStudyProductsDoseAndRoute(containerB, user, productIdB).size());
1036+
}
1037+
finally
1038+
{
1039+
if (null != containerB)
1040+
ContainerManager.delete(containerB, user);
1041+
if (null != containerA)
1042+
ContainerManager.delete(containerA, user);
1043+
}
1044+
}
1045+
1046+
private Container createStudyContainer(TestContext context, String name)
1047+
{
1048+
Container junit = JunitUtil.getTestContainer();
1049+
Container c = ContainerManager.createContainer(junit, name, context.getUser());
1050+
Set<Module> modules = new HashSet<>(c.getActiveModules());
1051+
modules.add(ModuleLoader.getInstance().getModule("studydesign"));
1052+
c.setActiveModules(modules);
1053+
StudyService.get().createStudy(c, context.getUser(), "Junit Study " + name, TimepointType.VISIT, true);
1054+
return c;
1055+
}
1056+
1057+
private int insertStudyProduct(Container c, User user, String label, String role)
1058+
{
1059+
UserSchema schema = QueryService.get().getUserSchema(user, c, StudyDesignQuerySchema.STUDY_SCHEMA_NAME);
1060+
TableInfo ti = ((FilteredTable) schema.getTable(StudyDesignQuerySchema.PRODUCT_TABLE_NAME)).getRealTable();
1061+
return Table.insert(user, ti, new ProductImpl(c, label, role)).getRowId();
1062+
}
9921063
}
9931064

9941065
@TestWhen(TestWhen.When.BVT)

0 commit comments

Comments
 (0)