Skip to content

Commit

Permalink
feat: 새로운 강좌 탐지 시 알림 기능
Browse files Browse the repository at this point in the history
  • Loading branch information
leemhoon00 committed Dec 8, 2024
1 parent 09ee39d commit e9a6404
Show file tree
Hide file tree
Showing 6 changed files with 390 additions and 2 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@types/aws-lambda": "^8.10.145",
"@types/dotenv": "^6.1.1",
"@types/pg": "^8.11.10",
"@types/uuid": "^10.0.0",
"prisma": "^5.22.0",
"prisma-kysely": "^1.8.0",
"ts-node": "^10.9.2",
Expand All @@ -22,6 +23,7 @@
"dependencies": {
"dotenv": "^16.4.5",
"kysely": "^0.27.4",
"pg": "^8.13.1"
"pg": "^8.13.1",
"uuid": "^11.0.3"
}
}
124 changes: 124 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,64 @@ datasource db {
url = env("DATABASE_URL")
}

model User {
id String @id
email String @unique
nickname String
createdAt DateTime @default(now())
NormalFavorite NormalFavorite[]
SpecialFavorite SpecialFavorite[]
Notification Notification[]
Review Review[]
}

model NormalFavorite {
userId String
businessId String
serialNumber String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([userId, businessId, serialNumber])
}

model SpecialFavorite {
userId String
businessId String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([userId, businessId])
}

