Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

64 impl proposal apis post and get #65

Merged
merged 10 commits into from
Dec 2, 2024
14 changes: 14 additions & 0 deletions packages/api/src/drizzle/schema/enum.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ export const AgendaAcceptedStatusEnum = mysqlTable(
},
);

export const DocumentReviewStatusEnum = mysqlTable(
"document_review_status_enum",
{
id: int("id").autoincrement().primaryKey().notNull(),
name: varchar("name", { length: 30 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
},
);

export type OrganizationTypeEnumT = InferSelectModel<
typeof OrganizationTypeEnum
>;
Expand All @@ -102,3 +113,6 @@ export type OrganizationPresidentTypeEnumT = InferSelectModel<
export type AgendaAcceptedStatusEnumT = InferSelectModel<
typeof AgendaAcceptedStatusEnum
>;
export type DocumentReviewStatusEnumT = InferSelectModel<
typeof DocumentReviewStatusEnum
>;
5 changes: 5 additions & 0 deletions packages/api/src/drizzle/schema/organization.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const OperatingCommitteeMember = mysqlTable(
id: int("id").autoincrement().primaryKey().notNull(),
organizationId: int("organization_id").notNull(),
userId: int("user_id").notNull(),
semesterId: int("semester_id").notNull(),
role: varchar("role", { length: 30 }).notNull(),
legalBasis: varchar("legal_basis", { length: 30 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
Expand All @@ -115,6 +116,10 @@ export const OperatingCommitteeMember = mysqlTable(
columns: [table.userId],
foreignColumns: [User.id],
}),
semesterIdFk: foreignKey({
columns: [table.semesterId],
foreignColumns: [Semester.id],
}),
}),
);

Expand Down
132 changes: 121 additions & 11 deletions packages/api/src/drizzle/schema/proposal.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
BudgetDivisionIncomeEnum,
BudgetDivisionExpenseEnum,
BudgetClassExpenseEnum,
DocumentReviewStatusEnum,
} from "./enum.schema";

