diff --git a/src/app/child-dev-project/children/children-components.ts b/src/app/child-dev-project/children/children-components.ts
index bf7e52a181..569caea244 100644
--- a/src/app/child-dev-project/children/children-components.ts
+++ b/src/app/child-dev-project/children/children-components.ts
@@ -45,11 +45,11 @@ export const childrenComponents: ComponentTuple[] = [
).then((c) => c.ChildrenBmiDashboardComponent),
],
[
- "EducationalMaterial",
+ "RelatedEntitiesWithSummary",
() =>
import(
- "./educational-material/educational-material-component/educational-material.component"
- ).then((c) => c.EducationalMaterialComponent),
+ "../../core/entity-details/related-entities-with-summary/related-entities-with-summary.component"
+ ).then((c) => c.RelatedEntitiesWithSummaryComponent),
],
[
"BmiBlock",
diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html
deleted file mode 100644
index abfd833c5c..0000000000
--- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
- Total: {{ summary }}
-
-
- Average: {{ avgSummary }}
-
-
diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts
deleted file mode 100644
index 5a065632c3..0000000000
--- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { Component, Input, OnInit } from "@angular/core";
-import { NgFor, NgIf } from "@angular/common";
-import { EducationalMaterial } from "../model/educational-material";
-import { Child } from "../../model/child";
-import { FormFieldConfig } from "../../../../core/common-components/entity-form/entity-form/FormConfig";
-import { DynamicComponent } from "../../../../core/config/dynamic-components/dynamic-component.decorator";
-import { EntityMapperService } from "../../../../core/entity/entity-mapper/entity-mapper.service";
-import { applyUpdate } from "../../../../core/entity/model/entity-update";
-import { filter } from "rxjs/operators";
-import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
-import { EntitySubrecordComponent } from "../../../../core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component";
-
-/**
- * Displays educational materials of a child, such as a pencil, rulers, e.t.c
- * as well as a summary
- */
-@DynamicComponent("EducationalMaterial")
-@UntilDestroy()
-@Component({
- selector: "app-educational-material",
- templateUrl: "./educational-material.component.html",
- imports: [
- EntitySubrecordComponent,
- NgIf,
- NgFor
- ],
- standalone: true,
-})
-export class EducationalMaterialComponent implements OnInit {
- @Input() entity: Child;
- @Input() summaries: { total?: boolean; average?: boolean } = { total: true };
- records: EducationalMaterial[] = [];
- summary = "";
- avgSummary = "";
-
- @Input() config: { columns: FormFieldConfig[] } = {
- columns: [
- { id: "date", visibleFrom: "xs" },
- { id: "materialType", visibleFrom: "xs" },
- { id: "materialAmount", visibleFrom: "md" },
- { id: "description", visibleFrom: "md" },
- ],
- };
-
- constructor(private entityMapper: EntityMapperService) {
- this.entityMapper
- .receiveUpdates(EducationalMaterial)
- .pipe(
- untilDestroyed(this),
- filter(
- ({ entity, type }) =>
- type === "remove" || entity.child === this.entity.getId(),
- ),
- )
- .subscribe((update) => {
- this.records = applyUpdate(this.records, update);
- this.updateSummary();
- });
- }
-
- ngOnInit() {
- return this.loadData();
- }
-
- /**
- * Loads the data for a given child and updates the summary
- * @param id The id of the child to load the data for
- */
- private async loadData() {
- const allMaterials = await this.entityMapper.loadType(EducationalMaterial);
- this.records = allMaterials.filter(
- (mat) => mat.child === this.entity.getId(),
- );
- this.updateSummary();
- }
-
- newRecordFactory = () => {
- const newAtt = new EducationalMaterial(Date.now().toString());
-
- // use last entered date as default, otherwise today's date
- newAtt.date = this.records.length > 0 ? this.records[0].date : new Date();
- newAtt.child = this.entity.getId();
-
- return newAtt;
- };
-
- /**
- * update the summary or generate a new one.
- * The summary contains no duplicates and is in a
- * human-readable format
- */
- updateSummary() {
- const summary = new Map();
- const average = new Map();
-
- this.records.forEach((m) => {
- const { materialType, materialAmount } = m;
- const label = materialType?.label;
-
- if (label) {
- summary.set(label, (summary.get(label) || { count: 0, sum: 0 }));
- summary.get(label)!.count++;
- summary.get(label)!.sum += materialAmount;
- }
- });
-
- if(this.summaries.total) {
- const summaryArray = Array.from(summary.entries(), ([label, { sum }]) => `${label}: ${sum}`);
- this.summary = summaryArray.join(", ");
- }
-
- if(this.summaries.average) {
- const avgSummaryArray = Array.from(summary.entries(), ([label, { count, sum }]) => {
- const avg = parseFloat((sum / count).toFixed(2));
- average.set(label, avg);
- return `${label}: ${avg}`;
- });
- this.avgSummary = avgSummaryArray.join(", ");
- }
- }
-}
diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts
index 333e83ca6f..0c160bf969 100644
--- a/src/app/core/config/config-fix.ts
+++ b/src/app/core/config/config-fix.ts
@@ -706,14 +706,24 @@ export const defaultJsonConfig = {
"components": [
{
"title": "",
- "component": "EducationalMaterial",
+ "component": "RelatedEntitiesWithSummary",
"config": {
- "summaries": {
- total: true,
- average: true,
+ "entityType": EducationalMaterial.ENTITY_TYPE,
+ "property": "child",
+ "columns": [
+ { "id": "date", "visibleFrom": "xs" },
+ { "id": "materialType", "visibleFrom": "xs" },
+ { "id": "materialAmount", "visibleFrom": "md" },
+ { "id": "description", "visibleFrom": "md" },
+ ],
+ "summaries": {
+ "countProperty": "materialAmount",
+ "groupBy": "materialType",
+ "total": true,
+ "average": false
}
}
- }
+ }
]
},
{
diff --git a/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.html b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.html
new file mode 100644
index 0000000000..c59e53e42c
--- /dev/null
+++ b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Total: {{ summarySum }}
+
+
+ Average: {{ summaryAvg }}
+
+
diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.spec.ts
similarity index 50%
rename from src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts
rename to src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.spec.ts
index 9068e33c8e..5c17e54951 100644
--- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts
+++ b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.spec.ts
@@ -1,17 +1,23 @@
-import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
-
-import { EducationalMaterialComponent } from "./educational-material.component";
-import { Child } from "../../model/child";
-import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
-import { EducationalMaterial } from "../model/educational-material";
-import { ConfigurableEnumValue } from "../../../../core/basic-datatypes/configurable-enum/configurable-enum.interface";
-import { EntityMapperService } from "../../../../core/entity/entity-mapper/entity-mapper.service";
+import {
+ ComponentFixture,
+ fakeAsync,
+ TestBed,
+ tick,
+ waitForAsync,
+} from "@angular/core/testing";
+
+import { RelatedEntitiesWithSummaryComponent } from "./related-entities-with-summary.component";
+import { Child } from "../../../child-dev-project/children/model/child";
+import { MockedTestingModule } from "../../../utils/mocked-testing.module";
+import { EducationalMaterial } from "../../../child-dev-project/children/educational-material/model/educational-material";
+import { ConfigurableEnumValue } from "../../basic-datatypes/configurable-enum/configurable-enum.interface";
+import { EntityMapperService } from "../../entity/entity-mapper/entity-mapper.service";
import { Subject } from "rxjs";
-import { UpdatedEntity } from "../../../../core/entity/model/entity-update";
+import { UpdatedEntity } from "../../entity/model/entity-update";
-describe("EducationalMaterialComponent", () => {
- let component: EducationalMaterialComponent;
- let fixture: ComponentFixture;
+describe("RelatedEntitiesWithSummaryComponent", () => {
+ let component: RelatedEntitiesWithSummaryComponent;
+ let fixture: ComponentFixture;
const updates = new Subject>();
const child = new Child("22");
const PENCIL: ConfigurableEnumValue = {
@@ -25,17 +31,29 @@ describe("EducationalMaterialComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [EducationalMaterialComponent, MockedTestingModule.withState()],
+ imports: [
+ RelatedEntitiesWithSummaryComponent,
+ MockedTestingModule.withState(),
+ ],
}).compileComponents();
const entityMapper = TestBed.inject(EntityMapperService);
spyOn(entityMapper, "receiveUpdates").and.returnValue(updates);
}));
beforeEach(() => {
- fixture = TestBed.createComponent(EducationalMaterialComponent);
+ fixture = TestBed.createComponent(RelatedEntitiesWithSummaryComponent);
component = fixture.componentInstance;
component.entity = child;
- component.summaries = {total: true, average: true};
+ component.entityType = EducationalMaterial.ENTITY_TYPE;
+ component.property = "child";
+
+ component.summaries = {
+ countProperty: "materialAmount",
+ groupBy: "materialType",
+ total: true,
+ average: true,
+ };
+
fixture.detectChanges();
});
@@ -44,32 +62,47 @@ describe("EducationalMaterialComponent", () => {
});
it("produces an empty summary when there are no records", () => {
- component.records = [];
+ component.data = [];
component.updateSummary();
- expect(component.summary).toHaveSize(0);
- expect(component.avgSummary).toHaveSize(0);
+ expect(component.summarySum).toHaveSize(0);
+ expect(component.summaryAvg).toHaveSize(0);
});
function setRecordsAndGenerateSummary(
...records: Partial[]
) {
- component.records = records.map(EducationalMaterial.create);
+ component.data = records.map(EducationalMaterial.create);
component.updateSummary();
}
it("produces a singleton summary when there is a single record", () => {
setRecordsAndGenerateSummary({ materialType: PENCIL, materialAmount: 1 });
- expect(component.summary).toEqual(`${PENCIL.label}: 1`);
- expect(component.avgSummary).toEqual(`${PENCIL.label}: 1`);
+ expect(component.summarySum).toEqual(`${PENCIL.label}: 1`);
+ expect(component.summaryAvg).toEqual(`${PENCIL.label}: 1`);
});
it("produces a summary of all records when they are all different", () => {
setRecordsAndGenerateSummary(
{ materialType: PENCIL, materialAmount: 2 },
{ materialType: RULER, materialAmount: 1 },
+ { materialAmount: 1 },
+ );
+ expect(component.summarySum).toEqual(
+ `${PENCIL.label}: 2, ${RULER.label}: 1, undefined: 1`,
);
- expect(component.summary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`);
- expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`);
+ expect(component.summaryAvg).toEqual(
+ `${PENCIL.label}: 2, ${RULER.label}: 1, undefined: 1`,
+ );
+ });
+
+ it("produces a singly summary without grouping, if `groupBy` is not given (or the group value undefined)", () => {
+ component.data = [{ amount: 1 }, { amount: 5 }] as any[];
+ delete component.summaries.groupBy;
+ component.summaries.countProperty = "amount";
+ component.updateSummary();
+
+ expect(component.summarySum).toEqual(`6`);
+ expect(component.summaryAvg).toEqual(`3`);
});
it("produces a summary of all records when there are duplicates", () => {
@@ -79,56 +112,70 @@ describe("EducationalMaterialComponent", () => {
{ materialType: PENCIL, materialAmount: 3 },
);
- expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`);
- expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`);
+ expect(component.summarySum).toEqual(
+ `${PENCIL.label}: 4, ${RULER.label}: 1`,
+ );
+ expect(component.summaryAvg).toEqual(
+ `${PENCIL.label}: 2, ${RULER.label}: 1`,
+ );
});
it("produces summary of all records when average is false and total is true", () => {
- component.summaries = { total: true, average: false }
+ component.summaries.total = true;
+ component.summaries.average = false;
setRecordsAndGenerateSummary(
{ materialType: PENCIL, materialAmount: 1 },
{ materialType: RULER, materialAmount: 1 },
{ materialType: PENCIL, materialAmount: 3 },
);
- expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`);
- expect(component.avgSummary).toEqual(``);
+ expect(component.summarySum).toEqual(
+ `${PENCIL.label}: 4, ${RULER.label}: 1`,
+ );
+ expect(component.summaryAvg).toEqual(``);
});
it("produces summary of all records when average is true and total is false", () => {
- component.summaries = { total: false, average: true };
+ component.summaries.total = false;
+ component.summaries.average = true;
setRecordsAndGenerateSummary(
{ materialType: PENCIL, materialAmount: 1 },
{ materialType: RULER, materialAmount: 1 },
{ materialType: PENCIL, materialAmount: 3 },
);
- expect(component.summary).toEqual(``);
- expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`);
+ expect(component.summarySum).toEqual(``);
+ expect(component.summaryAvg).toEqual(
+ `${PENCIL.label}: 2, ${RULER.label}: 1`,
+ );
});
it("does not produces summary of all records when both average and total are false", () => {
- component.summaries = { total: false, average: false };
+ component.summaries.total = false;
+ component.summaries.average = false;
setRecordsAndGenerateSummary(
{ materialType: PENCIL, materialAmount: 1 },
{ materialType: RULER, materialAmount: 1 },
{ materialType: PENCIL, materialAmount: 3 },
);
-
- expect(component.summary).toEqual(``);
- expect(component.avgSummary).toEqual(``);
+
+ expect(component.summarySum).toEqual(``);
+ expect(component.summaryAvg).toEqual(``);
});
it("produces summary of all records when both average and total are true", () => {
- component.summaries = { total: true, average: true };
setRecordsAndGenerateSummary(
{ materialType: PENCIL, materialAmount: 1 },
{ materialType: RULER, materialAmount: 1 },
{ materialType: PENCIL, materialAmount: 3 },
);
- expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`);
- expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`);
+ expect(component.summarySum).toEqual(
+ `${PENCIL.label}: 4, ${RULER.label}: 1`,
+ );
+ expect(component.summaryAvg).toEqual(
+ `${PENCIL.label}: 2, ${RULER.label}: 1`,
+ );
});
it("loads all education data associated with a child and updates the summary", async () => {
@@ -141,38 +188,41 @@ describe("EducationalMaterialComponent", () => {
);
component.entity = new Child("22");
await component.ngOnInit();
- expect(component.summary).toEqual(`${PENCIL.label}: 1, ${RULER.label}: 2`);
- expect(component.records).toEqual(educationalData);
+ expect(component.summarySum).toEqual(
+ `${PENCIL.label}: 1, ${RULER.label}: 2`,
+ );
+ expect(component.data).toEqual(educationalData);
});
- it("associates a new record with the current child", () => {
- const newRecord = component.newRecordFactory();
- expect(newRecord.child).toBe(child.getId());
- });
+ it("should update the summary when entity updates are received", fakeAsync(() => {
+ component.ngOnInit();
+ tick();
- it("should update the summary when entity updates are received", async () => {
const update1 = EducationalMaterial.create({
child: child.getId(),
materialType: PENCIL,
materialAmount: 1,
});
updates.next({ entity: update1, type: "new" });
+ tick();
- expect(component.records).toEqual([update1]);
- expect(component.summary).toBe(`${PENCIL.label}: 1`);
+ expect(component.data).toEqual([update1]);
+ expect(component.summarySum).toBe(`${PENCIL.label}: 1`);
const update2 = update1.copy() as EducationalMaterial;
update2.materialAmount = 2;
updates.next({ entity: update2, type: "update" });
+ tick();
- expect(component.records).toEqual([update2]);
- expect(component.summary).toBe(`${PENCIL.label}: 2`);
+ expect(component.data).toEqual([update2]);
+ expect(component.summarySum).toBe(`${PENCIL.label}: 2`);
const unrelatedUpdate = update1.copy() as EducationalMaterial;
unrelatedUpdate.child = "differentChild";
updates.next({ entity: unrelatedUpdate, type: "new" });
+ tick();
// No change
- expect(component.records).toEqual([update2]);
- expect(component.summary).toBe(`${PENCIL.label}: 2`);
- });
+ expect(component.data).toEqual([update2]);
+ expect(component.summarySum).toBe(`${PENCIL.label}: 2`);
+ }));
});
diff --git a/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.ts b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.ts
new file mode 100644
index 0000000000..2055435762
--- /dev/null
+++ b/src/app/core/entity-details/related-entities-with-summary/related-entities-with-summary.component.ts
@@ -0,0 +1,113 @@
+import { Component, Input, OnInit } from "@angular/core";
+import { NgFor, NgIf } from "@angular/common";
+import { DynamicComponent } from "../../config/dynamic-components/dynamic-component.decorator";
+import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
+import { EntitySubrecordComponent } from "../../common-components/entity-subrecord/entity-subrecord/entity-subrecord.component";
+import { RelatedEntitiesComponent } from "../related-entities/related-entities.component";
+import { Entity } from "../../entity/model/entity";
+import { filter } from "rxjs/operators";
+import { applyUpdate } from "../../entity/model/entity-update";
+
+/**
+ * Load and display a list of entity subrecords (entities related to the current entity details view)
+ * including a summary below the table.
+ */
+@DynamicComponent("RelatedEntitiesWithSummary")
+@UntilDestroy()
+@Component({
+ selector: "app-related-entities-with-summary",
+ templateUrl: "./related-entities-with-summary.component.html",
+ imports: [EntitySubrecordComponent, NgIf, NgFor],
+ standalone: true,
+})
+export class RelatedEntitiesWithSummaryComponent
+ extends RelatedEntitiesComponent
+ implements OnInit
+{
+ /**
+ * Configuration of what numbers should be summarized below the table.
+ */
+ @Input() summaries?: {
+ countProperty: string;
+ groupBy?: string;
+ total?: boolean;
+ average?: boolean;
+ };
+
+ summarySum = "";
+ summaryAvg = "";
+
+ async ngOnInit() {
+ await super.ngOnInit();
+ this.updateSummary();
+
+ this.entityMapper
+ .receiveUpdates(this.entityCtr)
+ .pipe(
+ untilDestroyed(this),
+ filter(
+ ({ entity, type }) =>
+ type === "remove" || entity[this.property] === this.entity.getId(),
+ ),
+ )
+ .subscribe((update) => {
+ this.data = applyUpdate(this.data, update);
+ this.updateSummary();
+ });
+ }
+
+ /**
+ * update the summary or generate a new one.
+ * The summary contains no duplicates and is in a
+ * human-readable format
+ */
+ updateSummary() {
+ if (!this.summaries) {
+ this.summarySum = "";
+ this.summaryAvg = "";
+ return;
+ }
+
+ const summary = new Map();
+ const average = new Map();
+
+ this.data.forEach((m) => {
+ const amount = m[this.summaries.countProperty];
+ let groupLabel;
+ if (this.summaries.groupBy) {
+ groupLabel =
+ m[this.summaries.groupBy]?.label ?? m[this.summaries.groupBy];
+ }
+
+ summary.set(groupLabel, summary.get(groupLabel) || { count: 0, sum: 0 });
+ summary.get(groupLabel).count++;
+ summary.get(groupLabel).sum += amount;
+ });
+
+ if (this.summaries.total) {
+ const summarySumArray = Array.from(
+ summary.entries(),
+ ([label, { sum }]) => `${label}: ${sum}`,
+ );
+ this.summarySum = summarySumArray.join(", ");
+ }
+
+ if (this.summaries.average) {
+ const summaryAvgArray = Array.from(
+ summary.entries(),
+ ([label, { count, sum }]) => {
+ const avg = parseFloat((sum / count).toFixed(2));
+ average.set(label, avg);
+ return `${label}: ${avg}`;
+ },
+ );
+ this.summaryAvg = summaryAvgArray.join(", ");
+ }
+
+ if (summary.size === 1 && summary.has(undefined)) {
+ // display only single summary without group label (this also applies if no groupBy is given)
+ this.summarySum = this.summarySum.replace("undefined: ", "");
+ this.summaryAvg = this.summaryAvg.replace("undefined: ", "");
+ }
+ }
+}
diff --git a/src/app/core/entity-details/related-entities/related-entities.component.spec.ts b/src/app/core/entity-details/related-entities/related-entities.component.spec.ts
index 44c9b0eebd..49a1a1f2f5 100644
--- a/src/app/core/entity-details/related-entities/related-entities.component.spec.ts
+++ b/src/app/core/entity-details/related-entities/related-entities.component.spec.ts
@@ -30,7 +30,7 @@ describe("RelatedEntitiesComponent", () => {
expect(component).toBeTruthy();
});
- it("should load the entities which are linked with the passed one", async () => {
+ it("should load only the entities which are linked with the passed one", async () => {
const c1 = new Child();
const c2 = new Child();
const r1 = new ChildSchoolRelation();
@@ -52,7 +52,7 @@ describe("RelatedEntitiesComponent", () => {
await component.ngOnInit();
expect(component.columns).toBe(columns);
- expect(component.data).toEqual([r1, r2, r3]);
+ expect(component.data).toEqual([r1, r2]);
expect(component.filter).toEqual({ ...filter, childId: c1.getId() });
});
diff --git a/src/app/core/entity-details/related-entities/related-entities.component.ts b/src/app/core/entity-details/related-entities/related-entities.component.ts
index a6c9b1507a..7e5a4eb93e 100644
--- a/src/app/core/entity-details/related-entities/related-entities.component.ts
+++ b/src/app/core/entity-details/related-entities/related-entities.component.ts
@@ -50,7 +50,7 @@ export class RelatedEntitiesComponent implements OnInit {
protected entityCtr: EntityConstructor;
constructor(
- private entityMapper: EntityMapperService,
+ protected entityMapper: EntityMapperService,
private entities: EntityRegistry,
) {}
@@ -64,7 +64,12 @@ export class RelatedEntitiesComponent implements OnInit {
this.entityCtr = this.entities.get(this.entityType) as EntityConstructor;
this.isArray = isArrayProperty(this.entityCtr, this.property);
- this.data = await this.entityMapper.loadType(this.entityType);
+ this.data = (await this.entityMapper.loadType(this.entityType)).filter(
+ (e) =>
+ this.isArray
+ ? e[this.property].includes(this.entity.getId())
+ : e[this.property] === this.entity.getId(),
+ );
this.filter = {
...this.filter,
[this.property]: this.isArray
diff --git a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
index 85bcc2e268..e5ad40422f 100644
--- a/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
+++ b/src/app/core/entity-details/related-time-period-entities/related-time-period-entities.component.spec.ts
@@ -124,13 +124,14 @@ describe("RelatedTimePeriodEntitiesComponent", () => {
});
it("should create a new entity with the start date inferred from previous relations", async () => {
+ const child = new Child();
const existingRelation = new ChildSchoolRelation();
existingRelation.start = moment().subtract(1, "year").toDate();
existingRelation.end = moment().subtract(1, "week").toDate();
+ existingRelation.childId = child.getId(false);
const loadType = spyOn(entityMapper, "loadType");
loadType.and.resolveTo([existingRelation]);
- const child = new Child();
component.entity = child;
await component.ngOnInit();