model Notification {
id String @id @default(uuid()) @db.Uuid
userId String
businessId String
serialNumber String?
facilityName String
courseNames String[]
isViewed Boolean @default(false)
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Review {
id String @id @default(uuid()) @db.Uuid
userId String
businessId String
serialNumber String?
score Float
content String
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Facility {
businessId String
serialNumber String
Expand Down Expand Up @@ -41,6 +99,35 @@ model Course {
@@id([businessId, courseId])
}

model CourseHistory {
businessId String
facilityName String
itemCode String
itemName String
address String
detailAddress String?
courseName String
courseId String
startDate DateTime @db.Date
endDate DateTime @db.Date
participantCount Int
price Int
@@id([courseId, startDate])
}

model SpecialFacility {
businessId String @id
name String
cityCode String
cityName String
localCode String
localName String
address String
detailAddress String?
phone String?
}

model SpecialCourse {
businessId String
courseId String
Expand All @@ -54,3 +141,40 @@ model SpecialCourse {
@@id([businessId, courseId])
}

model SpecialCourseHistory {
businessId String
facilityName String
itemCode String
itemName String
address String
detailAddress String?
courseName String
courseId String
startDate DateTime @db.Date
endDate DateTime @db.Date
participantCount Int
price Int
cityCode String
cityName String
localCode String
localName String
phone String?
@@id([businessId, courseId, startDate])
}

model NormalPreviousCourse {
businessId String
serialNumber String
count Int
@@id([businessId, serialNumber])
}

model SpecialPreviousCourse {
businessId String
count Int
@@id([businessId])
}
85 changes: 85 additions & 0 deletions src/course/course.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Database } from 'src/db/database';
import { sql } from 'kysely';
import { v4 as uuidv4 } from 'uuid';

export class CourseService {
key: string;
Expand Down Expand Up @@ -26,6 +28,21 @@ export class CourseService {
}

async saveAllCourse() {
await this.db.deleteFrom('NormalPreviousCourse').execute();
await this.db.executeQuery(
sql`
insert into "NormalPreviousCourse"("businessId", "serialNumber", "count")
SELECT
"businessId",
"facilitySerialNumber",
count(*) as "count"
FROM "Course"
GROUP BY
"businessId",
"facilitySerialNumber";
`.compile(this.db)
);

await this.db.deleteFrom('Course').execute();
const loopCount = await this.getLoopCount();

Expand Down Expand Up @@ -103,6 +120,74 @@ export class CourseService {

await this.db.insertInto('Course').values(courses).execute();
}

const afterResult = await this.db.executeQuery(
sql<{ businessId: string; serialNumber: string }>`
select
a."businessId",
a."facilitySerialNumber" as "serialNumber"
from
(select
"businessId",
"facilitySerialNumber",
count(*) as "count"
from "Course"
group by
"businessId",
"facilitySerialNumber") as a
left join "NormalPreviousCourse" as b
on a."businessId" = b."businessId" and a."facilitySerialNumber" = b."serialNumber"
where a."count" != b."count" or b."count" is null;
`.compile(this.db)
);

for await (const facility of afterResult.rows) {
const [facilityName, courseNames, users] = await Promise.all([
this.db
.selectFrom('Facility')
.select('name')
.where('businessId', '=', facility.businessId)
.where('serialNumber', '=', facility.serialNumber)
.execute(),
this.db
.selectFrom('Course')
.select('courseName')
.where('businessId', '=', facility.businessId)
.where('facilitySerialNumber', '=', facility.serialNumber)
.execute(),
this.db
.selectFrom('NormalFavorite')
.select('userId')
.where('businessId', '=', facility.businessId)
.where('serialNumber', '=', facility.serialNumber)
.execute(),
]);

if (
facilityName.length === 0 ||
facilityName[0] === undefined ||
courseNames.length === 0 ||
users.length === 0
) {
continue;
}

for await (const user of users) {
await this.db
.insertInto('Notification')
.values([
{
id: uuidv4(),
userId: user.userId,
businessId: facility.businessId,
serialNumber: facility.serialNumber,
facilityName: facilityName[0].name,
courseNames: courseNames.map((course) => course.courseName),
},
])
.execute();
}
}
}
}

Expand Down
76 changes: 76 additions & 0 deletions src/course/special-course.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Database } from 'src/db/database';
import { sql } from 'kysely';
import { v4 as uuidv4 } from 'uuid';

export class SpecialCourseService {
key: string;
Expand Down Expand Up @@ -27,6 +29,19 @@ export class SpecialCourseService {
}

async saveAllCourse() {
await this.db.deleteFrom('SpecialPreviousCourse').execute();
await this.db.executeQuery(
sql`
insert into "SpecialPreviousCourse"("businessId", "count")
SELECT
"businessId",
count(*) as "count"
FROM "SpecialCourse"
GROUP BY
"businessId"
`.compile(this.db)
);

await this.db.deleteFrom('SpecialCourse').execute();
const loopCount = await this.getLoopCount();

Expand Down Expand Up @@ -103,6 +118,67 @@ export class SpecialCourseService {

await this.db.insertInto('SpecialCourse').values(courses).execute();
}

const afterResult = await this.db.executeQuery(
sql<{ businessId: string }>`
select
a."businessId"
from
(select
"businessId",
count(*) as "count"
from "SpecialCourse"
group by
"businessId") as a
left join "SpecialPreviousCourse" as b
on a."businessId" = b."businessId"
where a."count" != b."count" or b."count" is null;
`.compile(this.db)
);

for await (const facility of afterResult.rows) {
const [facilityName, courseNames, users] = await Promise.all([
this.db
.selectFrom('SpecialFacility')
.select('name')
.where('businessId', '=', facility.businessId)
.execute(),
this.db
.selectFrom('SpecialCourse')
.select('courseName')
.where('businessId', '=', facility.businessId)
.execute(),
this.db
.selectFrom('SpecialFavorite')
.select('userId')
.where('businessId', '=', facility.businessId)
.execute(),
]);

if (
facilityName.length === 0 ||
facilityName[0] === undefined ||
courseNames.length === 0 ||
users.length === 0
) {
continue;
}

for await (const user of users) {
await this.db
.insertInto('Notification')
.values([
{
id: uuidv4(),
userId: user.userId,
businessId: facility.businessId,
facilityName: facilityName[0].name,
courseNames: courseNames.map((course) => course.courseName),
},
])
.execute();
}
}
}
}

Expand Down
Loading

0 comments on commit e9a6404

Please sign in to comment.