Skip to content

Commit

Permalink
fix: apiOrg001
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerbera3090 committed Nov 20, 2024
1 parent b8cf236 commit a429ff1
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 36 deletions.
3 changes: 2 additions & 1 deletion packages/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { DrizzleModule } from "./drizzle/drizzle.module";
import { OrganizationModule } from "./feature/organization/organization.module";

@Module({
imports: [DrizzleModule],
imports: [DrizzleModule, OrganizationModule],
controllers: [AppController],
providers: [AppService],
})
Expand Down
77 changes: 50 additions & 27 deletions packages/api/src/drizzle/schema/enum.schema.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,104 @@
import { InferSelectModel } from "drizzle-orm";
import { int, varchar, timestamp, mysqlTable } from "drizzle-orm/mysql-core";

export const OrganizationTypeEnum = mysqlTable("org_typ_e", {
export const OrganizationTypeEnum = mysqlTable("organization_type_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 const OrganizationPresidentTypeEnum = mysqlTable("org_pre_typ_e", {
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 const OrganizationPresidentTypeEnum = mysqlTable(
"organization_president_type_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 const BudgetDomainEnum = mysqlTable("bud_dom_e", {
export const BudgetDomainEnum = mysqlTable("budget_domain_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 const BudgetDivisionIncomeEnum = mysqlTable("bud_div_inc_e", {
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 const BudgetDivisionIncomeEnum = mysqlTable(
"budget_division_income_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 const BudgetDivisionExpenseEnum = mysqlTable("bud_div_exp_e", {
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 const BudgetDivisionExpenseEnum = mysqlTable(
"budget_division_expense_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 const BudgetClassExpenseEnum = mysqlTable("bud_cla_exp_e", {
export const BudgetClassExpenseEnum = mysqlTable("budget_class_expense_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 const TransactionTypeEnum = mysqlTable("tra_typ_e", {
export const TransactionTypeEnum = mysqlTable("transaction_type_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 const ReportFileTypeEnum = mysqlTable("rep_fil_typ_e", {
export const ReportFileTypeEnum = mysqlTable("report_file_type_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 const AssistantPermissionEnum = mysqlTable("ass_per_e", {
export const AssistantPermissionEnum = mysqlTable("assistant_permission_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 const AgendaAcceptedStatusEnum = mysqlTable(
"agenda_accepted_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
>;
export type OrganizationPresidentTypeEnumT = InferSelectModel<
typeof OrganizationPresidentTypeEnum
>;
export type AgendaAcceptedStatusEnumT = InferSelectModel<
typeof AgendaAcceptedStatusEnum
>;
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 @@ -51,6 +51,7 @@ export const OrganizationPresident = mysqlTable(
organizationPresidentTypeEnumId: int(
"organization_president_type_enum_id",
).notNull(),
organizationId: int("organization_id").notNull(),
phoneNumber: varchar("phone_number", { length: 20 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow().notNull(),
Expand All @@ -61,6 +62,10 @@ export const OrganizationPresident = mysqlTable(
columns: [table.userId],
foreignColumns: [User.id],
}),
organizationIdFk: foreignKey({
columns: [table.organizationId],
foreignColumns: [Organization.id],
}),
}),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {

import { OrganizationService } from "../service/organization.service";

@Controller("organization")
@Controller()
export class OrganizationController {
constructor(private readonly organizationService: OrganizationService) {}

Expand Down
3 changes: 2 additions & 1 deletion packages/api/src/feature/organization/organization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { DrizzleModule } from "src/drizzle/drizzle.module";
import { SemesterModule } from "src/feature/semester/semester.module";
import { OrganizationService } from "./service/organization.service";
import { OrganizationController } from "./controller/organization.controller";
import { OrganizationRepository } from "./repository/organization.repository";

@Module({
imports: [DrizzleModule, SemesterModule],
controllers: [OrganizationController],
providers: [OrganizationService],
providers: [OrganizationService, OrganizationRepository],
})
export class OrganizationModule {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable, Inject } from "@nestjs/common";
import { and, or, lte, gte, eq } from "drizzle-orm";
import { and, or, lte, gte, eq, isNull } from "drizzle-orm";
import { MySql2Database } from "drizzle-orm/mysql2";
import { DrizzleAsyncProvider } from "src/drizzle/drizzle.provider";

Expand All @@ -8,14 +8,69 @@ import {
OrganizationTypeEnum,
OrganizationT,
OrganizationTypeEnumT,
User,
UserStudent,
OrganizationPresident,
OrganizationPresidentT,
UserT,
UserStudentT,
} from "src/drizzle/schema";

export type OrganizationWithPresidentT = {
organization: OrganizationT;
organizationType: OrganizationTypeEnumT;
president: OrganizationPresidentT;
user: UserT;
userStudent: UserStudentT;
};
@Injectable()
export class OrganizationRepository {
constructor(
@Inject(DrizzleAsyncProvider) private readonly db: MySql2Database,
) {}

async getOrganizationById(id: number): Promise<OrganizationT[]> {
return this.db.select().from(Organization).where(eq(Organization.id, id));
}

async getOrganizationWithPresidentById(
id: number,
date: Date,
): Promise<OrganizationWithPresidentT[]> {
const res = await this.db
.select()
.from(Organization)
.innerJoin(
OrganizationTypeEnum,
eq(Organization.organizationTypeEnumId, OrganizationTypeEnum.id),
)
.innerJoin(
OrganizationPresident,
eq(Organization.id, OrganizationPresident.organizationId),
)
.innerJoin(User, eq(OrganizationPresident.userId, User.id))
.innerJoin(UserStudent, eq(UserStudent.userId, User.id))
.where(
and(
eq(Organization.id, id),
and(
lte(OrganizationPresident.startTerm, date),
or(
gte(OrganizationPresident.endTerm, date),
isNull(OrganizationPresident.endTerm),
),
),
),
);
return res.map(row => ({
organization: row.organization,
organizationType: row.organization_type_enum,
president: row.organization_president,
user: row.user,
userStudent: row.user_student,
}));
}

async getOrganizationsByTerms(
startTerm: Date,
endTerm: Date,
Expand All @@ -40,11 +95,14 @@ export class OrganizationRepository {
),
and(
lte(Organization.startTerm, endTerm),
eq(Organization.endTerm, null),
isNull(Organization.endTerm),
),
),
);

return res.map(row => ({ ...row, organizationTypeEnum: row.org_typ_e }));
return res.map(row => ({
...row,
organizationTypeEnum: row.organization_type_enum,
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { OrganizationT } from "src/drizzle/schema";
import { SemesterPublicService } from "src/feature/semester/semester.public.service";
import {
OrganizationRepository,
OrganizationWithPresidentT,
} from "../repository/organization.repository";

@Injectable()
export class OrganizationPublicService {
constructor(
private readonly organizationRepository: OrganizationRepository,
private readonly semesterPublicService: SemesterPublicService,
) {}

/**
* @param id organization id
* @returns OrganizationT id에 해당하는 OrganizationT 객체를 리턴합니다.
* @description 해당 id의 organization이 없으면 404 exception을 throw 합니다.
*/
async getOrganizationById(id: number): Promise<OrganizationT> {
const organizations =
await this.organizationRepository.getOrganizationById(id);
if (organizations.length === 0) {
throw new NotFoundException(`Organization with ID ${id} not found.`);
}
return organizations[0];
}

/**
* @param id organizationId, date
* @returns OrganizationT id에 해당하는 OrganizationT 객체를 리턴합니다.
* @description 해당 id의 organization이 없으면 404 exception을 throw 합니다.
*/
async getOrganizationWithPresidentByIdAndDate(
id: number,
date: Date,
): Promise<OrganizationWithPresidentT> {
const organizations =
await this.organizationRepository.getOrganizationWithPresidentById(
id,
date,
);
if (organizations.length === 0) {
throw new NotFoundException(`Organization with ID ${id} not found.`);
}
return organizations[0];
}

/**
* @param id organizationId, semesterId
* @returns OrganizationT id에 해당하는 semester의 마지막 OrganizationWithPresidentT 객체를 리턴합니다.
* @description 해당 id의 organization이 없으면 404 exception을 throw 합니다.
*/
async getOrganizationWithPresidentByIdAndSemester(
id: number,
semesterId: number,
): Promise<OrganizationWithPresidentT> {
const { endTerm } =
await this.semesterPublicService.getSemesterById(semesterId);

return this.getOrganizationWithPresidentByIdAndDate(id, endTerm);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ApiOrg001ResponseOK,
} from "@sparcs-students/interface/api/organization/index";

import SemesterPublicService from "src/feature/semester/semester.public.service";
import { SemesterPublicService } from "src/feature/semester/semester.public.service";

import { OrganizationRepository } from "../repository/organization.repository";

Expand Down
7 changes: 6 additions & 1 deletion packages/api/src/feature/semester/semester.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Module } from "@nestjs/common";
import { DrizzleModule } from "@sparcs-students/api/drizzle/drizzle.module";
import { SemesterRepository } from "./semester.repository";
import { SemesterPublicService } from "./semester.public.service";

@Module({ exports: [SemesterRepository], imports: [DrizzleModule] })
@Module({
providers: [SemesterRepository, SemesterPublicService],
exports: [SemesterPublicService],
imports: [DrizzleModule],
})
export class SemesterModule {}
3 changes: 2 additions & 1 deletion packages/api/src/feature/semester/semester.public.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SemesterT } from "@sparcs-students/api/drizzle/schema";
import { SemesterRepository } from "./semester.repository";

@Injectable()
export default class SemesterPublicService {
export class SemesterPublicService {
constructor(private semesterRepository: SemesterRepository) {}

/**
Expand All @@ -16,6 +16,7 @@ export default class SemesterPublicService {
if (semesters.length === 0) {
throw new NotFoundException(`Semester with ID ${id} not found.`);
}

return semesters[0];
}
}

0 comments on commit a429ff1

Please sign in to comment.