diff --git a/src/modules/forms/jobInfo/controller/jobInfo.controller.ts b/src/modules/forms/jobInfo/controller/jobInfo.controller.ts new file mode 100644 index 0000000..dab7543 --- /dev/null +++ b/src/modules/forms/jobInfo/controller/jobInfo.controller.ts @@ -0,0 +1,76 @@ +// src/modules/job-info/controller/job-info.controller.ts +import { Request, Response, NextFunction } from "express"; +import { JobInfoPayload } from "../types/index.type"; +import { Controller } from "../../../../core/controller/main.controller"; +import JobInfoService from "../service/jobInfo.service"; + + + + +class JobInfoControllerClass extends Controller { + #service; + constructor(){ + super(); + this.#service = JobInfoService + } + async upsert(req: any, res: Response, next: NextFunction) { + try { + const applicantId = req.user.id; + const data = await this.#service.upsert(applicantId, req.body); + + return res.status(200).json({ + status: 200, + message: "اطلاعات وضعیت شغلی با موفقیت ذخیره شد", + data, + }); + } catch (error) { + next(error); + } + } + + async getMy(req: any, res: Response, next: NextFunction) { + try { + const applicantId = req.user.id; + const data = await this.#service.getMy(applicantId); + + return res.status(200).json({ + status: 200, + data, + }); + } catch (error) { + next(error); + } + } + + async getByApplicantId(req: any, res: Response, next: NextFunction) { + try { + const { applicantId } = req.params; + const data = await this.#service.getByApplicantId(applicantId); + + return res.status(200).json({ + status: 200, + data, + }); + } catch (error) { + next(error); + } + } + + async delete(req: any, res: Response, next: NextFunction) { + try { + const applicantId = req.user.id; + await this.#service.delete(applicantId); + + return res.status(200).json({ + status: 200, + message: "اطلاعات وضعیت شغلی با موفقیت حذف شد", + }); + } catch (error) { + next(error); + } + } +} + + +const JobInfoController = new JobInfoControllerClass() +export default JobInfoController; diff --git a/src/modules/forms/jobInfo/service/jobInfo.service.ts b/src/modules/forms/jobInfo/service/jobInfo.service.ts new file mode 100644 index 0000000..c831f9f --- /dev/null +++ b/src/modules/forms/jobInfo/service/jobInfo.service.ts @@ -0,0 +1,56 @@ +import { JobInfo } from "../../../../models/JobInfo"; +import { JobInfoPayload } from "../types/index.type"; + + +class JobInfoServiceClass { + async upsert(applicantId: string, payload: JobInfoPayload) { + const existing = await JobInfo.findOne({where: {applicantId}}); + + const data = { + applicantId, + readyToWorkDate: payload.readyToWorkDate, + isCurrentEmployee: payload.isCurrentEmployee ?? false, + hasPastCooperation: payload.hasPastCooperation ?? false, + isCurrentlyEmployed: payload.isCurrentlyEmployed ?? false, + dualJobInterest: payload.dualJobInterest ?? false, + retirementStatus: payload.retirementStatus ?? "None", + isMilitary: payload.isMilitary ?? false, + hasInsurance: payload.hasInsurance ?? false, + insuranceType: payload.hasInsurance + ? (payload.insuranceType ?? null) + : null, + totalInsuranceYears: payload.hasInsurance + ? (payload.totalInsuranceYears ?? 0) + : 0, + }; + + if (existing) { + await existing.update(data); + return existing; + } + + return await JobInfo.create(data as any); + } + + async getMy(applicantId: string) { + return await JobInfo.findOne({where: {applicantId}}); + } + + async getByApplicantId(applicantId: string) { + return await JobInfo.findOne({where: {applicantId}}); + } + + async delete(applicantId: string) { + const record = await JobInfo.findOne({where: {applicantId}}); + if (!record) { + throw new Error("اطلاعات وضعیت شغلی یافت نشد"); + } + + await record.destroy(); + return true; + } +} + +const JobInfoService = new JobInfoServiceClass(); + +export default JobInfoService; diff --git a/src/modules/forms/jobInfo/types/index.type.ts b/src/modules/forms/jobInfo/types/index.type.ts new file mode 100644 index 0000000..df24c49 --- /dev/null +++ b/src/modules/forms/jobInfo/types/index.type.ts @@ -0,0 +1,13 @@ +export interface JobInfoPayload { + applicantId?: string; // از کلاینت نادیده گرفته می‌شود + readyToWorkDate: string; // چون از req.body می‌آید بهتر است string باشد + isCurrentEmployee?: boolean; + hasPastCooperation?: boolean; + isCurrentlyEmployed?: boolean; + dualJobInterest?: boolean; + retirementStatus?: "None" | "Retired" | "Redeemed"; + isMilitary?: boolean; + hasInsurance?: boolean; + insuranceType?: string | null; + totalInsuranceYears?: number; +} diff --git a/src/modules/permission/controller/permission.controller.ts b/src/modules/permission/controller/permission.controller.ts new file mode 100644 index 0000000..df7442c --- /dev/null +++ b/src/modules/permission/controller/permission.controller.ts @@ -0,0 +1,83 @@ +import {NextFunction} from "express"; +import PermissionService from "../service/permission.service"; +import {Controller} from "../../../core/controller/main.controller"; +import {ServerResponse} from "../../../core/types"; + +class PermissionController extends Controller { + #service; + constructor() { + super(); + this.#service = PermissionService; + } + async create(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await PermissionService.create(req.body); + + return res.status(201).json({ + status: 201, + message: "سطح دسترسی با موفقیت ایجاد شد", + data, + }); + } catch (error) { + next(error); + } + } + + async getAll(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await this.#service.getAll(); + + return res.status(200).json({ + status: 200, + data, + }); + } catch (error) { + next(error); + } + } + + async getById(req: any, res: ServerResponse, next: NextFunction) { + try { + const {id} = req.params; + const data = await this.#service.getById(id); + + return res.status(200).json({ + status: 200, + data, + }); + } catch (error) { + next(error); + } + } + + async update(req: any, res: ServerResponse, next: NextFunction) { + try { + const {id} = req.params; + const data = await this.#service.update(id, req.body); + + return res.status(200).json({ + status: 200, + message: "سطح دسترسی با موفقیت بروزرسانی شد", + data, + }); + } catch (error) { + next(error); + } + } + + async delete(req: any, res: ServerResponse, next: NextFunction) { + try { + const {id} = req.params; + const data = await this.#service.delete(id); + + return res.status(200).json({ + status: 200, + data: {...data}, + }); + } catch (error) { + next(error); + } + } +} + +export default new PermissionController(); diff --git a/src/modules/permission/routes/permission.routes.ts b/src/modules/permission/routes/permission.routes.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/permission/service/permission.service.ts b/src/modules/permission/service/permission.service.ts new file mode 100644 index 0000000..95deb2f --- /dev/null +++ b/src/modules/permission/service/permission.service.ts @@ -0,0 +1,75 @@ +import { Permission } from "../../../models/Permission"; + + +interface CreatePermissionDto { + name: string; +} + +interface UpdatePermissionDto { + name?: string; +} + +class PermissionService { + async create(data: CreatePermissionDto) { + const existingPermission = await Permission.findOne({ + where: { name: data.name }, + }); + + if (existingPermission) { + throw new Error("سطح دسترسی با این نام قبلاً ثبت شده است"); + } + + const permission = await Permission.create({ + name: data.name, + }); + + return permission; + } + + async getAll() { + return await Permission.findAll({ + order: [["createdAt", "DESC"]], + }); + } + + async getById(id: string) { + const permission = await Permission.findByPk(id); + + if (!permission) { + throw new Error("سطح دسترسی مورد نظر یافت نشد"); + } + + return permission; + } + + async update(id: string, data: UpdatePermissionDto) { + const permission = await this.getById(id); + + if (data.name && data.name !== permission.name) { + const existingPermission = await Permission.findOne({ + where: { name: data.name }, + }); + + if (existingPermission) { + throw new Error("سطح دسترسی با این نام قبلاً ثبت شده است"); + } + } + + await permission.update({ + name: data.name ?? permission.name, + }); + + return permission; + } + + async delete(id: string) { + const permission = await this.getById(id); + await permission.destroy(); + + return { + message: "سطح دسترسی با موفقیت حذف شد", + }; + } +} + +export default new PermissionService(); diff --git a/src/modules/role/controller/role.controller.ts b/src/modules/role/controller/role.controller.ts new file mode 100644 index 0000000..7e59e54 --- /dev/null +++ b/src/modules/role/controller/role.controller.ts @@ -0,0 +1,66 @@ +// src/modules/role/controller/role.controller.ts +import {NextFunction} from "express"; +import RoleService from "../service/role.service"; +import {Controller} from "../../../core/controller/main.controller"; +import {ServerResponse} from "../../../core/types"; + +class RoleControllerClass extends Controller { + #service; + constructor() { + super(); + this.#service = RoleService; + } + async create(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await this.#service.create(req.body); + res + .status(201) + .json({status: 201, message: "نقش با موفقیت ایجاد شد", data}); + } catch (error) { + next(error); + } + } + + async getAll(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await this.#service.getAll(); + res.status(200).json({status: 200, data}); + } catch (error) { + next(error); + } + } + + async getById(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await this.#service.getById(req.params.id); + res.status(200).json({status: 200, data}); + } catch (error) { + next(error); + } + } + + async update(req: any, res: ServerResponse, next: NextFunction) { + try { + const data = await this.#service.update(req.params.id, req.body); + res + .status(200) + .json({status: 200, message: "نقش با موفقیت بروزرسانی شد", data}); + } catch (error) { + next(error); + } + } + + async delete(req: any, res: ServerResponse, next: NextFunction) { + try { + const id = req?.params?.id; + await this.#service.delete(id); + res.status(200).json({status: 200,data:{}, message: "نقش با موفقیت حذف شد"}); + } catch (error) { + next(error); + } + } +} + +const RoleController = new RoleControllerClass(); + +export default RoleController; diff --git a/src/modules/role/routes/role.routes.ts b/src/modules/role/routes/role.routes.ts new file mode 100644 index 0000000..d9cebf6 --- /dev/null +++ b/src/modules/role/routes/role.routes.ts @@ -0,0 +1,14 @@ +// src/modules/role/role.routes.ts +import {Router} from "express"; +import RoleController from "../controller/role.controller"; + +const roleRouter = Router(); + +// پیشنهاد می‌شود این مسیرها فقط برای ادمین در دسترس باشند +roleRouter.post("/", RoleController.create); +roleRouter.get("/", RoleController.getAll); +roleRouter.get("/:id", RoleController.getById); +roleRouter.put("/:id", RoleController.update); +roleRouter.delete("/:id", RoleController.delete); + +export default roleRouter; diff --git a/src/modules/role/service/role.service.ts b/src/modules/role/service/role.service.ts new file mode 100644 index 0000000..ce4df47 --- /dev/null +++ b/src/modules/role/service/role.service.ts @@ -0,0 +1,35 @@ +import {Role} from "../../../models/Role"; + +class RoleServiceClass { + async create(data: {name: string; description?: string}) { + return await Role.create(data); + } + + async getAll() { + return await Role.findAll({order: [["createdAt", "DESC"]]}); + } + + async getById(id: string) { + const role = await Role.findByPk(id); + if (!role) throw new Error("نقش مورد نظر یافت نشد"); + return role; + } + + async update(id: string, data: {name?: string; description?: string}) { + const role = await this.getById(id); + return await role.update(data); + } + + async delete(id: string) { + const role = await this.getById(id); + await role.destroy(); + return true; + } + + // متد کمکی برای چک کردن وجود نقش (مثلاً در زمان ثبت‌نام) + async getByName(name: string) { + return await Role.findOne({where: {name}}); + } +} +const RoleService = new RoleServiceClass(); +export default RoleService;