Implement Overtime Repository

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)
}
}