// ProjectProposal 테이블
Expand Down Expand Up @@ -51,17 +52,18 @@ export const ProjectProposalRevision = mysqlTable(
id: int("id").autoincrement().primaryKey().notNull(),
documentId: int("document_id").notNull(),
name: varchar("name", { length: 255 }).notNull(),
method: text("method").notNull(),
prepareStartTerm: datetime("prepare_start_term").notNull(),
prepareEndTerm: datetime("prepare_end_term").notNull(),
startTerm: datetime("start_term").notNull(),
endTerm: datetime("end_term").notNull(),
teamId: int("team_id").notNull(),
managerId: int("manager_id").notNull(),
purpose: text("purpose").notNull(),
target: text("target").notNull(),
detail: text("detail").notNull(),
method: text("method"),
prepareStartTerm: datetime("prepare_start_term"),
prepareEndTerm: datetime("prepare_end_term"),
startTerm: datetime("start_term"),
endTerm: datetime("end_term"),
teamId: int("team_id"),
managerId: int("manager_id"),
purpose: text("purpose"),
target: text("target"),
detail: text("detail"),
note: text("note"),
submittedAt: timestamp("submitted_at"),
agendaId: int("agenda_id"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
Expand Down Expand Up @@ -198,13 +200,14 @@ export const BudgetProposalIncomeRevision = mysqlTable(
documentId: int("document_id").notNull(),
budgetDomainEnumId: int("budget_domain_enum_id"),
budgetDivisionIncomeEnumId: int("budget_division_income_enum_id"),
name: varchar("name", { length: 30 }),
name: varchar("name", { length: 30 }).notNull(),
amount: int("amount"),
detail: text("detail"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
agendaId: int("agenda_id"),
submittedAt: timestamp("submitted_at"),
},
table => ({
documentIdFk: foreignKey({
Expand Down Expand Up @@ -272,6 +275,7 @@ export const BudgetProposalExpenseRevision = mysqlTable(
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
agendaId: int("agenda_id"),
submittedAt: timestamp("submitted_at"),
},
table => ({
documentIdFk: foreignKey({
Expand Down Expand Up @@ -307,6 +311,103 @@ export const BudgetProposalExpenseRevision = mysqlTable(
}),
);

// ProjectProposalDocumentReview 테이블
export const ProjectProposalDocumentReview = mysqlTable(
"project_proposal_document_review",
{
id: int("id").autoincrement().primaryKey().notNull(),
documentId: int("document_id").notNull(),
userId: int("user_id").notNull(),
documentReviewStatusEnumId: int("document_review_status_enum_id").notNull(),
detail: text("detail"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
},
table => ({
documentIdFk: foreignKey({
columns: [table.documentId],
foreignColumns: [ProjectProposal.id],
name: "pro_pro_doc_rev_document_id_fk",
}),
userIdFk: foreignKey({
columns: [table.userId],
foreignColumns: [User.id],
name: "pro_pro_doc_rev_user_id_fk",
}),
documentReviewStatusEnumIdFk: foreignKey({
columns: [table.documentReviewStatusEnumId],
foreignColumns: [DocumentReviewStatusEnum.id],
name: "pro_pro_doc_rev_document_review_status_enum_id_fk",
}),
}),
);

// BudgetProposalIncomeDocumentReview 테이블
export const BudgetProposalIncomeDocumentReview = mysqlTable(
"budget_proposal_income_document_review",
{
id: int("id").autoincrement().primaryKey().notNull(),
documentId: int("document_id").notNull(),
userId: int("user_id").notNull(),
documentReviewStatusEnumId: int("document_review_status_enum_id").notNull(),
detail: text("detail"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
},
table => ({
documentIdFk: foreignKey({
columns: [table.documentId],
foreignColumns: [BudgetProposalIncome.id],
name: "bud_pro_inc_doc_rev_document_id_fk",
}),
userIdFk: foreignKey({
columns: [table.userId],
foreignColumns: [User.id],
name: "bud_pro_inc_doc_rev_user_id_fk",
}),
documentReviewStatusEnumIdFk: foreignKey({
columns: [table.documentReviewStatusEnumId],
foreignColumns: [DocumentReviewStatusEnum.id],
name: "bud_pro_inc_doc_rev_document_review_status_enum_id_fk",
}),
}),
);

// BudgetProposalExpenseDocumentReview 테이블
export const BudgetProposalExpenseDocumentReview = mysqlTable(
"budget_proposal_expense_document_review",
{
id: int("id").autoincrement().primaryKey().notNull(),
documentId: int("document_id").notNull(),
userId: int("user_id").notNull(),
documentReviewStatusEnumId: int("document_review_status_enum_id").notNull(),
detail: text("detail"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
deletedAt: timestamp("deleted_at"),
},
table => ({
documentIdFk: foreignKey({
columns: [table.documentId],
foreignColumns: [BudgetProposalExpense.id],
name: "bud_pro_exp_doc_rev_document_id_fk",
}),
userIdFk: foreignKey({
columns: [table.userId],
foreignColumns: [User.id],
name: "bud_pro_exp_doc_rev_user_id_fk",
}),
documentReviewStatusEnumIdFk: foreignKey({
columns: [table.documentReviewStatusEnumId],
foreignColumns: [DocumentReviewStatusEnum.id],
name: "bud_pro_exp_doc_rev_document_review_status_enum_id_fk",
}),
}),
);

// 타입 추론
export type ProjectProposalT = InferSelectModel<typeof ProjectProposal>;
export type ProjectProposalRevisionT = InferSelectModel<
typeof ProjectProposalRevision
Expand All @@ -330,3 +431,12 @@ export type BudgetProposalExpenseT = InferSelectModel<
export type BudgetProposalExpenseRevisionT = InferSelectModel<
typeof BudgetProposalExpenseRevision
>;
export type ProjectProposalDocumentReviewT = InferSelectModel<
typeof ProjectProposalDocumentReview
>;
export type BudgetProposalIncomeDocumentReviewT = InferSelectModel<
typeof BudgetProposalIncomeDocumentReview
>;
export type BudgetProposalExpenseDocumentReviewT = InferSelectModel<
typeof BudgetProposalExpenseDocumentReview
>;
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,68 @@ export class OrganizationRepository {
return this.db.select().from(Organization).where(eq(Organization.id, id));
}

async selectOrganization(
target: Partial<OrganizationT>,
): Promise<OrganizationT[]> {
const {
id,
name,
nameEng,
organizationTypeEnumId,
foundingYear,
startTerm,
endTerm,
} = target;
let query = this.db.select().from(Organization).$dynamic();

const whereConditions = [];

if (id) {
whereConditions.push(eq(Organization.id, id));
}

if (name) {
whereConditions.push(eq(Organization.name, name));
}

if (nameEng) {
whereConditions.push(eq(Organization.nameEng, nameEng));
}

if (organizationTypeEnumId) {
whereConditions.push(
eq(Organization.organizationTypeEnumId, organizationTypeEnumId),
);
}

if (foundingYear) {
whereConditions.push(eq(Organization.foundingYear, foundingYear));
}

if (startTerm) {
whereConditions.push(
or(gte(Organization.endTerm, startTerm), isNull(Organization.endTerm)),
);
}

if (endTerm) {
whereConditions.push(lte(Organization.startTerm, endTerm));
}

// 삭제된 항목 제외
whereConditions.push(isNull(Organization.deletedAt));

// 조건이 하나라도 있으면 AND로 묶어서 처리
if (whereConditions.length > 0) {
query = query.where(and(...whereConditions));
}

// 쿼리 실행
const res = await query.execute();

return res;
}

async getOrganizationWithPresidentById(
organizationId: number,
date: Date,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class OrganizationPublicService {

/**
* @param userId, organizationId, startTerm, endTerm
* @returns TeamMemeberT 해당 학기 해당 단체에 해당하는 TeamMemberT 객체를 리턴합니다.
* @returns OrganizationMemeberT 해당 학기 해당 단체에 해당하는 OrganizationMemberT 객체를 리턴합니다.
* @description 해당 시기에 해당하는 OrganizationMember가 없으면 404 exception을 throw 합니다.
*/
async getOrganizationMemberByUserAndOrgAndDate(
Expand Down Expand Up @@ -110,13 +110,13 @@ export class OrganizationPublicService {

/**
* @param userId, organizationId, semesterId
* @returns TeamMemeberT 해당 학기 해당 단체에 해당하는 TeamMemberT 객체를 리턴합니다.
* @returns OrganizationMemeberT 해당 학기 해당 단체에 해당하는 OrganizationMemberT 객체를 리턴합니다.
* @description 해당 시기에 해당하는 OrganizationMember가 없으면 404 exception을 throw 합니다.
*/
async getOrganizationMemberByUserAndOrgAndSemester(
userId: number,
semesterId: number,
organizationId: number,
semesterId: number,
): Promise<OrganizationMemberT> {
const { startTerm, endTerm } =
await this.semesterPublicService.getSemesterById(semesterId);
Expand All @@ -127,4 +127,30 @@ export class OrganizationPublicService {
endTerm,
);
}

/**
* @param organizationId, semesterId
* @returns boolean 단체가 해당 학기에 존재했으면 true, 아니면 false를 리턴합니다.
* @description organizationId에 해당하는 단체가 semesterId에 해당하는 학기에 존재하는지 확인합니다.
* 해당 시기에 해당하는 Organization이 없었더라도 404Error를 발생시키지 않습니다.
*/
async checkOrganizationInSemester(
organizationId: number,
semesterId: number,
): Promise<boolean> {
const semester =
await this.semesterPublicService.getSemesterById(semesterId);
const organizations = await this.organizationRepository.selectOrganization({
id: organizationId,
startTerm: semester.startTerm,
endTerm: semester.endTerm,
});
if (organizations.length > 1) {
throw new HttpException(
`Unreachable: Organization with ID ${organizationId} has multiple records.`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
return organizations.length !== 0;
}
}
Loading