Skip to content

Commit f1252a5

Browse files
committed
create new achievements for first student match
1 parent 8ad1771 commit f1252a5

File tree

11 files changed

+517
-264
lines changed

11 files changed

+517
-264
lines changed

common/achievement/derive.ts

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ const GhostAchievements: { [key: string]: achievement_template } = {
2626
group: PupilNewMatchGroup,
2727
groupOrder: 1,
2828
type: AchievementType.SEQUENTIAL,
29-
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_1.png',
29+
image: 'gamification/achievements/release/new_match/five_pieces/empty_state.png',
3030
tagline: 'Starte eine Lernpatenschaft',
3131
title: 'Neue Lernunterstützung',
3232
subtitle: null,
3333
description:
34-
'Es war großartig, dich am {{date}} besser kennenzulernen und freuen uns, dass du gemeinsam mit uns die Bildungschancen von Schüler:innen verbessern möchtest. Um dir eine:n passende:n Lernpartner:in zuzuweisen, bitten wir dich zunächst, eine Anfrage auf unserer Plattform zu stellen. Hier kannst du die Fächer und Jahrgangsstufe angeben, die für dich passend sind. Wir freuen uns auf den Start!',
34+
'Damit wir dir den:die perfekte:n Lernpartner:in zuweisen können, musst du zunächst eine Anfrage auf unserer Plattform stellen. Dort kannst du ganz einfach die Fächer angeben, die für dich wichtig sind und in denen wir dir helfen können. Wir freuen uns darauf, mit dir gemeinsam durchzustarten und die Lernreise zu beginnen!',
3535
footer: null,
3636
actionName: 'Anfrage stellen',
37-
actionRedirectLink: '/matching',
37+
actionRedirectLink: '/request-match',
3838
actionType: AchievementActionType.Action,
3939
condition: 'false', // This will ensure that an evaluation will always fail
4040
conditionDataAggregations: {},
@@ -50,7 +50,7 @@ const GhostAchievements: { [key: string]: achievement_template } = {
5050
group: PupilNewMatchGroup,
5151
groupOrder: 2,
5252
type: AchievementType.SEQUENTIAL,
53-
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_2.png',
53+
image: 'gamification/achievements/release/new_match/five_pieces/step_1.png',
5454
tagline: 'Starte eine Lernpatenschaft',
5555
title: 'Neue Lernunterstützung',
5656
subtitle: null,
@@ -74,15 +74,15 @@ const GhostAchievements: { [key: string]: achievement_template } = {
7474
group: StudentNewMatchGroup,
7575
groupOrder: 1,
7676
type: AchievementType.SEQUENTIAL,
77-
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_1.png',
77+
image: 'gamification/achievements/release/new_match/five_pieces/empty_state.png',
7878
tagline: 'Starte eine Lernpatenschaft',
7979
title: 'Neue Lernunterstützung',
8080
subtitle: null,
8181
description:
8282
'Es war großartig, dich am {{date}} besser kennenzulernen und freuen uns, dass du gemeinsam mit uns die Bildungschancen von Schüler:innen verbessern möchtest. Um dir eine:n passende:n Lernpartner:in zuzuweisen, bitten wir dich zunächst, eine Anfrage auf unserer Plattform zu stellen. Hier kannst du die Fächer und Jahrgangsstufe angeben, die für dich passend sind. Wir freuen uns auf den Start!',
8383
footer: null,
8484
actionName: 'Anfrage stellen',
85-
actionRedirectLink: '/matching',
85+
actionRedirectLink: '/request-match',
8686
actionType: AchievementActionType.Action,
8787
condition: 'false', // This will ensure that an evaluation will always fail
8888
conditionDataAggregations: {},
@@ -92,30 +92,6 @@ const GhostAchievements: { [key: string]: achievement_template } = {
9292
achievedImage: null,
9393
sequentialStepName: 'Anfrage stellen',
9494
},
95-
student_new_match_2: {
96-
id: -1,
97-
templateFor: AchievementTemplateFor.Match,
98-
group: StudentNewMatchGroup,
99-
groupOrder: 2,
100-
type: AchievementType.SEQUENTIAL,
101-
image: 'gamification/achievements/release/finish_onboarding/two_pieces/step_2.png',
102-
tagline: 'Starte eine Lernpatenschaft',
103-
title: 'Neue Lernunterstützung',
104-
subtitle: null,
105-
description:
106-
'Fantastisch, deine Anfrage ist eingegangen! Bevor wir dir deine:n ideale:n Lernpartner:in vermitteln können, möchten wir gerne kurz per Zoom mit dir sprechen. Unser Ziel ist es, die perfekte Person für dich zu finden und genau zu verstehen, was du dir wünschst. Buche doch gleich einen Termin für unser Gespräch – wir sind schon ganz gespannt auf dich!',
107-
footer: null,
108-
actionName: 'Termin buchen',
109-
actionRedirectLink: 'https://calendly.com',
110-
actionType: AchievementActionType.Action,
111-
condition: 'false',
112-
conditionDataAggregations: {},
113-
isActive: true,
114-
achievedDescription: null,
115-
achievedFooter: null,
116-
achievedImage: null,
117-
sequentialStepName: 'Gespräch mit Lern-Fair absolvieren',
118-
},
11995
};
12096

12197
// Large parts of our user communication are event based, i.e. users get a notification for an appointment,
@@ -175,6 +151,8 @@ async function generatePupilMatching(
175151
});
176152
}
177153

