Skip to content
CodeSook
CodeSook

16. Implement Overtime Repository


Let’s create interface for Overtime Repository

ก็ทำเหมือนกันกับ Employee repository เลย

Files and Folders

folder structure
src
18 collapsed lines
├── configure
└── openapi
├── setup-openapi.ts
└── setup-scalar-docs.ts
├── controllers
├── employees
├── delete.ts
├── get.ts
├── index.ts
├── post.ts
└── put.ts
├── healthz.ts
└── overtimes
├── get.ts
├── index.ts
└── post.ts
├── global.d.ts
├── index.ts
├── repositories
6 collapsed lines
├── employees
├── creates.ts
├── finds.ts
├── index.ts
├── removes.ts
└── updates.ts
├── overtimes
├── creates.ts
├── finds.ts
├── index.ts
├── removes.ts
└── updates.ts
23 collapsed lines
└── prisma.ts
├── schema
├── branded.ts
├── employee.ts
├── employeeWithRelations.ts
├── general.ts
├── helpers.ts
├── index.ts
├── overtime.ts
└── overtimeWithRelations.ts
├── services
├── employee
├── create.ts
├── finds.ts
├── index.ts
├── removes.ts
└── updates.ts
└── overtime
├── creates.ts
├── finds.ts
├── index.ts
├── removes.ts
└── updates.ts
└── types
├── repositories
├── employee.ts
└── overtime.ts
3 collapsed lines
└── services
├── employee.ts
└── overtime.ts

Overtime Interface

เราจะมาสร้าง interface หรือ type กันก่อน เพื่อให้เห็นภาพรวมก่อนว่าเราจะต้องทำอะไรบ้าง

types/repositories/overtime.ts
types/repositories/overtime.ts
import type { Branded, EmployeeSchema, OvertimeSchema, OvertimeWithRelationsSchema } from "../../schema/index.js"
export type OvertimeRepository = {
create: (data: OvertimeSchema.CreateOvertime) => Promise<OvertimeSchema.Overtime>
findById: (id: Branded.OvertimeId) => Promise<OvertimeSchema.Overtime | null>
findByIdWithRelations: (id: Branded.OvertimeId) => Promise<OvertimeWithRelationsSchema.OvertimeWithRelations | null>
findMany: () => Promise<OvertimeSchema.OvertimeArray>
findManyWithRelations: () => Promise<OvertimeWithRelationsSchema.OvertimeWithRelationsArray>
findByDeparmentName: (departmentName: EmployeeSchema.Employee["department"]) => Promise<OvertimeWithRelationsSchema.OvertimeWithRelationsArray>
summaryByEmployeeId: (filters: { employeeId: Branded.EmployeeId, dateRange: { start: Date, end: Date } }) => Promise<{ hoursWorked: number }>
summaryByDepartment: (filters: { department: EmployeeSchema.Employee["department"], dateRange: { start: Date, end: Date } }) => Promise<{ hoursWorked: number }>
update: (id: Branded.OvertimeId, data: OvertimeSchema.UpdateOvertime) => Promise<OvertimeSchema.Overtime | null>
updatePartial: (id: Branded.OvertimeId, data: Partial<OvertimeSchema.UpdateOvertime>) => Promise<OvertimeSchema.Overtime | null>
remove: (id: Branded.OvertimeId) => Promise<OvertimeSchema.Overtime | null>
hardRemove: (id: Branded.OvertimeId) => Promise<OvertimeSchema.Overtime | null>
}

Overtime Repository functions

repositories/overtimes/creates.ts
repositories/overtimes/creates.ts
import type { PrismaClient } from "@prisma/client"
import type { OvertimeRepository } from "../../types/repositories/overtime.js"
import { Helpers, OvertimeSchema } from "../../schema/index.js"
export function create(prismaClient: PrismaClient): OvertimeRepository["create"] {
return async (data) => {
const overtime = await prismaClient.overtime.create({
data,
})
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(overtime)
}
}

Finding Overtime Repository functions

เราจะยังทำเหมือนเดิม ทำ Dependency Injection

เขียน find functions ต้องอย่าลืมว่าเราจะไม่เอาตัวที่ถูกทำ soft deleted ไปแล้วนะ

