Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion apps/opencase/src/application/case/endpoints/GetCFConcept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@ export class GetCFConcept {
async execute (query: GetCFConceptQuery) {
const entry = this.store.getDefinitionById(query.tenantId, query.caseVersion, 'CFConcepts', query.sourcedId)
if (!entry) return null
return entry.value

// Per spec, the response is the CFConcept plus the set of children as
// determined by their place in the 'hierarchyCode' of the CFConcept.
const hierarchyCode = entry.value?.hierarchyCode as string | undefined
const allConcepts = this.store.getTenantDefinitions(query.tenantId, query.caseVersion).CFConcepts
const children = hierarchyCode
? allConcepts
.filter((c: any) => c.identifier !== entry.value.identifier && typeof c.hierarchyCode === 'string' && c.hierarchyCode.startsWith(`${hierarchyCode}.`))
.sort((a: any, b: any) => a.hierarchyCode.localeCompare(b.hierarchyCode))
: []

return { CFConcepts: [entry.value, ...children] }
}
}

Expand Down
13 changes: 12 additions & 1 deletion apps/opencase/src/application/case/endpoints/GetCFItemType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@ export class GetCFItemType {
async execute (query: GetCFItemTypeQuery) {
const entry = this.store.getDefinitionById(query.tenantId, query.caseVersion, 'CFItemTypes', query.sourcedId)
if (!entry) return null
return entry.value

// Per spec, the response is the CFItemType plus the set of children as
// determined by their place in the 'hierarchyCode' of the CFItemType.
const hierarchyCode = entry.value?.hierarchyCode as string | undefined
const allItemTypes = this.store.getTenantDefinitions(query.tenantId, query.caseVersion).CFItemTypes
const children = hierarchyCode
? allItemTypes
.filter((t: any) => t.identifier !== entry.value.identifier && typeof t.hierarchyCode === 'string' && t.hierarchyCode.startsWith(`${hierarchyCode}.`))
.sort((a: any, b: any) => a.hierarchyCode.localeCompare(b.hierarchyCode))
: []

return { CFItemTypes: [entry.value, ...children] }
}
}