154+
console.log('iso', hasRequest, hasSuccessfulScreening, achievement);
155+
178156
result.push({
179157
id: -1,
180158
templateId: -1,
@@ -183,7 +161,8 @@ async function generatePupilMatching(
183161
template: GhostAchievements.pupil_new_match_1,
184162
context: ctx,
185163
recordValue: null,
186-
achievedAt: hasRequest || achievement ? new Date() : null,
164+
achievedAt: new Date(),
165+
// achievedAt: hasRequest || achievement ? new Date() : null,
187166
relation: achievement?.relation ?? randomRelation,
188167
});
189168

@@ -195,7 +174,8 @@ async function generatePupilMatching(
195174
template: GhostAchievements.pupil_new_match_2,
196175
context: ctx,
197176
recordValue: null,
198-
achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
177+
// achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
178+
achievedAt: new Date(),
199179
relation: achievement?.relation ?? randomRelation,
200180
});
201181
return result;
@@ -211,6 +191,7 @@ async function derivePupilMatching(user: User, pupil: Pupil, result: achievement
211191
where: { pupilId: pupil.id, status: pupil_screening_status_enum.success, invalidated: false },
212192
orderBy: { createdAt: 'desc' },
213193
});
194+
const totalMatchCount = await prisma.match.count({ where: { pupilId: pupil.id } });
214195

