eletrotupi / tcc/ api/src/lib/queue/processors/insights/dailySleep.ts6b26342b4c2a6455f9f53eba33dca2c0bc5a4cee
2.8 KB | 108 lines Raw
1
import { prisma } from "@app/lib/prisma";
2
import { InsightType, InsightPeriod } from "@prisma/client";
3
import { InsightPeriodPayload } from "@app/lib/queue/types";
4
import { logger } from "@app/lib/logger";
5
import { formatHours, formatDiff } from "@app/utils/calc";
6
import { appDayWindow } from "@app/lib/queue/processors/insights/utils";
7

8
export async function processDailySleep({
9
  userId,
10
  periodStart,
11
}: InsightPeriodPayload): Promise<void> {
12
  const { start: today, end: tomorrow } = appDayWindow(new Date(periodStart));
13
  const { start: yesterday } = appDayWindow(new Date(today.getTime() - 1));
14

15
  const [todayRecords, yesterdayRecords] = await Promise.all([
16
    prisma.sleepRecord.findMany({
17
      where: { userId, date: { gte: today, lt: tomorrow } },
18
      select: { average: true },
19
    }),
20
    prisma.sleepRecord.findMany({
21
      where: { userId, date: { gte: yesterday, lt: today } },
22
      select: { average: true },
23
    }),
24
  ]);
25

26
  logger.debug(
27
    { todayRecords, yesterdayRecords },
28
    "[insights] daily sleep records",
29
  );
30

31
  if (todayRecords.length === 0) return;
32

33
  // average is stored in hours
34
  // sum across all records for the day
35
  const totalToday = todayRecords.reduce(
36
    (sum: number, r: { average: number }) => sum + r.average,
37
    0,
38
  );
39
  const totalYesterday =
40
    yesterdayRecords.length > 0
41
      ? yesterdayRecords.reduce(
42
          (sum: number, r: { average: number }) => sum + r.average,
43
          0,
44
        )
45
      : null;
46

47
  const diffMinutes =
48
    totalYesterday !== null
49
      ? Math.round((totalToday - totalYesterday) * 60)
50
      : null;
51

52
  const sessionCount = todayRecords.length; // 1 = normal night, 2+ = nap(s)
53

54
  const diffStr =
55
    diffMinutes !== null && Math.abs(diffMinutes) >= 5
56
      ? `${formatDiff(diffMinutes)} que ontem`
57
      : "";
58

59
  const napStr =
60
    sessionCount > 1
61
      ? `incluindo ${sessionCount - 1} cochilo${sessionCount > 2 ? "s" : ""}`
62
      : "";
63

64
  await prisma.insight.upsert({
65
    where: {
66
      userId_type_periodStart: {
67
        userId,
68
        type: InsightType.DAILY_SLEEP,
69
        periodStart: today,
70
      },
71
    },
72
    update: {
73
      body: buildBody(totalToday),
74
      metadata: {
75
        totalHours: totalToday,
76
        diffMinutes,
77
        diffStr,
78
        sessionCount,
79
        napStr,
80
        hadNaps: sessionCount > 1,
81
      },
82
      generatedAt: new Date(),
83
    },
84
    create: {
85
      userId,
86
      type: InsightType.DAILY_SLEEP,
87
      period: InsightPeriod.DAILY,
88
      title: "Sono",
89
      body: buildBody(totalToday),
90
      metadata: {
91
        totalHours: totalToday,
92
        diffMinutes,
93
        sessionCount,
94
        diffStr,
95
        napStr,
96
        hadNaps: sessionCount > 1,
97
      },
98
      periodStart: today,
99
      periodEnd: tomorrow,
100
    },
101
  });
102
}
103

104
function buildBody(total: number): string {
105
  const totalStr = formatHours(total);
106

107
  return `${totalStr} de sono hoje`;
108
}