diff --git a/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml b/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml
index 94623f25a..d4ccd6e05 100644
--- a/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml
+++ b/.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml
@@ -17,7 +17,7 @@ onFlowComplete:
file: "scripts/teardown.js"
---
-# Invite new user:
+# Invite Teacher as new user:
- runFlow: "subflows/school_admin_login_flow.yaml"
- assertVisible:
id: "app_title"
@@ -96,6 +96,10 @@ onFlowComplete:
- tapOn: "Password*"
- inputText: "test123"
- tapOn: "Sign-up"
+- runFlow:
+ when:
+ visible: "Save password for Respect?"
+ file: "subflows/save_password_prompt_cancel.yaml"
- assertVisible:
id: "app_title"
text: "Apps"
@@ -118,7 +122,7 @@ onFlowComplete:
- copyTextFrom:
id: "invite_code"
-# C) Student sign-up via invite code to the class
+# Student sign-up via invite code to the class
- clearState: world.respect.app
- launchApp:
arguments:
@@ -173,23 +177,14 @@ onFlowComplete:
text: "Waiting for approval"
- assertVisible: "Please wait"
-# H) Teacher approve student's request to join the class
+# Teacher approve student's request to join the class
- clearState: world.respect.app
-- launchApp:
- arguments:
- respect_directory: ${output.SCHOOL_URL}
-- tapOn: "Get Started"
- runFlow:
- file: "subflows/get_started_select_school_by_name.yaml"
+ file: "subflows/school_user_login_flow.yaml"
env:
SCHOOL_NAME: ${SCHOOL_NAME}
-- tapOn:
- id: "username"
-- inputText: "teacherauser"
-- tapOn:
- id : "password"
-- inputText: "test123"
-- tapOn: "Login"
+ USER_NAME: "teacherauser"
+ USER_PASSWORD: "test123"
- assertVisible: "Apps"
- tapOn: "Classes"
- assertVisible:
@@ -199,15 +194,25 @@ onFlowComplete:
- assertVisible: "Pending requests.*"
- assertVisible: "Student User.*"
- tapOn: "Accept Invite"
+- assertNotVisible: "Pending requests.*"
-# E) Teacher share invite link for parent device based signup
-- tapOn: "Add student"
+# Teacher send family member invite to Parent User
+- tapOn: "Student User"
+- assertVisible:
+ id: "app_title"
+ text: "Student User"
+- tapOn:
+ id: "floating_action_button"
+- assertVisible:
+ id: "app_title"
+ text: "Edit person"
+- tapOn: "Family member"
- tapOn: "Invite person"
-- tapOn: "Invite via parents"
+- assertVisible: "Student User / Family member"
- tapOn: "Approval required" # turn the switch off
- assertVisible: "Approval not required until:.*"
- copyTextFrom:
- id: "invite_url"
+ id: "invite_url"
# Parent sign-up to the app using invite link
- runFlow:
@@ -220,10 +225,10 @@ onFlowComplete:
text: "Invitation"
- assertVisible: "Role"
- assertVisible: "Parent"
+- assertVisible: "Child"
+- assertVisible: "Student User"
- assertVisible: "School name"
- assertVisible: ${output.SCHOOL_NAME}
-- assertVisible: "Class name"
-- assertVisible: "New Class"
- assertVisible: "School server URL"
- assertVisible: ${output.SCHOOL_URL}
- tapOn: "Next"
@@ -254,13 +259,13 @@ onFlowComplete:
- tapOn: "Password*"
- inputText: "test123"
- tapOn: "Sign-up"
-- tapOn: "Child's name*"
-- inputText: "Student User2"
-- tapOn: "Gender*"
-- tapOn: "Female"
-- tapOn: "Child's date of birth*"
-- runScript:
- file: "scripts/setDate.js"
-- inputText: ${output.pastYearDateC}
-- tapOn: "Done"
-# 1/Feb/2026: MD: Maestro AGAIN does not actually deliver the tap. Thanks.
+- runFlow:
+ when:
+ visible: "Save password for Respect?"
+ file: "subflows/save_password_prompt_cancel.yaml"
+- assertVisible:
+ id: "app_title"
+ text: "Apps"
+- tapOn: "People"
+- tapOn: "Student User"
+- assertVisible: "Parent User"
\ No newline at end of file
diff --git a/.maestro/flows/subflows/school_user_login_flow.yaml b/.maestro/flows/subflows/school_user_login_flow.yaml
new file mode 100644
index 000000000..c7c2cda88
--- /dev/null
+++ b/.maestro/flows/subflows/school_user_login_flow.yaml
@@ -0,0 +1,26 @@
+appId: world.respect.app
+
+---
+- launchApp:
+ arguments:
+ respect_directory: ${output.SCHOOL_URL}
+
+- tapOn: "Get Started"
+
+- runFlow:
+ file: "get_started_select_school_by_name.yaml"
+ env:
+ SCHOOL_NAME: ${SCHOOL_NAME}
+
+- tapOn:
+ id: "username"
+- inputText: ${USER_NAME}
+- tapOn:
+ id : "password"
+- inputText: ${USER_PASSWORD}
+- tapOn: "Login"
+- runFlow:
+ when:
+ visible: "Save password for Respect?"
+ file: "save_password_prompt_cancel.yaml"
+
diff --git a/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/manageuser/acceptinvite/AcceptInviteScreen.kt b/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/manageuser/acceptinvite/AcceptInviteScreen.kt
index 1c47c2a89..e67c4a70a 100644
--- a/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/manageuser/acceptinvite/AcceptInviteScreen.kt
+++ b/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/manageuser/acceptinvite/AcceptInviteScreen.kt
@@ -25,6 +25,7 @@ import world.respect.app.components.uiTextStringResource
import world.respect.datalayer.school.model.ClassInvite
import world.respect.datalayer.school.model.NewUserInvite
import world.respect.shared.generated.resources.Res
+import world.respect.shared.generated.resources.child
import world.respect.shared.generated.resources.class_name
import world.respect.shared.generated.resources.loading
import world.respect.shared.generated.resources.next
@@ -122,7 +123,16 @@ fun AcceptInviteScreen(
}
else -> {
- //Do nothing else
+ RespectDetailField(
+ modifier = Modifier.defaultItemPadding(),
+ label = { Text(stringResource(Res.string.role)) },
+ value = { Text(stringResource(invite.roleLabel)) }
+ )
+ RespectDetailField(
+ modifier = Modifier.defaultItemPadding(),
+ label = { Text(stringResource(Res.string.child)) },
+ value = { Text(uiState.inviteInfo?.childName?:"") }
+ )
}
}
diff --git a/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/person/inviteperson/InvitePersonScreen.kt b/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/person/inviteperson/InvitePersonScreen.kt
index 1abf71dfd..2791d1128 100644
--- a/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/person/inviteperson/InvitePersonScreen.kt
+++ b/respect-app-compose/src/commonMain/kotlin/world/respect/app/view/person/inviteperson/InvitePersonScreen.kt
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
@@ -50,6 +51,7 @@ import world.respect.shared.generated.resources.Res
import world.respect.shared.generated.resources.approval_not_required_until
import world.respect.shared.generated.resources.approval_required
import world.respect.shared.generated.resources.copy_link
+import world.respect.shared.generated.resources.family_member
import world.respect.shared.generated.resources.invite_code_label
import world.respect.shared.generated.resources.invite_students_directly
import world.respect.shared.generated.resources.invite_via_email
@@ -135,6 +137,15 @@ fun InvitePersonScreen(
uiState.inviteUrl?.also { link ->
val linkStr = link.toString()
+ uiState.childName?.let {
+ Text(
+ text = "$it / "+stringResource(Res.string.family_member),
+ textAlign = TextAlign.Center,
+ modifier = Modifier.align(Alignment.CenterHorizontally)
+ .padding(vertical = 8.dp),
+ )
+ }
+
Image(
painter = rememberQrCodePainter(linkStr),
contentDescription = stringResource(Res.string.qr_code),
diff --git a/respect-datalayer-db/src/commonMain/kotlin/world/respect/datalayer/db/school/InviteDataSourceDb.kt b/respect-datalayer-db/src/commonMain/kotlin/world/respect/datalayer/db/school/InviteDataSourceDb.kt
index 1cd7ce281..0f8436b40 100644
--- a/respect-datalayer-db/src/commonMain/kotlin/world/respect/datalayer/db/school/InviteDataSourceDb.kt
+++ b/respect-datalayer-db/src/commonMain/kotlin/world/respect/datalayer/db/school/InviteDataSourceDb.kt
@@ -16,6 +16,7 @@ import world.respect.datalayer.db.school.adapters.toModel
import world.respect.datalayer.exceptions.ForbiddenException
import world.respect.datalayer.school.InviteDataSource
import world.respect.datalayer.school.InviteDataSourceLocal
+import world.respect.datalayer.school.PersonDataSourceLocal
import world.respect.datalayer.school.domain.CheckPersonPermissionUseCase
import world.respect.datalayer.school.model.ClassInvite
import world.respect.datalayer.school.model.EnrollmentRoleEnum
@@ -114,7 +115,23 @@ class InviteDataSourceDb(
else -> {
//Family member invite
- val knownPersonUid = (inviteToStore as? FamilyMemberInvite)?.personUid ?: "0"
+ val knownPersonUid =
+ (inviteToStore as? FamilyMemberInvite)?.personUid ?: "0"
+ val authGuid = authenticatedUser.guid
+
+ if (authGuid != knownPersonUid) {
+ val hasWrite = checkPersonPermissionUseCase(
+ otherPersonUid = knownPersonUid,
+ otherPersonKnownRole = null,
+ permissionsRequiredByRole = CheckPersonPermissionUseCase.PermissionsRequiredByRole.WRITE_PERMISSIONS
+ )
+
+ if (!hasWrite) {
+ throw Exception(
+ "user does not have permission to create family invite for $knownPersonUid"
+ )
+ }
+ }
}
}
}
diff --git a/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/respect/model/invite/RespectInviteInfo.kt b/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/respect/model/invite/RespectInviteInfo.kt
index 33e911dcd..08048ce35 100644
--- a/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/respect/model/invite/RespectInviteInfo.kt
+++ b/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/respect/model/invite/RespectInviteInfo.kt
@@ -13,6 +13,7 @@ import world.respect.datalayer.school.model.Invite2
class RespectInviteInfo(
val classGuid: String?=null,
val className: String?=null,
+ val childName: String?=null,
val userInviteType: UserInviteType?=null,
val invite: Invite2? = null
) {
diff --git a/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/school/model/Invite.kt b/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/school/model/Invite.kt
index 5df9eab25..50542a5e3 100644
--- a/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/school/model/Invite.kt
+++ b/respect-datalayer/src/commonMain/kotlin/world/respect/datalayer/school/model/Invite.kt
@@ -120,10 +120,15 @@ data class ClassInvite(
data class FamilyMemberInvite(
override val uid: String,
override val code: String,
- override val approvalRequiredAfter: InstantAsISO8601,
+ override val approvalRequiredAfter: InstantAsISO8601= Instant.fromEpochMilliseconds(0),
override val lastModified: InstantAsISO8601 = Clock.System.now(),
override val stored: InstantAsISO8601 = Clock.System.now(),
override val status: StatusEnum = StatusEnum.ACTIVE,
val personUid: String,
-): Invite2
+): Invite2 {
+ companion object {
+ fun uidFor(personUid: String?): String = "$TYPE_FAMILY_MEMBER:$personUid"
+ }
+}
+
diff --git a/respect-lib-shared/src/commonMain/composeResources/values/strings.xml b/respect-lib-shared/src/commonMain/composeResources/values/strings.xml
index 52b9cb015..768f10c64 100644
--- a/respect-lib-shared/src/commonMain/composeResources/values/strings.xml
+++ b/respect-lib-shared/src/commonMain/composeResources/values/strings.xml
@@ -498,6 +498,7 @@
System administrator
Site administrator
Role
+ Child
Date
Time
diff --git a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt
index 17746057e..fbdb61de5 100644
--- a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt
+++ b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt
@@ -837,6 +837,11 @@ data class InvitePerson(
val inviteUid: String,
): InvitePersonOptions
+ @Serializable
+ @SerialName("family")
+ data class FamilyInviteOptions(
+ val personUid: String
+ ) : InvitePersonOptions
@Transient
val invitePersonOptions: InvitePersonOptions = Json.decodeFromString(
diff --git a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/edit/PersonEditViewModel.kt b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/edit/PersonEditViewModel.kt
index 5ee68fb28..5c45e7129 100644
--- a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/edit/PersonEditViewModel.kt
+++ b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/edit/PersonEditViewModel.kt
@@ -56,6 +56,10 @@ import world.respect.shared.viewmodel.app.appstate.ActionBarButtonUiState
import kotlin.collections.first
import kotlin.getValue
import kotlin.time.Clock
+import world.respect.datalayer.school.model.FamilyMemberInvite
+import world.respect.datalayer.school.model.Invite2
+import world.respect.datalayer.school.model.StatusEnum
+import kotlin.time.Duration.Companion.minutes
data class PersonEditUiState(
val uid: String = "",
@@ -298,12 +302,12 @@ class PersonEditViewModel(
NavCommand.Navigate(
PersonList.create(
filterByRole = filterByRole,
- personGuid = route.guid,
+ personGuid = FamilyMemberInvite.uidFor(route.guid),
resultDest = RouteResultDest(
resultPopUpTo = route,
resultKey = PERSON_SELECT_RESULT
),
- hideInvite = true,
+ hideInvite = false,
)
)
)
@@ -392,6 +396,19 @@ class PersonEditViewModel(
familyMembersAdded + familyMembersRemoved + personToSave.copy(lastModified = modTime)
)
+ if (route.guid == null && personToSave.roles.any { it.roleEnum == PersonRoleEnum.STUDENT }) {
+ val invite = FamilyMemberInvite(
+ uid = FamilyMemberInvite.uidFor(personToSave.guid),
+ code = Invite2.newRandomCode(),
+ approvalRequiredAfter = modTime + Invite2.APPROVAL_NOT_REQUIRED_INTERVAL_MINS.minutes,
+ lastModified = modTime,
+ stored = modTime,
+ status = StatusEnum.ACTIVE,
+ personUid = personToSave.guid
+ )
+ schoolDataSource.inviteDataSource.store(listOf(invite))
+ }
+
if(
!navResultReturner.sendResultIfResultExpected(
route = route,
diff --git a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/inviteperson/InvitePersonViewModel.kt b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/inviteperson/InvitePersonViewModel.kt
index e386d7d54..4f7e62f2a 100644
--- a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/inviteperson/InvitePersonViewModel.kt
+++ b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/inviteperson/InvitePersonViewModel.kt
@@ -22,6 +22,7 @@ import world.respect.datalayer.DataLoadState
import world.respect.datalayer.DataLoadingState
import world.respect.datalayer.NoDataLoadedState
import world.respect.datalayer.SchoolDataSource
+import world.respect.datalayer.db.school.ext.fullName
import world.respect.datalayer.ext.dataOrNull
import world.respect.datalayer.school.domain.GetWritableRolesListUseCase
import world.respect.datalayer.school.ext.copyInvite
@@ -30,6 +31,7 @@ import world.respect.datalayer.school.ext.newUserInviteUid
import world.respect.datalayer.school.model.ClassInvite
import world.respect.datalayer.school.model.ClassInviteModeEnum
import world.respect.datalayer.school.model.EnrollmentRoleEnum
+import world.respect.datalayer.school.model.FamilyMemberInvite
import world.respect.datalayer.school.model.Invite2
import world.respect.datalayer.school.model.NewUserInvite
import world.respect.datalayer.school.model.PersonRoleEnum
@@ -62,6 +64,7 @@ data class InvitePersonUiState(
val selectedRole: PersonRoleEnum? = null,
val className: String? = null,
val schoolName: String? = null,
+ val childName: String? = null,
val roleOptions: List = emptyList()
) {
val inviteCode: String?
@@ -132,6 +135,7 @@ class InvitePersonViewModel(
}
_inviteUid.value = (route.invitePersonOptions as? InvitePerson.ClassInviteOptions)?.inviteUid
+ ?: (route.invitePersonOptions as? InvitePerson.FamilyInviteOptions)?.personUid
?: selectedRole.newUserInviteUid
_inviteUid.collectLatest { inviteUid ->
@@ -140,6 +144,17 @@ class InvitePersonViewModel(
uid = inviteUid,
loadParams = DataLoadParams()
).collectLatest { invite ->
+ (invite.dataOrNull() as? FamilyMemberInvite)?.let { familyInvite ->
+ val childPerson= schoolDataSource.personDataSource.findByGuid(
+ loadParams = DataLoadParams(),
+ guid = familyInvite.personUid
+ ).dataOrNull()
+ _uiState.update { prev ->
+ prev.copy(
+ childName = childPerson?.fullName(),
+ )
+ }
+ }
_uiState.update { prev ->
prev.copy(
invite = invite,
diff --git a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/list/PersonListViewModel.kt b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/list/PersonListViewModel.kt
index 64ee9fced..92b5cf7fc 100644
--- a/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/list/PersonListViewModel.kt
+++ b/respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/person/list/PersonListViewModel.kt
@@ -38,6 +38,7 @@ import world.respect.shared.viewmodel.RespectViewModel
import world.respect.shared.viewmodel.app.appstate.AppBarSearchUiState
import world.respect.datalayer.school.domain.CheckPersonPermissionUseCase.PermissionsRequiredByRole
import world.respect.datalayer.school.model.Person
+import world.respect.datalayer.school.model.PersonRoleEnum
import world.respect.datalayer.school.model.PersonStatusEnum
import world.respect.shared.domain.account.invite.ApproveOrDeclineInviteRequestUseCase
import world.respect.shared.domain.permissions.CheckSchoolPermissionsUseCase
@@ -240,19 +241,29 @@ class PersonListViewModel(
}
fun onClickInvitePerson() {
+ val inviteOptions = when {
+ route.inviteUid != null -> {
+ InvitePerson.ClassInviteOptions(
+ inviteUid = route.inviteUid
+ )
+ }
+
+ route.filterByRole == PersonRoleEnum.PARENT && route.personGuidStr != null -> {
+ InvitePerson.FamilyInviteOptions(
+ personUid = route.personGuidStr
+ )
+ }
+
+ else -> {
+ InvitePerson.NewUserInviteOptions(
+ presetRole = route.filterByRole
+ )
+ }
+ }
+
_navCommandFlow.tryEmit(
NavCommand.Navigate(
- InvitePerson.create(
- invitePersonOptions = if(route.inviteUid != null) {
- InvitePerson.ClassInviteOptions(
- inviteUid = route.inviteUid
- )
- }else {
- InvitePerson.NewUserInviteOptions(
- presetRole = route.filterByRole
- )
- }
- )
+ InvitePerson.create(invitePersonOptions = inviteOptions)
)
)
}
diff --git a/respect-lib-shared/src/jvmMain/kotlin/world/respect/shared/domain/account/invite/RedeemInviteUseCaseDb.kt b/respect-lib-shared/src/jvmMain/kotlin/world/respect/shared/domain/account/invite/RedeemInviteUseCaseDb.kt
index b294e00e6..6e4832f9f 100644
--- a/respect-lib-shared/src/jvmMain/kotlin/world/respect/shared/domain/account/invite/RedeemInviteUseCaseDb.kt
+++ b/respect-lib-shared/src/jvmMain/kotlin/world/respect/shared/domain/account/invite/RedeemInviteUseCaseDb.kt
@@ -12,11 +12,13 @@ import world.respect.credentials.passkey.RespectQRBadgeCredential
import world.respect.credentials.passkey.RespectUserHandle
import world.respect.credentials.passkey.request.GetPasskeyProviderInfoUseCase
import world.respect.datalayer.AuthenticatedUserPrincipalId
+import world.respect.datalayer.DataLoadParams
import world.respect.datalayer.SchoolDataSourceLocal
import world.respect.datalayer.UidNumberMapper
import world.respect.datalayer.db.RespectSchoolDatabase
import world.respect.datalayer.db.school.adapters.toEntity
import world.respect.datalayer.db.school.adapters.toModel
+import world.respect.datalayer.ext.dataOrNull
import world.respect.datalayer.school.adapters.toPersonPasskey
import world.respect.datalayer.school.ext.accepterEnrollmentRole
import world.respect.datalayer.school.ext.accepterPersonRole
@@ -28,6 +30,8 @@ import world.respect.datalayer.school.model.NewUserInvite
import world.respect.datalayer.school.model.ClassInvite
import world.respect.datalayer.school.model.ClassInviteModeEnum
import world.respect.datalayer.school.model.Enrollment
+import world.respect.datalayer.school.model.FamilyMemberInvite
+import world.respect.datalayer.school.model.PersonRoleEnum
import world.respect.datalayer.school.model.PersonStatusEnum
import world.respect.datalayer.school.model.StatusEnum
import world.respect.libutil.ext.randomString
@@ -115,7 +119,42 @@ class RedeemInviteUseCaseDb(
)
)
}
+ val timeNow = Clock.System.now()
+ if (inviteFromDb is FamilyMemberInvite) {
+ val parentUid = inviteFromDb.personUid
+
+ val inviterPerson = schoolDataSourceVal.personDataSource.findByGuid(
+ loadParams = DataLoadParams(),
+ guid = parentUid
+ ).dataOrNull() ?: throw IllegalStateException("person not found: $parentUid")
+
+
+ val updatedInviter = inviterPerson.copy(
+ relatedPersonUids = inviterPerson.relatedPersonUids + accountPerson.guid,
+ lastModified = timeNow
+ )
+
+ val updatedAccountPerson = accountPerson.copy(
+ relatedPersonUids = accountPerson.relatedPersonUids + parentUid,
+ lastModified = timeNow
+ )
+ schoolDataSourceVal.personDataSource.updateLocal(listOf(updatedInviter, updatedAccountPerson))
+ }
+ if (inviteFromDb !is FamilyMemberInvite){
+ if ( accountPerson.roles.any { it.roleEnum == PersonRoleEnum.STUDENT }) {
+ val invite = FamilyMemberInvite(
+ uid = FamilyMemberInvite.uidFor(accountPerson.guid),
+ code = Invite2.newRandomCode(),
+ approvalRequiredAfter = timeNow,
+ lastModified = timeNow,
+ stored = timeNow,
+ status = StatusEnum.ACTIVE,
+ personUid = accountPerson.guid
+ )
+ schoolDataSourceVal.inviteDataSource.store(listOf(invite))
+ }
+ }
val credential = redeemRequest.account.credential
val authResponse = when (credential) {
diff --git a/respect-server/src/main/kotlin/world/respect/server/account/invite/GetInviteInfoUseCaseServer.kt b/respect-server/src/main/kotlin/world/respect/server/account/invite/GetInviteInfoUseCaseServer.kt
index 2135308db..893a9e36c 100644
--- a/respect-server/src/main/kotlin/world/respect/server/account/invite/GetInviteInfoUseCaseServer.kt
+++ b/respect-server/src/main/kotlin/world/respect/server/account/invite/GetInviteInfoUseCaseServer.kt
@@ -26,9 +26,24 @@ class GetInviteInfoUseCaseServer(
}else {
null
}
-
+ val childUid = invite.iForFamilyOfGuid
+ val childName = if(childUid != null) {
+ val child = schoolDb.getPersonEntityDao().findByGuidNum(uidNumberMapper(childUid))
+ buildString {
+ append(child?.person?.pGivenName)
+ append(" ")
+ child?.person?.pMiddleName?.also {
+ append(it)
+ append(" ")
+ }
+ append(child?.person?.pFamilyName)
+ }
+ }else {
+ null
+ }
return RespectInviteInfo(
className = className,
+ childName = childName,
invite = invite.toModel(),
)
}