215196
const newMatchAchievements = userAchievements.filter(
216197
(row) => row.template.group === PupilNewMatchGroup && row.template.groupOrder === PupilNewMatchGroupOrder
@@ -222,12 +203,20 @@ async function derivePupilMatching(user: User, pupil: Pupil, result: achievement
222203
if (successfulScreenings.length > 0) {
223204
ctx.lastScreeningDate = successfulScreenings[0].updatedAt.toISOString();
224205
}
206+
// This case happens when the student just registered and had a successful screening
207+
if (pupil.openMatchRequestCount === 0 && totalMatchCount === 0) {
208+
console.log('hier');
209+
const ghosts = await generatePupilMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
210+
result.push(...ghosts);
211+
}
225212
for (let i = 0; i < pupil.openMatchRequestCount; i++) {
213+
console.log('hier2');
226214
const ghosts = await generatePupilMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
227215
result.push(...ghosts);
228216
}
229217

230218
for (const userAchievement of newMatchAchievements) {
219+
console.log('hier3');
231220
const ghosts = await generatePupilMatching(userAchievement, user, hasRequest, successfulScreenings.length > 0, ctx);
232221
result.push(...ghosts);
233222
}
@@ -243,6 +232,7 @@ async function deriveStudentMatching(user: User, student: Student, result: achie
243232
where: { studentId: student.id, success: true },
244233
orderBy: { createdAt: 'desc' },
245234
});
235+
const totalMatchCount = await prisma.match.count({ where: { studentId: student.id } });
246236

247237
const newMatchAchievements = userAchievements.filter(
248238
(row) => row.template.group === StudentNewMatchGroup && row.template.groupOrder === StudentNewMatchGroupOrder
@@ -254,13 +244,19 @@ async function deriveStudentMatching(user: User, student: Student, result: achie
254244
if (successfulScreenings.length > 0) {
255245
ctx.lastScreeningDate = successfulScreenings[0].updatedAt.toISOString();
256246
}
247+
// This case happens when the student just registered and had a successful screening
248+
if (student.openMatchRequestCount === 0 && totalMatchCount === 0) {
249+
const ghosts = await generateStudentMatching(null, user, hasRequest, ctx);
250+
result.push(...ghosts);
251+
}
252+
// This will
257253
for (let i = 0; i < student.openMatchRequestCount; i++) {
258-
const ghosts = await generateStudentMatching(null, user, hasRequest, successfulScreenings.length > 0, ctx);
254+
const ghosts = await generateStudentMatching(null, user, hasRequest, ctx);
259255
result.push(...ghosts);
260256
}
261257

262258
for (const userAchievement of newMatchAchievements) {
263-
const ghosts = await generateStudentMatching(userAchievement, user, hasRequest, successfulScreenings.length > 0, ctx);
259+
const ghosts = await generateStudentMatching(userAchievement, user, hasRequest, ctx);
264260
result.push(...ghosts);
265261
}
266262
}
@@ -269,7 +265,6 @@ async function generateStudentMatching(
269265
achievement: achievement_with_template | null,
270266
user: User,
271267
hasRequest: boolean,
272-
hasSuccessfulScreening: boolean,
273268
ctx: StudentNewMatchGhostContext
274269
): Promise<achievement_with_template[]> {
275270
const result: achievement_with_template[] = [];
@@ -306,16 +301,5 @@ async function generateStudentMatching(
306301
relation: achievement?.relation ?? randomRelation,
307302
});
308303

309-
result.push({
310-
id: -1,
311-
templateId: -1,
312-
userId: user.userID,
313-
isSeen: true,
314-
template: GhostAchievements.student_new_match_2,
315-
context: ctx,
316-
recordValue: null,
317-
achievedAt: hasSuccessfulScreening || achievement ? new Date() : null,
318-
relation: achievement?.relation ?? randomRelation,
319-
});
320304
return result;
321305
}

common/achievement/metric.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const batchOfMetrics = [
2929
createMetric('student_onboarding_screened', ['student_screening_appointment_done', 'tutor_screening_success', 'instructor_screening_success'], () => {
3030
return 1;
3131
}),
32+
createMetric('student_onboarding_tutor_screened', ['tutor_screening_success'], () => {
33+
return 1;
34+
}),
3235
createMetric('student_onboarding_coc_success', ['student_coc_updated'], () => {
3336
return 1;
3437
}),
@@ -49,6 +52,9 @@ const batchOfMetrics = [
4952
),
5053

5154
/* CONDUCTED MATCH APPOINTMENT */
55+
createMetric('student_add_match_appointment', ['student_add_appointment_match_with_pupil'], () => {
56+
return 1;
57+
}),
5258
createMetric('student_conducted_match_appointment', ['student_joined_match_meeting'], () => {
5359
return 1;
5460
}),
@@ -106,9 +112,18 @@ const batchOfMetrics = [
106112
}),
107113

108114
/* Matching */
115+
createMetric('pupil_create_new_match_chat', ['pupil_create_new_match_chat'], () => {
116+
return 1;
117+
}),
118+
createMetric('student_create_new_match_chat', ['student_create_new_match_chat'], () => {
119+
return 1;
120+
}),
109121
createMetric('pupil_match_create', ['tutee_matching_success'], () => {
110122
return 1;
111123
}),
124+
createMetric('student_match_requested', ['tutor_match_requested'], () => {
125+
return 1;
126+
}),
112127
createMetric('student_match_create', ['tutor_matching_success'], () => {
113128
return 1;
114129
}),

common/appointment/create.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { getMatch, getPupil, getStudent } from '../../graphql/util';
1414
import { PrerequisiteError, RedundantError } from '../../common/util/error';
1515
import { getContextForGroupAppointmentReminder, getContextForMatchAppointmentReminder } from './util';
1616
import { getNotificationContextForSubcourse } from '../../common/courses/notifications';
17+
import { createRelation, EventRelationType } from '../achievement/relation';
1718

1819
const logger = getLogger();
1920

@@ -96,6 +97,7 @@ export const createMatchAppointments = async (matchId: number, appointmentsToBeC
9697

9798
if (!silent) {
9899
await Notification.actionTaken(userForPupil(pupil), 'student_add_appointment_match', {
100+
relation: createRelation(EventRelationType.Match, matchId),
99101
student,
100102
matchId: matchId.toString(),
101103
});
@@ -110,6 +112,12 @@ export const createMatchAppointments = async (matchId: number, appointmentsToBeC
110112
...(await getContextForMatchAppointmentReminder(appointment)),
111113
pupil,
112114
});
115+
await Notification.actionTaken(userForStudent(student), 'student_add_appointment_match_with_pupil', {
116+
relation: createRelation(EventRelationType.Match, matchId),
117+
pupil,
118+
match: { id: matchId.toString() },
119+
lecture: appointment,
120+
});
113121
}
114122
}
115123

