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

Impl MEE 006 008 010 api #1217

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/api/src/drizzle/schema/meeting.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const Meeting = mysqlTable(
startDate: datetime("start_datetime").notNull(),
endDate: datetime("end_datetime"),
tag: varchar("meeting_group_tag", { length: 255 }).notNull(),
statusEnumId: int("meeting_status_enum").notNull().default(1), // CHACHA : NEW!
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow(),
deletedAt: timestamp("deleted_at"),
Expand Down Expand Up @@ -203,6 +204,9 @@ export const MeetingMapping = mysqlTable(
meetingAgendaContentId: int("meeting_agenda_content_id"),
meetingAgendaVoteId: int("meeting_agenda_vote_id"),
meetingAgendaEntityPosition: int("meeting_agenda_entity_position"),
createdAt: timestamp("created_at").defaultNow(), // CHACHA : NEW!
updatedAt: timestamp("updated_at").defaultNow().onUpdateNow(), // CHACHA : NEW!
deletedAt: timestamp("deleted_at"), // CHACHA : NEW!
},
table => ({
meetingMeetingMappingIdFk: foreignKey({
Expand Down
88 changes: 88 additions & 0 deletions packages/api/src/feature/meeting/agenda/agenda.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
Body,
Controller,
Delete,
Param,
Patch,
Post,
UsePipes,
} from "@nestjs/common";

import apiMee006, {
ApiMee006RequestBody,
ApiMee006RequestParam,
ApiMee006ResponseCreated,
} from "@sparcs-clubs/interface/api/meeting/apiMee006";

import apiMee008, {
ApiMee008RequestBody,
ApiMee008RequestParam,
ApiMee008ResponseOk,
} from "@sparcs-clubs/interface/api/meeting/apiMee008";

import apiMee010, {
ApiMee010RequestParam,
ApiMee010ResponseOk,
} from "@sparcs-clubs/interface/api/meeting/apiMee010";

import { ZodPipe } from "@sparcs-clubs/api/common/pipe/zod-pipe";
import { Executive } from "@sparcs-clubs/api/common/util/decorators/method-decorator";
import { GetExecutive } from "@sparcs-clubs/api/common/util/decorators/param-decorator";

import { AgendaService } from "./agenda.service";

@Controller()
export default class AgendaController {
constructor(private meetingService: AgendaService) {}

@Executive()
@Post("/executive/meetings/meeting/:meetingId/agendas/agenda")
@UsePipes(new ZodPipe(apiMee006))
async postExecutiveMeetingAgenda(
@GetExecutive() user: GetExecutive,
@Param() { meetingId }: ApiMee006RequestParam,
@Body() { meetingEnumId, description, title }: ApiMee006RequestBody,
): Promise<ApiMee006ResponseCreated> {
const result = await this.meetingService.postExecutiveMeetingAgenda(
user.executiveId,
meetingId,
meetingEnumId,
description,
title,
);
return result;
}

@Executive()
@Patch("/executive/meetings/meeting/:meetingId/agendas/agenda/:agendaId")
@UsePipes(new ZodPipe(apiMee008))
async patchExecutiveMeetingAgenda(
@GetExecutive() user: GetExecutive,
@Param() { agendaId }: ApiMee008RequestParam,
@Body() { agendaEnumId, description, title }: ApiMee008RequestBody,
): Promise<ApiMee008ResponseOk> {
const result = await this.meetingService.patchExecutiveMeetingAgenda(
user.executiveId,
agendaId,
agendaEnumId,
description,
title,
);
return result;
}

@Executive()
@Delete("/executive/meetings/meeting/:meetingId/agendas/agenda/:agendaId")
@UsePipes(new ZodPipe(apiMee010))
async deleteExecutiveMeetingAgenda(
@GetExecutive() user: GetExecutive,
@Param() { meetingId, agendaId }: ApiMee010RequestParam,
): Promise<ApiMee010ResponseOk> {
const result = await this.meetingService.deleteExecutiveMeetingAgenda(
user.executiveId,
meetingId,
agendaId,
);
return result;
}
}
17 changes: 17 additions & 0 deletions packages/api/src/feature/meeting/agenda/agenda.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Module } from "@nestjs/common";

import { DrizzleModule } from "@sparcs-clubs/api/drizzle/drizzle.module";
import UserModule from "@sparcs-clubs/api/feature/user/user.module";

import { MeetingRepository } from "../meeting.repository";

import AgendaController from "./agenda.controller";

import { AgendaService } from "./agenda.service";

@Module({
imports: [DrizzleModule, UserModule],
providers: [AgendaService, MeetingRepository],
controllers: [AgendaController],
})
export class AgendaModule {}
95 changes: 95 additions & 0 deletions packages/api/src/feature/meeting/agenda/agenda.service.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ 원래는 서비스 + 컨트롤러 + 레포지토리가 전부 모듈 안으로 들어오는게 좋다고 생각했는데, 이번에는 한 쿼리가 agenda가 아닌 테이블도 건드리다 보니까 그 범위가 애매하다고 느껴집니다. 가능한 한 agendarepository 안으로 가져오고, 한 트랜잭션으로 묶이지 않아도 괜찮을 것 같은 쿼리를 분리하는 것에 대해 어떻게 생각해요?

Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {
HttpException,
HttpStatus,
Injectable,
UnauthorizedException,
} from "@nestjs/common";

import { ApiMee006ResponseCreated } from "@sparcs-clubs/interface/api/meeting/apiMee006";

import { ApiMee008ResponseOk } from "@sparcs-clubs/interface/api/meeting/apiMee008";

import { ApiMee010ResponseOk } from "@sparcs-clubs/interface/api/meeting/apiMee010";

import UserPublicService from "@sparcs-clubs/api/feature/user/service/user.public.service";

import { MeetingRepository } from "../meeting.repository";

@Injectable()
export class AgendaService {
constructor(
private readonly meetingRepository: MeetingRepository,
private readonly userPublicService: UserPublicService,
) {}

async postExecutiveMeetingAgenda(
executiveId: number,
meetingId: number,
meetingEnumId: number,
description: string,
title: string,
): Promise<ApiMee006ResponseCreated> {
const user = await this.userPublicService.getExecutiveById({
id: executiveId,
});

if (!user) {
throw new UnauthorizedException("Not allowed type");
}

await this.meetingRepository.insertMeetingAgendaAndMapping(
meetingId,
meetingEnumId,
description,
title,
);

return {};
}

async patchExecutiveMeetingAgenda(
executiveId: number,
agendaId: number,
agendaEnumId: number,
description: string,
title: string,
): Promise<ApiMee008ResponseOk> {
const user = await this.userPublicService.getExecutiveById({
id: executiveId,
});

if (!user) {
throw new HttpException("Executive not found", HttpStatus.NOT_FOUND);
}

await this.meetingRepository.updateMeetingAgenda(
agendaId,
agendaEnumId,
description,
title,
);

return {};
}

async deleteExecutiveMeetingAgenda(
executiveId: number,
meetingId: number,
agendaId: number,
): Promise<ApiMee010ResponseOk> {
const user = await this.userPublicService.getExecutiveById({
id: executiveId,
});

if (!user) {
throw new HttpException("Executive not found", HttpStatus.NOT_FOUND);
}

await this.meetingRepository.deleteMeetingAgendaMapping(
meetingId,
agendaId,
);

return {};
}
}
3 changes: 2 additions & 1 deletion packages/api/src/feature/meeting/meeting.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { DrizzleModule } from "src/drizzle/drizzle.module";

import UserModule from "../user/user.module";

import { AgendaModule } from "./agenda/agenda.module";
import { AnnouncementModule } from "./announcement/announcement.module";
import MeetingController from "./meeting.controller";
import { MeetingGateway } from "./meeting.gateway";
import { MeetingRepository } from "./meeting.repository";
import { MeetingService } from "./meeting.service";

@Module({
imports: [DrizzleModule, UserModule, AnnouncementModule],
imports: [DrizzleModule, UserModule, AnnouncementModule, AgendaModule],
controllers: [MeetingController],
providers: [MeetingGateway, MeetingService, MeetingRepository],
})
Expand Down
Loading