repositories/overtimes/finds.ts
repositories/overtimes/finds.ts
import type { PrismaClient } from "@prisma/client"
import type { OvertimeRepository } from "../../types/repositories/overtime.js"
import { Helpers, OvertimeSchema, OvertimeWithRelationsSchema } from "../../schema/index.js"
export function findById(prismaClient: PrismaClient): OvertimeRepository["findById"] {
return async (id) => {
const overtime = await prismaClient.overtime.findUnique({
where: {
deletedAt: null,
id,
},
})
if (overtime === null)
return null
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(overtime)
}
}
export function findByIdWithRelations(prismaClient: PrismaClient): OvertimeRepository["findByIdWithRelations"] {
return async (id) => {
const overtime = await prismaClient.overtime.findUnique({
include: {
employee: true,
},
where: {
deletedAt: null,
id,
},
})
if (overtime === null)
return null
return Helpers.fromObjectToSchema(OvertimeWithRelationsSchema.Schema)(overtime)
}
}
export function findMany(prismaClient: PrismaClient): OvertimeRepository["findMany"] {
return async () => {
const overtimes = await prismaClient.overtime.findMany({
where: {
deletedAt: null,
},
})
return Helpers.fromObjectToSchema(OvertimeSchema.SchemaArray)(overtimes)
}
}
export function findManyWithRelations(prismaClient: PrismaClient): OvertimeRepository["findManyWithRelations"] {
return async () => {
const overtimes = await prismaClient.overtime.findMany({
include: {
employee: true,
},
where: {
deletedAt: null,
},
})
return Helpers.fromObjectToSchema(OvertimeWithRelationsSchema.SchemaArray)(overtimes)
}
}
export function findByDeparmentName(prismaClient: PrismaClient): OvertimeRepository["findByDeparmentName"] {
return async (departmentName) => {
const overtimes = await prismaClient.overtime.findMany({
include: {
employee: true,
},
where: {
deletedAt: null,
employee: {
department: departmentName,
},
},
})
return Helpers.fromObjectToSchema(OvertimeWithRelationsSchema.SchemaArray)(overtimes)
}
}
export function summaryByEmployeeId(prismaClient: PrismaClient): OvertimeRepository["summaryByEmployeeId"] {
return async (filters) => {
const agg = await prismaClient.overtime.aggregate({
_sum: {
hoursWorked: true,
},
where: {
date: {
gte: filters.dateRange.start,
lt: filters.dateRange.end,
},
employee: {
id: filters.employeeId,
},
},
})
if (agg._sum.hoursWorked === null) {
return {
hoursWorked: 0,
}
}
return {
hoursWorked: agg._sum.hoursWorked,
}
}
}
export function summaryByDepartment(prismaClient: PrismaClient): OvertimeRepository["summaryByDepartment"] {
return async (filters) => {
const agg = await prismaClient.overtime.aggregate({
_sum: {
hoursWorked: true,
},
where: {
date: {
gte: filters.dateRange.start,
lt: filters.dateRange.end,
},
employee: {
department: filters.department,
},
},
})
if (agg._sum.hoursWorked === null) {
return {
hoursWorked: 0,
}
}
return {
hoursWorked: agg._sum.hoursWorked,
}
}
}

จากด้านบนเรามีการทำการ find แบบปกติ
แต่ที่เพิ่มมาคือการทำ aggregate จาก function summaryByEmployeeId(), summaryByDepartment()

Updating Overtime Repository functions

repositories/overtimes/updates.ts
repositories/overtimes/updates.ts
import type { PrismaClient } from "@prisma/client"
import type { OvertimeRepository } from "../../types/repositories/overtime.js"
import { Helpers, OvertimeSchema } from "../../schema/index.js"
export function update(prismaClient: PrismaClient): OvertimeRepository["update"] {
return async (id, data) => {
const overtime = await prismaClient.overtime.update({
data,
where: {
id,
},
})
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(overtime)
}
}
export function updatePartial(prismaClient: PrismaClient): OvertimeRepository["updatePartial"] {
return async (id, data) => {
const overtime = await prismaClient.overtime.update({
data,
where: {
id,
},
})
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(overtime)
}
}

Remove Overtime functions

repositories/overtimes/removes.ts
repositories/overtimes/removes.ts
import type { PrismaClient } from "@prisma/client"
import type { OvertimeRepository } from "../../types/repositories/overtime.js"
import { Helpers, OvertimeSchema } from "../../schema/index.js"
export function removeById(prismaClient: PrismaClient): OvertimeRepository["remove"] {
return async (id) => {
const data = await prismaClient.overtime.update({
data: {
deletedAt: new Date(),
},
where: {
id,
},
})
if (data === null)
return null
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(data)
}
}
export function hardRemoveById(prismaClient: PrismaClient): OvertimeRepository["hardRemove"] {
return async (id) => {
const data = await prismaClient.overtime.delete({
where: {
id,
},
})
if (data === null)
return null
return Helpers.fromObjectToSchema(OvertimeSchema.Schema)(data)
}
}