common/chat/create.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import systemMessages from './localization';
99
import { getLogger } from '../logger/logger';
1010
import assert from 'assert';
1111
import { createHmac } from 'crypto';
12+
import { actionTaken } from '../notification';
13+
import { createRelation, EventRelationType } from '../achievement/relation';
1214

1315
const logger = getLogger('Chat');
1416
const getOrCreateOneOnOneConversation = async (
@@ -201,6 +203,22 @@ async function createContactChat(meUser: User, contactUser: User): Promise<strin
201203
},
202204
};
203205

206+
if (contact.match) {
207+
if (meUser.studentId) {
208+
await actionTaken(meUser, 'student_create_new_match_chat', {
209+
user: meUser,
210+
match: { id: `${contact.match.matchId}` },
211+
relation: createRelation(EventRelationType.Match, contact.match.matchId),
212+
});
213+
} else {
214+
await actionTaken(meUser, 'pupil_create_new_match_chat', {
215+
user: meUser,
216+
match: { id: `${contact.match.matchId}` },
217+
relation: createRelation(EventRelationType.Match, contact.match.matchId),
218+
});
219+
}
220+
}
221+
204222
const conversation = await getOrCreateOneOnOneConversation([meUser, contactUser], conversationInfos, ContactReason.CONTACT);
205223
logger.info(`Contact conversation was created by ${meUser} with ${contactUser} with ID ${conversation.id} `);
206224
return conversation.id;

common/notification/actions.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,12 +551,20 @@ const _notificationActions = {
551551
},
552552
},
553553
student_add_appointment_match: {
554-
description: 'Tutee / Tutor added Match Appointment',
554+
description: 'Tutee / Tutor added Match Appointment (Pupil event)',
555555
sampleContext: {
556556
student: sampleUser,
557557
matchId: '1',
558558
},
559559
},
560+
student_add_appointment_match_with_pupil: {
561+
description: 'Tutee / Tutor added Match Appointment (Tutee / Tutor event)',
562+
sampleContext: {
563+
pupil: sampleUser,
564+
match: { id: '1' },
565+
lecture: {},
566+
},
567+
},
560568
pupil_decline_appointment_group: {
561569
description: 'Instructor / Group Appointment declined by Participant',
562570
sampleContext: {
@@ -602,6 +610,20 @@ const _notificationActions = {
602610
appointment: sampleAppointment,
603611
},
604612
},
613+
pupil_create_new_match_chat: {
614+
description: 'User has clicked on new chat with a match partner',
615+
sampleContext: {
616+
user: sampleUser,
617+
match: { id: '1' },
618+
},
619+
},
620+
student_create_new_match_chat: {
621+
description: 'User has clicked on new chat with a match partner',
622+
sampleContext: {
623+
user: sampleUser,
624+
match: { id: '1' },
625+
},
626+
},
605627
missed_one_on_one_chat_message: {
606628
description: 'Missed message in 1:1 chat',
607629
sampleContext: sampleMissedOneOnOneMessage,

common/student/screening.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ export async function addTutorScreening(
6060
},
6161
});
6262

63+
const asUser = userForStudent(student);
6364
if (!batchMode) {
6465
if (screening.success) {
65-
const asUser = userForStudent(student);
6666
await updateSessionRolesOfUser(asUser.userID);
6767
await scheduleCoCReminders(student);
6868
await Notification.actionTaken(userForStudent(student), 'tutor_screening_success', {});

0 commit comments

Comments
 (0)