Expand Down
13 changes: 12 additions & 1 deletion apps/opencase/src/application/case/endpoints/GetCFSubject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@ export class GetCFSubject {
async execute (query: GetCFSubjectQuery) {
const entry = this.store.getDefinitionById(query.tenantId, query.caseVersion, 'CFSubjects', query.sourcedId)
if (!entry) return null
return entry.value

// Per spec, the response is the CFSubject plus the set of children as
// determined by their place in the 'hierarchyCode' of the CFSubject.
const hierarchyCode = entry.value?.hierarchyCode as string | undefined
const allSubjects = this.store.getTenantDefinitions(query.tenantId, query.caseVersion).CFSubjects
const children = hierarchyCode
? allSubjects
.filter((s: any) => s.identifier !== entry.value.identifier && typeof s.hierarchyCode === 'string' && s.hierarchyCode.startsWith(`${hierarchyCode}.`))
.sort((a: any, b: any) => a.hierarchyCode.localeCompare(b.hierarchyCode))
: []

return { CFSubjects: [entry.value, ...children] }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe('GetCFConcept', () => {
} as any

mockStore = {
getDefinitionById: jest.fn()
getDefinitionById: jest.fn(),
getTenantDefinitions: jest.fn()
} as any

getCFConcept = new GetCFConcept(mockRepository, mockStore)
Expand All @@ -34,23 +35,42 @@ describe('GetCFConcept', () => {
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFConcepts', conceptId)
})

it('should return CFConcept when found', async () => {
it('should return a CFConceptSet containing just the concept when it has no children', async () => {
const concept = {
identifier: conceptId,
title: 'Test Concept',
hierarchyCode: '1.01',
uri: '/ims/case/v1p1/CFConcepts/concept-123'
}

mockStore.getDefinitionById.mockReturnValue({
docSourcedId: 'doc-123',
value: concept
} as any)
mockStore.getTenantDefinitions.mockReturnValue({ CFConcepts: [concept] } as any)

const result = await getCFConcept.execute({ tenantId, caseVersion, sourcedId: conceptId })

expect(result).toEqual(concept)
expect(result).toEqual({ CFConcepts: [concept] })
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFConcepts', conceptId)
})

it('should include children determined by hierarchyCode, sorted, excluding unrelated siblings', async () => {
const concept = { identifier: conceptId, title: 'Parent', hierarchyCode: '1.01' }
const childB = { identifier: 'child-b', title: 'Child B', hierarchyCode: '1.01.02' }
const childA = { identifier: 'child-a', title: 'Child A', hierarchyCode: '1.01.01' }
const unrelated = { identifier: 'other', title: 'Unrelated', hierarchyCode: '1.02' }
const falsePrefixMatch = { identifier: 'not-a-child', title: 'Not a child', hierarchyCode: '1.010' }

mockStore.getDefinitionById.mockReturnValue({ docSourcedId: 'doc-123', value: concept } as any)
mockStore.getTenantDefinitions.mockReturnValue({
CFConcepts: [concept, childB, childA, unrelated, falsePrefixMatch]
} as any)

const result = await getCFConcept.execute({ tenantId, caseVersion, sourcedId: conceptId })

expect(result).toEqual({ CFConcepts: [concept, childA, childB] })
})
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe('GetCFItemType', () => {
} as any

mockStore = {
getDefinitionById: jest.fn()
getDefinitionById: jest.fn(),
getTenantDefinitions: jest.fn()
} as any

getCFItemType = new GetCFItemType(mockRepository, mockStore)
Expand All @@ -34,7 +35,7 @@ describe('GetCFItemType', () => {
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFItemTypes', itemTypeId)
})

it('should return CFItemType when found', async () => {
it('should return a CFItemTypeSet containing just the item type when it has no children', async () => {
const itemType = {
identifier: itemTypeId,
title: 'Test Item Type',
Expand All @@ -49,12 +50,29 @@ describe('GetCFItemType', () => {
value: itemType,
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
} as any)
mockStore.getTenantDefinitions.mockReturnValue({ CFItemTypes: [itemType] } as any)

const result = await getCFItemType.execute({ tenantId, caseVersion, sourcedId: itemTypeId })

expect(result).toEqual(itemType)
expect(result).toEqual({ CFItemTypes: [itemType] })
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFItemTypes', itemTypeId)
})

it('should include children determined by hierarchyCode, sorted', async () => {
const itemType = { identifier: itemTypeId, title: 'Parent', hierarchyCode: '01' }
const childB = { identifier: 'child-b', title: 'Child B', hierarchyCode: '01.02' }
const childA = { identifier: 'child-a', title: 'Child A', hierarchyCode: '01.01' }
const unrelated = { identifier: 'other', title: 'Unrelated', hierarchyCode: '02' }

mockStore.getDefinitionById.mockReturnValue({ docSourcedId: 'doc-123', value: itemType } as any)
mockStore.getTenantDefinitions.mockReturnValue({
CFItemTypes: [itemType, childB, childA, unrelated]
} as any)

const result = await getCFItemType.execute({ tenantId, caseVersion, sourcedId: itemTypeId })

expect(result).toEqual({ CFItemTypes: [itemType, childA, childB] })
})
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe('GetCFSubject', () => {
} as any

mockStore = {
getDefinitionById: jest.fn()
getDefinitionById: jest.fn(),
getTenantDefinitions: jest.fn()
} as any

getCFSubject = new GetCFSubject(mockRepository, mockStore)
Expand All @@ -34,23 +35,41 @@ describe('GetCFSubject', () => {
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFSubjects', subjectId)
})

it('should return CFSubject when found', async () => {
it('should return a CFSubjectSet containing just the subject when it has no children', async () => {
const subject = {
identifier: subjectId,
title: 'Mathematics',
hierarchyCode: '1.01',
uri: '/ims/case/v1p1/CFSubjects/subject-123'
}

mockStore.getDefinitionById.mockReturnValue({
docSourcedId: 'doc-123',
value: subject
} as any)
mockStore.getTenantDefinitions.mockReturnValue({ CFSubjects: [subject] } as any)

const result = await getCFSubject.execute({ tenantId, caseVersion, sourcedId: subjectId })

expect(result).toEqual(subject)
expect(result).toEqual({ CFSubjects: [subject] })
expect(mockStore.getDefinitionById).toHaveBeenCalledWith(tenantId, caseVersion, 'CFSubjects', subjectId)
})

it('should include children determined by hierarchyCode, sorted', async () => {
const subject = { identifier: subjectId, title: 'Parent', hierarchyCode: '1.01' }
const childB = { identifier: 'child-b', title: 'Child B', hierarchyCode: '1.01.02' }
const childA = { identifier: 'child-a', title: 'Child A', hierarchyCode: '1.01.01' }
const unrelated = { identifier: 'other', title: 'Unrelated', hierarchyCode: '1.02' }

mockStore.getDefinitionById.mockReturnValue({ docSourcedId: 'doc-123', value: subject } as any)
mockStore.getTenantDefinitions.mockReturnValue({
CFSubjects: [subject, childB, childA, unrelated]
} as any)

const result = await getCFSubject.execute({ tenantId, caseVersion, sourcedId: subjectId })

expect(result).toEqual({ CFSubjects: [subject, childA, childB] })
})
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ describe('CFConceptsControllerV1p1', () => {
})

describe('getById', () => {
it('should return CFConcept when found', async () => {
it('should return CFConceptSet when found', async () => {
const result = {
identifier: 'concept-123',
uri: '/ims/case/v1p1/CFConcepts/concept-123',
title: 'Test Concept',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
CFConcepts: [{
identifier: 'concept-123',
uri: '/ims/case/v1p1/CFConcepts/concept-123',
title: 'Test Concept',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
}]
}

mockGetCFConcept.execute.mockResolvedValue(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ describe('CFItemTypesControllerV1p1', () => {
})

describe('getById', () => {
it('should return CFItemType when found', async () => {
it('should return CFItemTypeSet when found', async () => {
const result = {
identifier: 'itemtype-123',
uri: '/ims/case/v1p1/CFItemTypes/itemtype-123',
title: 'Test Item Type',
description: 'Test Description',
hierarchyCode: '01',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
CFItemTypes: [{
identifier: 'itemtype-123',
uri: '/ims/case/v1p1/CFItemTypes/itemtype-123',
title: 'Test Item Type',
description: 'Test Description',
hierarchyCode: '01',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
}]
}

mockGetCFItemType.execute.mockResolvedValue(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ describe('CFSubjectsControllerV1p1', () => {
})

describe('getById', () => {
it('should return CFSubject when found', async () => {
it('should return CFSubjectSet when found', async () => {
const result = {
identifier: 'subject-123',
uri: '/ims/case/v1p1/CFSubjects/subject-123',
title: 'Mathematics',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
CFSubjects: [{
identifier: 'subject-123',
uri: '/ims/case/v1p1/CFSubjects/subject-123',
title: 'Mathematics',
lastChangeDateTime: '2024-01-01T00:00:00.000Z'
}]
}

mockGetCFSubject.execute.mockResolvedValue(result)
Expand Down
Loading