From c902eb0f1bdab011f80102c79da8bb987a9fbbcd Mon Sep 17 00:00:00 2001 From: Janaina <jsk22@inf.ufpr.br> Date: Fri, 27 Sep 2024 12:02:49 -0300 Subject: [PATCH] ok --- src/db/migrations/0000_noisy_metal_master.sql | 3 - src/db/repo/status.repo.ts | 50 +++++++ src/db/repo/submission-reason.repo.ts | 51 +++++++ src/db/schema/complaints.model.ts | 10 ++ src/db/schema/index.ts | 10 +- src/db/schema/status.schema.ts | 27 ++++ src/db/schema/submission-reason.schema.ts | 27 ++++ src/db/schema/submission.model.ts | 8 +- src/db/seed.ts | 2 + src/db/seeds/index.ts | 2 + src/db/seeds/status.seed.ts | 19 +++ src/db/seeds/submission-reason.seed.ts | 19 +++ src/db/seeds/submission.seed.ts | 8 -- src/index.ts | 4 + src/routes/status.route.ts | 134 ++++++++++++++++++ src/routes/submission-reason.route.ts | 134 ++++++++++++++++++ src/services/status.service.ts | 29 ++++ src/services/submission-reason.service.ts | 29 ++++ 18 files changed, 546 insertions(+), 20 deletions(-) create mode 100644 src/db/repo/status.repo.ts create mode 100644 src/db/repo/submission-reason.repo.ts create mode 100644 src/db/schema/complaints.model.ts create mode 100644 src/db/schema/status.schema.ts create mode 100644 src/db/schema/submission-reason.schema.ts create mode 100644 src/db/seeds/status.seed.ts create mode 100644 src/db/seeds/submission-reason.seed.ts create mode 100644 src/routes/status.route.ts create mode 100644 src/routes/submission-reason.route.ts create mode 100644 src/services/status.service.ts create mode 100644 src/services/submission-reason.service.ts diff --git a/src/db/migrations/0000_noisy_metal_master.sql b/src/db/migrations/0000_noisy_metal_master.sql index 2b74924..d310649 100644 --- a/src/db/migrations/0000_noisy_metal_master.sql +++ b/src/db/migrations/0000_noisy_metal_master.sql @@ -51,9 +51,6 @@ CREATE TABLE IF NOT EXISTS "stats_resources" ( CONSTRAINT "stats_resources_id_unique" UNIQUE("id") ); -CREATE TYPE status AS ENUM ('pending', 'approved', 'rejected'); -CREATE TYPE reasons AS ENUM ('reason1', 'reason2', 'reason3', 'reason4'); - --> statement-breakpoint CREATE TABLE IF NOT EXISTS "submission" ( "id" serial PRIMARY KEY NOT NULL, diff --git a/src/db/repo/status.repo.ts b/src/db/repo/status.repo.ts new file mode 100644 index 0000000..7780bb1 --- /dev/null +++ b/src/db/repo/status.repo.ts @@ -0,0 +1,50 @@ +import { Service } from "typedi"; +import type { StatusInput, StatusModel, StatusUpdate } from "../schema/status.schema"; +import db from ".."; +import statusTable, { statusSchema } from "../schema/status.schema"; +import { eq } from "drizzle-orm"; + +@Service() +export class StatusRepo { + async create(status: StatusInput): Promise<StatusModel> { + const [ret] = await db + .insert(statusTable) + .values(status) + .returning() + + return statusSchema.statusModelSchema.parse(ret) + } + + async update(status: StatusUpdate): Promise<StatusModel> { + const [ret] = await db + .update(statusTable) + .set(status) + .where(eq(statusTable.id, status.id)) + .returning() + + return statusSchema.statusModelSchema.parse(ret) + } + + async delete(id: StatusModel['id']): Promise<StatusModel> { + const [ret] = await db + .delete(statusTable) + .where(eq(statusTable.id, id)) + .returning() + + return statusSchema.statusModelSchema.parse(ret) + } + + async find(id: StatusModel['id']): Promise<StatusModel | undefined> { + const status = await db.query.statsResourcesTable.findFirst({ + where: eq(statusTable.id, id), + }) + + return status ? statusSchema.statusModelSchema.parse(status) : undefined + } + + async findMany(): Promise<StatusModel[]> { + return statusSchema.statusModelSchema + .array() + .parse(await db.query.statusTable.findMany()) + } +} \ No newline at end of file diff --git a/src/db/repo/submission-reason.repo.ts b/src/db/repo/submission-reason.repo.ts new file mode 100644 index 0000000..f933c95 --- /dev/null +++ b/src/db/repo/submission-reason.repo.ts @@ -0,0 +1,51 @@ +import { Service } from "typedi"; +import type { SubmissionReasonInput, SubmissionReasonModel, SubmissionReasonUpdate } from "../schema/submission-reason.schema"; +import db from ".."; +import { submissionReasonSchema } from "../schema/submission-reason.schema"; +import { eq } from "drizzle-orm"; +import submissionReasonTable from "../schema/submission-reason.schema"; + +@Service() +export class SubmissionReasonRepo { + async create(submissionReason: SubmissionReasonInput): Promise<SubmissionReasonModel> { + const [ret] = await db + .insert(submissionReasonTable) + .values(submissionReason) + .returning() + + return submissionReasonSchema.submissionReasonModelSchema.parse(ret) + } + + async update(submissionReason: SubmissionReasonUpdate): Promise<SubmissionReasonModel> { + const [ret] = await db + .update(submissionReasonTable) + .set(submissionReason) + .where(eq(submissionReasonTable.id, submissionReason.id)) + .returning() + + return submissionReasonSchema.submissionReasonModelSchema.parse(ret) + } + + async delete(id: SubmissionReasonModel['id']): Promise<SubmissionReasonModel> { + const [ret] = await db + .delete(submissionReasonTable) + .where(eq(submissionReasonTable.id, id)) + .returning() + + return submissionReasonSchema.submissionReasonModelSchema.parse(ret) + } + + async find(id: SubmissionReasonModel['id']): Promise<SubmissionReasonModel | undefined> { + const submissionReason = await db.query.submissionReasonTable.findFirst({ + where: eq(submissionReasonTable.id, id), + }) + + return submissionReason ? submissionReasonSchema.submissionReasonModelSchema.parse(submissionReason) : undefined + } + + async findMany(): Promise<SubmissionReasonModel[]> { + return submissionReasonSchema.submissionReasonModelSchema + .array() + .parse(await db.query.submissionReasonTable.findMany()) + } +} \ No newline at end of file diff --git a/src/db/schema/complaints.model.ts b/src/db/schema/complaints.model.ts new file mode 100644 index 0000000..99bdb7e --- /dev/null +++ b/src/db/schema/complaints.model.ts @@ -0,0 +1,10 @@ +import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; + +const complaintTable = pgTable('complaint', { + id: serial('id').primaryKey().notNull(), + description: text('description'), + // complainable_type + // complaint_reason + evaluated_at: timestamp('evaluated_at', { mode: 'string'}), + created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), +}) \ No newline at end of file diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index 20548b4..51e2086 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -6,6 +6,8 @@ import collectionStatsTable from './collection-stats.model' import collectionTable from './collections.model' import subjectsTable from './subjects.schema' import submissionTable from './submission.model' +import statusTable from './status.schema' +import submissionReasonTable from './submission-reason.schema' export { userTable, @@ -15,7 +17,9 @@ export { statsResourcesTable, collectionStatsTable, subjectsTable, - submissionTable + submissionTable, + statusTable, + submissionReasonTable, } export const tables = [ @@ -26,7 +30,9 @@ export const tables = [ collectionTable, collectionStatsTable, subjectsTable, - submissionTable + submissionTable, + statusTable, + submissionReasonTable, ] diff --git a/src/db/schema/status.schema.ts b/src/db/schema/status.schema.ts new file mode 100644 index 0000000..0933e93 --- /dev/null +++ b/src/db/schema/status.schema.ts @@ -0,0 +1,27 @@ +import { pgTable, serial, varchar } from "drizzle-orm/pg-core"; +import { createInsertSchema, createSelectSchema } from "drizzle-zod"; +import type { z } from "zod"; + +const statusTable = pgTable('status', { + id: serial('id').primaryKey().notNull(), + name: varchar('name').notNull().unique(), +}) + +const statusModelSchema = createSelectSchema(statusTable) +const statusDtoSchema = statusModelSchema +const statusInputSchema = createInsertSchema(statusTable) +const statusUpdateSchema = statusInputSchema.partial().required({ id: true }) + +export type StatusModel = z.infer<typeof statusModelSchema> +export type StatusDto = z.infer<typeof statusDtoSchema> +export type StatusInput = z.infer<typeof statusInputSchema> +export type StatusUpdate = z.infer<typeof statusUpdateSchema> + +export const statusSchema = { + statusModelSchema, + statusDtoSchema, + statusInputSchema, + statusUpdateSchema, +} + +export default statusTable \ No newline at end of file diff --git a/src/db/schema/submission-reason.schema.ts b/src/db/schema/submission-reason.schema.ts new file mode 100644 index 0000000..555a35f --- /dev/null +++ b/src/db/schema/submission-reason.schema.ts @@ -0,0 +1,27 @@ +import { pgTable, serial, varchar } from "drizzle-orm/pg-core"; +import { createInsertSchema, createSelectSchema } from "drizzle-zod"; +import type { z } from "zod"; + +const submissionReasonTable = pgTable('submissionReason', { + id: serial('id').primaryKey().notNull(), + name: varchar('name').notNull().unique(), +}) + +const submissionReasonModelSchema = createSelectSchema(submissionReasonTable) +const submissionReasonDtoSchema = submissionReasonModelSchema +const submissionReasonInputSchema = createInsertSchema(submissionReasonTable) +const submissionReasonUpdateSchema = submissionReasonModelSchema.partial().required({ id: true }) + +export type SubmissionReasonModel = z.infer<typeof submissionReasonModelSchema> +export type SubmissionReasonDto = z.infer<typeof submissionReasonDtoSchema> +export type SubmissionReasonInput = z.infer<typeof submissionReasonInputSchema> +export type SubmissionReasonUpdate = z.infer<typeof submissionReasonUpdateSchema> + +export const submissionReasonSchema = { + submissionReasonModelSchema, + submissionReasonDtoSchema, + submissionReasonInputSchema, + submissionReasonUpdateSchema, +} + +export default submissionReasonTable diff --git a/src/db/schema/submission.model.ts b/src/db/schema/submission.model.ts index fd86cdf..fbcd0d9 100644 --- a/src/db/schema/submission.model.ts +++ b/src/db/schema/submission.model.ts @@ -1,16 +1,10 @@ -import { pgEnum, pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; +import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; import { createInsertSchema, createSelectSchema } from "drizzle-zod"; import type { z } from "zod"; -const statusEnum = pgEnum('status', ['pending', 'approved', 'rejected']) -// as razões são sobre o que o usuário quer reportar -const reasonsEnum = pgEnum('reason', ['reason1', 'reason2', 'reason3', 'reason4']) - const submissionTable = pgTable('submission', { id: serial('id').primaryKey().notNull(), - status: statusEnum('status').default('pending'), justification: text('justification'), - reason: reasonsEnum('reason').default('reason4'), answered_at: timestamp('answered_at', { mode: 'string'}), created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), }) diff --git a/src/db/seed.ts b/src/db/seed.ts index 7e6d973..cef4ecf 100644 --- a/src/db/seed.ts +++ b/src/db/seed.ts @@ -29,5 +29,7 @@ await seeds.collectionSeed(db) await seeds.collectionStatsSeed(db) await seeds.subjectsData(db) await seeds.submissionSeed(db) +await seeds.statusSeed(db) +await seeds.reasonsSeed(db) await connection.end() diff --git a/src/db/seeds/index.ts b/src/db/seeds/index.ts index 4c28bd4..b77b271 100644 --- a/src/db/seeds/index.ts +++ b/src/db/seeds/index.ts @@ -6,3 +6,5 @@ export { default as collectionSeed } from './collections.seed' export { default as collectionStatsSeed } from './collection-stats.seed' export { default as subjectsData } from './subjects.seed' export { default as submissionSeed } from './submission.seed' +export { default as statusSeed } from './status.seed' +export { default as reasonsSeed } from './submission-reason.seed' diff --git a/src/db/seeds/status.seed.ts b/src/db/seeds/status.seed.ts new file mode 100644 index 0000000..e6a1f36 --- /dev/null +++ b/src/db/seeds/status.seed.ts @@ -0,0 +1,19 @@ +import type db from ".."; +import type { StatusInput } from "../schema/status.schema"; +import statusTable from "../schema/status.schema"; + +export default async function seed(db: db) { + await db.insert(statusTable).values(statusData) +} + +const statusData: StatusInput[] = [ + { + name: 'Pending', + }, + { + name: 'Approved', + }, + { + name: 'Rejected', + }, +] \ No newline at end of file diff --git a/src/db/seeds/submission-reason.seed.ts b/src/db/seeds/submission-reason.seed.ts new file mode 100644 index 0000000..69ee770 --- /dev/null +++ b/src/db/seeds/submission-reason.seed.ts @@ -0,0 +1,19 @@ +import type db from ".."; +import { reasonsTable } from "../schema"; +import type { ReasonsInput } from "../schema/submission-reason.schema"; + +export default async function seed(db: db) { + await db.insert(reasonsTable).values(reasonsData) +} + +const reasonsData : ReasonsInput[] = [ + { + name: 'Reason 1', + }, + { + name: 'Reason 2', + }, + { + name: 'Reason 3', + }, +] \ No newline at end of file diff --git a/src/db/seeds/submission.seed.ts b/src/db/seeds/submission.seed.ts index aa155f4..8e49702 100644 --- a/src/db/seeds/submission.seed.ts +++ b/src/db/seeds/submission.seed.ts @@ -8,23 +8,15 @@ export default async function seed(db: db) { const submissionData: SubmissionInput[] = [ { - status: 'pending', justification: ' ', - reason: 'reason1', }, { - status: 'pending', justification: ' ', - reason: 'reason2', }, { - status: 'pending', justification: ' ', - reason: 'reason3', }, { - status: 'pending', justification: ' ', - reason: 'reason4', } ] \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 49b12a9..6c776cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,8 @@ import { uploaderRouter } from './routes/uploader.route' import { collectionsStatsRouter, getCollectionsStats } from './routes/collection-stats.route' import { publicSubjectsRouter, subjectsRouter } from './routes/subjects.route' import { submissionRouter } from './routes/submission.route' +import { statusRouter } from './routes/status.route' +import { reasonsRouter } from './routes/submission-reason.route' const app = new Hono() @@ -74,6 +76,8 @@ app .route('/collection', collectionsRouter) .route('/collection-stats', collectionsStatsRouter) .route('/submission', submissionRouter) + .route('/status', statusRouter) + .route('/reason', reasonsRouter) export default app export type AppType = typeof app diff --git a/src/routes/status.route.ts b/src/routes/status.route.ts new file mode 100644 index 0000000..87470ce --- /dev/null +++ b/src/routes/status.route.ts @@ -0,0 +1,134 @@ +import { StatusService } from "@/services/status.service"; +import Container from "typedi"; +import { honoWithJwt } from ".."; +import { zValidator } from "@hono/zod-validator"; +import { statusSchema } from "@/db/schema/status.schema"; +import { createApexError, HttpStatus } from "@/services/error.service"; + +const service = Container.get(StatusService); + +export const statusRouter = honoWithJwt() + .post( + '/create', + zValidator('json', statusSchema.statusInputSchema), + async (c) => { + try { + const input = await c.req.valid('json') + + const status = statusSchema.statusDtoSchema.parse( + await service.create(input) + ) + + return c.json({ status }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not create status', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .post( + '/update', + zValidator('json', statusSchema.statusUpdateSchema), + async (c) => { + try { + const input = await c.req.valid('json') + + const status = statusSchema.statusDtoSchema.parse( + await service.update(input) + ) + + return c.json({ status }) + } catch (e) { + console.log(e) + + return c.json( + createApexError({ + status: 'error', + message: 'could not update status', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .post( + '/delete/:id', async (c) => { + try { + const id = +c.req.param('id') + + const status = statusSchema.statusDtoSchema.parse( + await service.delete(id) + ) + + return c.json({ status }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not delete status', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .get( + '/find/:id', async (c) => { + try { + const id = +c.req.param('id') + + const status = statusSchema.statusDtoSchema.parse( + await service.find(id) + ) + + return c.json({ status }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not find status', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.NOT_FOUND + ) + } + } + ) + .get( + '/get-all', async (c) => { + try { + const status = statusSchema.statusDtoSchema.array().parse( + await service.findMany() + ) + + return c.json({ status }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not find statuses', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.NOT_FOUND + ) + } + } + ) \ No newline at end of file diff --git a/src/routes/submission-reason.route.ts b/src/routes/submission-reason.route.ts new file mode 100644 index 0000000..ce496d0 --- /dev/null +++ b/src/routes/submission-reason.route.ts @@ -0,0 +1,134 @@ +import { ReasonsService } from "@/services/submission-reason.service"; +import Container from "typedi"; +import { honoWithJwt } from ".."; +import { zValidator } from "@hono/zod-validator"; +import { submissionReasonSchema } from "@/db/schema/submission-reason.schema"; +import { createApexError, HttpStatus } from "@/services/error.service"; + +const service = Container.get(ReasonsService); + +export const reasonsRouter = honoWithJwt() + .post( + '/create', + zValidator('json', submissionReasonSchema.submissionReasonInputSchema), + async (c) => { + try { + const input = await c.req.valid('json') + + const submissionReason = submissionReasonSchema.submissionReasonDtoSchema.parse( + await service.create(input) + ) + + return c.json({ submissionReason }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not create reason', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .post( + '/update', + zValidator('json', submissionReasonSchema.submissionReasonUpdateSchema), + async (c) => { + try { + const input = await c.req.valid('json') + + const submissionReason = submissionReasonSchema.submissionReasonDtoSchema.parse( + await service.update(input) + ) + + return c.json({ submissionReason }) + } catch (e) { + console.log(e) + + return c.json( + createApexError({ + status: 'error', + message: 'could not update reason', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .post( + '/delete/:id', async (c) => { + try { + const id = +c.req.param('id') + + const submissionReason = submissionReasonSchema.submissionReasonDtoSchema.parse( + await service.delete(id) + ) + + return c.json({ submissionReason }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not delete reason', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.BAD_REQUEST + ) + } + } + ) + .get( + '/find/:id', async (c) => { + try { + const id = +c.req.param('id') + + const submissionReason = submissionReasonSchema.submissionReasonDtoSchema.parse( + await service.find(id) + ) + + return c.json({ submissionReason }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not find reason', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.NOT_FOUND + ) + } + } + ) + .get( + '/get-all', async (c) => { + try { + const submissionReason = submissionReasonSchema.submissionReasonDtoSchema.array().parse( + await service.findMany() + ) + + return c.json({ submissionReason }) + } catch (e) { + return c.json( + createApexError({ + status: 'error', + message: 'could not find reasons', + code: HttpStatus.BAD_REQUEST, + path: c.req.routePath, + suggestion: 'check the input and try again', + }), + HttpStatus.NOT_FOUND + ) + } + } + ) diff --git a/src/services/status.service.ts b/src/services/status.service.ts new file mode 100644 index 0000000..b297034 --- /dev/null +++ b/src/services/status.service.ts @@ -0,0 +1,29 @@ +import type { StatusRepo } from "@/db/repo/status.repo"; +import type { StatusInput, StatusModel, StatusUpdate } from "@/db/schema/status.schema"; +import { Inject, Service } from "typedi"; + +@Service() +export class StatusService { + @Inject() + private readonly repo: StatusRepo + + async create(status: StatusInput): Promise<StatusInput> { + return this.repo.create(status) + } + + async update(status: StatusUpdate): Promise<StatusInput> { + return this.repo.update(status) + } + + async delete(id: StatusModel['id']): Promise<StatusInput> { + return this.repo.delete(id) + } + + async find(id: StatusModel['id']): Promise<StatusModel | undefined> { + return this.repo.find(id) + } + + async findMany(): Promise<StatusModel[]> { + return this.repo.findMany() + } +} \ No newline at end of file diff --git a/src/services/submission-reason.service.ts b/src/services/submission-reason.service.ts new file mode 100644 index 0000000..2084fad --- /dev/null +++ b/src/services/submission-reason.service.ts @@ -0,0 +1,29 @@ +import type { SubmissionReasonRepo } from "@/db/repo/submission-reason.repo"; +import type { SubmissionReasonInput, SubmissionReasonModel, SubmissionReasonUpdate } from "@/db/schema/submission-reason.schema"; +import { Inject, Service } from "typedi"; + +@Service() +export class ReasonsService { + @Inject() + private readonly repo: SubmissionReasonRepo + + async create(reason: SubmissionReasonInput): Promise<SubmissionReasonInput> { + return this.repo.create(reason) + } + + async update(reason: SubmissionReasonUpdate): Promise<SubmissionReasonInput> { + return this.repo.update(reason) + } + + async delete(id: SubmissionReasonModel['id']): Promise<SubmissionReasonInput> { + return this.repo.delete(id) + } + + async find(id: SubmissionReasonModel['id']): Promise<SubmissionReasonModel | undefined> { + return this.repo.find(id) + } + + async findMany(): Promise<SubmissionReasonModel[]> { + return this.repo.findMany() + } +} \ No newline at end of file -- GitLab