-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1419 from academic-relations/1399-fix-funding-api…
…-for-executive-feedbacks feat base repository and fix funding api for executive feedbacks
- Loading branch information
Showing
16 changed files
with
417 additions
and
297 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export abstract class MEntity { | ||
id: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import { Inject, Injectable, NotFoundException } from "@nestjs/common"; | ||
import { ColumnBaseConfig, ColumnDataType, eq, inArray } from "drizzle-orm"; | ||
import { MySqlColumn, MySqlTable } from "drizzle-orm/mysql-core"; | ||
import { MySql2Database } from "drizzle-orm/mysql2"; | ||
|
||
import { | ||
DrizzleAsyncProvider, | ||
DrizzleTransaction, | ||
} from "@sparcs-clubs/api/drizzle/drizzle.provider"; | ||
|
||
import { MEntity } from "../model/entity.model"; | ||
import { getKSTDate } from "../util/util"; | ||
|
||
interface TableWithId { | ||
id: MySqlColumn<ColumnBaseConfig<ColumnDataType, string>>; | ||
} | ||
|
||
interface ModelWithFrom<T extends MEntity, D> { | ||
from(result: D): T; | ||
} | ||
|
||
@Injectable() | ||
export abstract class BaseRepository< | ||
M extends MEntity, | ||
R, | ||
D, | ||
T extends MySqlTable & TableWithId, | ||
> { | ||
@Inject(DrizzleAsyncProvider) private db: MySql2Database; | ||
|
||
constructor( | ||
protected table: T, | ||
protected modelClass: ModelWithFrom<M, D>, | ||
) {} | ||
|
||
async withTransaction<Result>( | ||
callback: (tx: DrizzleTransaction) => Promise<Result>, | ||
): Promise<Result> { | ||
return this.db.transaction(callback); | ||
} | ||
|
||
async findTx(tx: DrizzleTransaction, id: number): Promise<M | null> { | ||
const result = await tx | ||
.select() | ||
.from(this.table) | ||
.where(eq(this.table.id, id)) | ||
.then(rows => rows.map(row => this.modelClass.from(row as D))); | ||
|
||
return (result[0] as M) ?? null; | ||
} | ||
|
||
async find(id: number): Promise<M | null> { | ||
return this.withTransaction(async tx => this.findTx(tx, id)); | ||
} | ||
|
||
async fetchTx(tx: DrizzleTransaction, id: number): Promise<M> { | ||
const result = await this.findTx(tx, id); | ||
if (result === null) { | ||
throw new NotFoundException(`Not found: ${this.table} with id: ${id}`); | ||
} | ||
return result; | ||
} | ||
|
||
async fetch(id: number): Promise<M> { | ||
return this.withTransaction(async tx => this.fetchTx(tx, id)); | ||
} | ||
|
||
async fetchAllTx(tx: DrizzleTransaction, ids: number[]): Promise<M[]> { | ||
if (ids.length === 0) { | ||
return []; | ||
} | ||
|
||
const result = await tx | ||
.select() | ||
.from(this.table) | ||
.where(inArray(this.table.id, ids)); | ||
|
||
return result.map(row => this.modelClass.from(row as D)); | ||
} | ||
|
||
async fetchAll(ids: number[]): Promise<M[]> { | ||
return this.withTransaction(async tx => this.fetchAllTx(tx, ids)); | ||
} | ||
|
||
async insertTx(tx: DrizzleTransaction, param: R): Promise<M> { | ||
const [result] = await tx.insert(this.table).values(param).execute(); | ||
|
||
const newId = Number(result.insertId); | ||
|
||
return this.fetchTx(tx, newId); | ||
} | ||
|
||
async insert(param: R): Promise<M> { | ||
return this.withTransaction(async tx => this.insertTx(tx, param)); | ||
} | ||
|
||
async putTx(tx: DrizzleTransaction, id: number, param: R): Promise<M> { | ||
await tx | ||
.update(this.table) | ||
.set(param) | ||
.where(eq(this.table.id, id)) | ||
.execute(); | ||
return this.fetchTx(tx, id); | ||
} | ||
|
||
async put(id: number, param: R): Promise<M> { | ||
return this.withTransaction(async tx => this.putTx(tx, id, param)); | ||
} | ||
|
||
async patchTx( | ||
tx: DrizzleTransaction, | ||
oldbie: M, | ||
consumer: (oldbie: M) => M, | ||
): Promise<M> { | ||
const param = consumer(oldbie); | ||
await tx | ||
.update(this.table) | ||
.set(param) | ||
.where(eq(this.table.id, oldbie.id)) | ||
.execute(); | ||
|
||
return this.fetchTx(tx, oldbie.id); | ||
} | ||
|
||
async patch(oldbie: M, consumer: (oldbie: M) => M): Promise<M> { | ||
return this.withTransaction(async tx => this.patchTx(tx, oldbie, consumer)); | ||
} | ||
|
||
async deleteTx(tx: DrizzleTransaction, id: number): Promise<void> { | ||
await tx | ||
.update(this.table) | ||
.set({ deletedAt: getKSTDate() }) | ||
.where(eq(this.table.id, id)) | ||
.execute(); | ||
} | ||
|
||
async delete(id: number): Promise<void> { | ||
return this.withTransaction(async tx => this.deleteTx(tx, id)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 45 additions & 54 deletions
99
packages/api/src/feature/funding/repository/funding.comment.repository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,71 @@ | ||
import { Inject, Injectable } from "@nestjs/common"; | ||
import { IFundingCommentRequestCreate } from "@sparcs-clubs/interface/api/funding/type/funding.type"; | ||
import { eq } from "drizzle-orm"; | ||
import { Injectable } from "@nestjs/common"; | ||
|
||
import { MySql2Database } from "drizzle-orm/mysql2"; | ||
import { IFundingCommentRequest } from "@sparcs-clubs/interface/api/funding/type/funding.comment.type"; | ||
import { eq } from "drizzle-orm"; | ||
|
||
import { | ||
DrizzleAsyncProvider, | ||
DrizzleTransaction, | ||
} from "@sparcs-clubs/api/drizzle/drizzle.provider"; | ||
import { BaseRepository } from "@sparcs-clubs/api/common/repository/base.repository"; | ||
import { DrizzleTransaction } from "@sparcs-clubs/api/drizzle/drizzle.provider"; | ||
import { FundingFeedback } from "@sparcs-clubs/api/drizzle/schema/funding.schema"; | ||
import { MFundingComment } from "@sparcs-clubs/api/feature/funding/model/funding.comment.model"; | ||
import { | ||
FundingCommentDbResult, | ||
MFundingComment, | ||
} from "@sparcs-clubs/api/feature/funding/model/funding.comment.model"; | ||
|
||
@Injectable() | ||
export default class FundingCommentRepository { | ||
constructor(@Inject(DrizzleAsyncProvider) private db: MySql2Database) {} | ||
|
||
// WARD: Transaction | ||
async withTransaction<T>( | ||
callback: (tx: DrizzleTransaction) => Promise<T>, | ||
): Promise<T> { | ||
return this.db.transaction(callback); | ||
} | ||
|
||
async fetchAll(fundingId: number): Promise<MFundingComment[]> { | ||
return this.db.transaction(async tx => this.fetchAllTx(tx, fundingId)); | ||
export default class FundingCommentRepository extends BaseRepository< | ||
MFundingComment, | ||
IFundingCommentRequest, | ||
FundingCommentDbResult, | ||
typeof FundingFeedback | ||
> { | ||
constructor() { | ||
super(FundingFeedback, MFundingComment); | ||
} | ||
|
||
async fetchAllTx( | ||
tx: DrizzleTransaction, | ||
ids: number[], | ||
): Promise<MFundingComment[]>; | ||
async fetchAllTx( | ||
tx: DrizzleTransaction, | ||
fundingId: number, | ||
): Promise<MFundingComment[]>; | ||
async fetchAllTx( | ||
tx: DrizzleTransaction, | ||
arg1: number | number[], | ||
): Promise<MFundingComment[]> { | ||
if (Array.isArray(arg1)) { | ||
return super.fetchAllTx(tx, arg1); | ||
} | ||
|
||
const result = await tx | ||
.select() | ||
.from(FundingFeedback) | ||
.where(eq(FundingFeedback.fundingId, fundingId)); | ||
|
||
return result.map(row => MFundingComment.fromDBResult(row)); | ||
} | ||
.where(eq(FundingFeedback.fundingId, arg1)); | ||
|
||
async fetch(id: number): Promise<MFundingComment> { | ||
return this.db.transaction(async tx => this.fetchTx(tx, id)); | ||
return result.map(row => MFundingComment.from(row)); | ||
} | ||
|
||
async fetchTx(tx: DrizzleTransaction, id: number): Promise<MFundingComment> { | ||
const result = await tx | ||
.select() | ||
.from(FundingFeedback) | ||
.where(eq(FundingFeedback.id, id)); | ||
|
||
if (result.length === 0) { | ||
throw new Error(`Not found: FundingComment with id: ${id}`); | ||
async fetchAll(fundingId: number): Promise<MFundingComment[]>; | ||
async fetchAll(ids: number[]): Promise<MFundingComment[]>; | ||
async fetchAll(arg1: number | number[]): Promise<MFundingComment[]> { | ||
if (Array.isArray(arg1)) { | ||
return super.fetchAll(arg1); | ||
} | ||
return MFundingComment.fromDBResult(result[0]); | ||
} | ||
|
||
async insert(param: IFundingCommentRequestCreate): Promise<MFundingComment> { | ||
return this.db.transaction(async tx => this.insertTx(tx, param)); | ||
return this.withTransaction(async tx => this.fetchAllTx(tx, arg1)); | ||
} | ||
|
||
async insertTx( | ||
tx: DrizzleTransaction, | ||
param: IFundingCommentRequestCreate, | ||
param: IFundingCommentRequest, | ||
): Promise<MFundingComment> { | ||
const [comment] = await tx | ||
.insert(FundingFeedback) | ||
.values({ | ||
...param, | ||
fundingId: param.funding.id, | ||
chargedExecutiveId: param.chargedExecutive.id, | ||
feedback: param.content, | ||
createdAt: new Date(), | ||
}) | ||
.execute(); | ||
|
||
const newId = Number(comment.insertId); | ||
|
||
return this.fetchTx(tx, newId); | ||
const comment = { | ||
...param, | ||
fundingId: param.funding.id, | ||
chargedExecutiveId: param.chargedExecutive.id, | ||
feedback: param.content, | ||
}; | ||
return super.insertTx(tx, comment); | ||
} | ||
} |
Oops, something went wrong.