eletrotupi / tcc/ api/src/lib/queue/processors/insights/dailySleep.tsde0605fcb0d1980cedfafe4830a7aeaef31de5dc
2.7 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 {
7
  appDayWindow,
8
  previousAppDay,
9
  DAY_WINDOW_LABEL,
10
} from "@app/lib/queue/processors/insights/utils";
11

12
export async function processDailySleep({
13
  userId,
14
  periodStart,
15
}: InsightPeriodPayload): Promise<void> {
16
  const { start: today, end: tomorrow } = appDayWindow(new Date(periodStart));
17
  const yesterday = previousAppDay(today);
18

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

30
  logger.debug(
31
    { todayRecords, yesterdayRecords },
32
    "[insights] daily sleep records",
33
  );
34

35
  if (todayRecords.length === 0) return;
36

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

51
  const diffMinutes =
52
    totalYesterday !== null
53
      ? Math.round((totalToday - totalYesterday) * 60)
54
      : null;
55

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

58
  const diffStr =
59
    diffMinutes !== null && Math.abs(diffMinutes) >= 5
60
      ? `${formatDiff(diffMinutes)} que ontem`
61
      : "";
62

63
  const napStr =
64
    sessionCount > 1
65
      ? `incluindo ${sessionCount - 1} cochilo${sessionCount > 2 ? "s" : ""}`
66
      : "";
67

68
  const metadata = {
69
    totalHours: totalToday,
70
    diffMinutes,
71
    diffStr,
72
    sessionCount,
73
    napStr,
74
    hadNaps: sessionCount > 1,
75
    windowLabel: DAY_WINDOW_LABEL,
76
  };
77

78
  await prisma.insight.upsert({
79
    where: {
80
      userId_type_periodStart: {
81
        userId,
82
        type: InsightType.DAILY_SLEEP,
83
        periodStart: today,
84
      },
85
    },
86
    update: {
87
      body: buildBody(totalToday),
88
      metadata,
89
      generatedAt: new Date(),
90
    },
91
    create: {
92
      userId,
93
      type: InsightType.DAILY_SLEEP,
94
      period: InsightPeriod.DAILY,
95
      title: "Sono",
96
      body: buildBody(totalToday),
97
      metadata,
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
}