add server to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 11:57:50 +02:00
parent 28e309981b
commit 80b97b5fdc
1303 changed files with 137049 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator';
import { Service, Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseController from '@/api/controllers/BaseController';
import { AbilitySubject, IProjectStatus, ProjectAction } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ProjectsApplication } from '@/services/Projects/Projects/ProjectsApplication';
@Service()
export class ProjectsController extends BaseController {
@Inject()
private projectsApplication: ProjectsApplication;
/**
* Router constructor method.
*/
router() {
const router = Router();
router.post(
'/',
CheckPolicies(ProjectAction.CREATE, AbilitySubject.Project),
[
check('contact_id').exists(),
check('name').exists().trim(),
check('deadline').exists().isISO8601(),
check('cost_estimate').exists().isDecimal(),
],
this.validationResult,
asyncMiddleware(this.createProject.bind(this)),
this.catchServiceErrors
);
router.post(
'/:id',
CheckPolicies(ProjectAction.EDIT, AbilitySubject.Project),
[
param('id').exists().isInt().toInt(),
check('contact_id').exists(),
check('name').exists().trim(),
check('deadline').exists().isISO8601(),
check('cost_estimate').exists().isDecimal(),
],
this.validationResult,
asyncMiddleware(this.editProject.bind(this)),
this.catchServiceErrors
);
router.patch(
'/:projectId/status',
CheckPolicies(ProjectAction.EDIT, AbilitySubject.Project),
[
param('projectId').exists().isInt().toInt(),
check('status')
.exists()
.isIn([IProjectStatus.InProgress, IProjectStatus.Closed]),
],
this.validationResult,
asyncMiddleware(this.editProject.bind(this)),
this.catchServiceErrors
);
router.get(
'/:id',
CheckPolicies(ProjectAction.VIEW, AbilitySubject.Project),
[param('id').exists().isInt().toInt()],
this.validationResult,
asyncMiddleware(this.getProject.bind(this)),
this.catchServiceErrors
);
router.get(
'/:projectId/billable/entries',
CheckPolicies(ProjectAction.VIEW, AbilitySubject.Project),
[
param('projectId').exists().isInt().toInt(),
query('billable_type').optional().toArray(),
query('to_date').optional().isISO8601(),
],
this.validationResult,
asyncMiddleware(this.projectBillableEntries.bind(this)),
this.catchServiceErrors
);
router.get(
'/',
CheckPolicies(ProjectAction.VIEW, AbilitySubject.Project),
[],
this.validationResult,
asyncMiddleware(this.getProjects.bind(this)),
this.catchServiceErrors
);
router.delete(
'/:id',
CheckPolicies(ProjectAction.DELETE, AbilitySubject.Project),
[param('id').exists().isInt().toInt()],
this.validationResult,
asyncMiddleware(this.deleteProject.bind(this)),
this.catchServiceErrors
);
return router;
}
/**
* Creates a new project.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
private async createProject(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const projectDTO = this.matchedBodyData(req);
try {
const account = await this.projectsApplication.createProject(
tenantId,
projectDTO
);
return res.status(200).send({
id: account.id,
message: 'The project has been created successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Edit project details.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
private async editProject(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { projectId } = req.params;
const editProjectDTO = this.matchedBodyData(req);
try {
const account = await this.projectsApplication.editProjectStatus(
tenantId,
projectId,
editProjectDTO.status
);
return res.status(200).send({
id: account.id,
message: 'The project has been edited successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Get details of the given account.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
private async getProject(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { id: projectId } = req.params;
try {
const project = await this.projectsApplication.getProject(
tenantId,
projectId
);
return res.status(200).send({ project });
} catch (error) {
next(error);
}
}
/**
* Delete the given account.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
private async deleteProject(req: Request, res: Response, next: NextFunction) {
const { id: accountId } = req.params;
const { tenantId } = req;
try {
await this.projectsApplication.deleteProject(tenantId, accountId);
return res.status(200).send({
id: accountId,
message: 'The deleted project has been deleted successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Retrieve accounts datatable list.
* @param {Request} req
* @param {Response} res
* @param {Response}
*/
private async getProjects(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
// Filter query.
const filter = {
sortOrder: 'desc',
columnSortBy: 'created_at',
inactiveMode: false,
...this.matchedQueryData(req),
};
try {
const projects = await this.projectsApplication.getProjects(
tenantId,
filter
);
return res.status(200).send({
projects,
});
} catch (error) {
next(error);
}
}
/**
* Retrieves the given billable entries of the given project.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
* @returns {Response}
*/
private projectBillableEntries = async (
req: Request,
res: Response,
next: NextFunction
) => {
const { tenantId } = req;
const { projectId } = req.params;
const query = this.matchedQueryData(req);
try {
const billableEntries =
await this.projectsApplication.getProjectBillableEntries(
tenantId,
projectId,
query
);
return res.status(200).send({
billableEntries,
});
} catch (error) {
next(error);
}
};
/**
* Transforms service errors to response.
* @param {Error}
* @param {Request} req
* @param {Response} res
* @param {ServiceError} error
*/
private catchServiceErrors(
error,
req: Request,
res: Response,
next: NextFunction
) {
if (error instanceof ServiceError) {
}
next(error);
}
}

View File

@@ -0,0 +1,211 @@
import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator';
import { Service, Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseController from '@/api/controllers/BaseController';
import { AbilitySubject, AccountAction } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { TasksApplication } from '@/services/Projects/Tasks/TasksApplication';
import { ProjectTaskChargeType } from '@/services/Projects/Tasks/constants';
@Service()
export class ProjectTasksController extends BaseController {
@Inject()
private tasksApplication: TasksApplication;
/**
* Router constructor method.
*/
router() {
const router = Router();
router.post(
'/projects/:projectId/tasks',
CheckPolicies(AccountAction.CREATE, AbilitySubject.Project),
[
check('name').exists(),
check('charge_type')
.exists()
.trim()
.toUpperCase()
.isIn(Object.values(ProjectTaskChargeType)),
check('rate').exists(),
check('estimate_hours').exists(),
],
this.validationResult,
asyncMiddleware(this.createTask.bind(this)),
this.catchServiceErrors
);
router.post(
'/tasks/:taskId',
CheckPolicies(AccountAction.EDIT, AbilitySubject.Project),
[
param('taskId').exists().isInt().toInt(),
check('name').exists(),
check('charge_type').exists().trim(),
check('rate').exists(),
check('estimate_hours').exists(),
],
this.validationResult,
asyncMiddleware(this.editTask.bind(this)),
this.catchServiceErrors
);
router.get(
'/tasks/:taskId',
CheckPolicies(AccountAction.VIEW, AbilitySubject.Project),
[param('taskId').exists().isInt().toInt()],
this.validationResult,
asyncMiddleware(this.getTask.bind(this)),
this.catchServiceErrors
);
router.get(
'/projects/:projectId/tasks',
CheckPolicies(AccountAction.VIEW, AbilitySubject.Project),
[param('projectId').exists().isInt().toInt()],
this.validationResult,
asyncMiddleware(this.getTasks.bind(this)),
this.catchServiceErrors
);
router.delete(
'/tasks/:taskId',
CheckPolicies(AccountAction.DELETE, AbilitySubject.Project),
[param('taskId').exists().isInt().toInt()],
this.validationResult,
asyncMiddleware(this.deleteTask.bind(this)),
this.catchServiceErrors
);
return router;
}
/**
* Creates a new project.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
async createTask(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { projectId } = req.params;
const taskDTO = this.matchedBodyData(req);
try {
const task = await this.tasksApplication.createTask(
tenantId,
projectId,
taskDTO
);
return res.status(200).send({
id: task.id,
message: 'The task has been created successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Edit project details.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async editTask(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { taskId } = req.params;
const editTaskDTO = this.matchedBodyData(req);
try {
const task = await this.tasksApplication.editTask(
tenantId,
taskId,
editTaskDTO
);
return res.status(200).send({
id: task.id,
message: 'The task has been edited successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Get details of the given task.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async getTask(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { taskId } = req.params;
try {
const task = await this.tasksApplication.getTask(tenantId, taskId);
return res.status(200).send({ task });
} catch (error) {
next(error);
}
}
/**
* Delete the given task.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async deleteTask(req: Request, res: Response, next: NextFunction) {
const { taskId } = req.params;
const { tenantId } = req;
try {
await this.tasksApplication.deleteTask(tenantId, taskId);
return res.status(200).send({
id: taskId,
message: 'The deleted task has been deleted successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Retrieve accounts datatable list.
* @param {Request} req
* @param {Response} res
* @param {Response}
*/
public async getTasks(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { projectId } = req.params;
try {
const tasks = await this.tasksApplication.getTasks(tenantId, projectId);
return res.status(200).send({ tasks });
} catch (error) {
next(error);
}
}
/**
* Transforms service errors to response.
* @param {Error}
* @param {Request} req
* @param {Response} res
* @param {ServiceError} error
*/
private catchServiceErrors(
error,
req: Request,
res: Response,
next: NextFunction
) {
if (error instanceof ServiceError) {
}
next(error);
}
}

View File

@@ -0,0 +1,253 @@
import { Router, Request, Response, NextFunction } from 'express';
import { check, param, query } from 'express-validator';
import { Service, Inject } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseController from '@/api/controllers/BaseController';
import { AbilitySubject, AccountAction } from '@/interfaces';
import { ServiceError } from '@/exceptions';
import CheckPolicies from '@/api/middleware/CheckPolicies';
import { TimesApplication } from '@/services/Projects/Times/TimesApplication';
@Service()
export class ProjectTimesController extends BaseController {
@Inject()
private timesApplication: TimesApplication;
/**
* Router constructor method.
*/
router() {
const router = Router();
router.post(
'/projects/tasks/:taskId/times',
CheckPolicies(AccountAction.CREATE, AbilitySubject.Project),
[
param('taskId').exists().isInt().toInt(),
check('duration').exists().isDecimal(),
check('description').exists().trim(),
check('date').exists().isISO8601(),
],
this.validationResult,
asyncMiddleware(this.createTime.bind(this)),
this.catchServiceErrors
);
router.post(
'/projects/times/:timeId',
CheckPolicies(AccountAction.EDIT, AbilitySubject.Project),
[
param('timeId').exists().isInt().toInt(),
check('duration').exists().isDecimal(),
check('description').exists().trim(),
check('date').exists().isISO8601(),
],
this.validationResult,
asyncMiddleware(this.editTime.bind(this)),
this.catchServiceErrors
);
router.get(
'/projects/times/:timeId',
CheckPolicies(AccountAction.VIEW, AbilitySubject.Project),
[
param('timeId').exists().isInt().toInt(),
],
this.validationResult,
asyncMiddleware(this.getTime.bind(this)),
this.catchServiceErrors
);
router.get(
'/projects/:projectId/times',
CheckPolicies(AccountAction.VIEW, AbilitySubject.Project),
[
param('projectId').exists().isInt().toInt(),
],
this.validationResult,
asyncMiddleware(this.getTimeline.bind(this)),
this.catchServiceErrors
);
router.delete(
'/projects/times/:timeId',
CheckPolicies(AccountAction.DELETE, AbilitySubject.Project),
[
param('timeId').exists().isInt().toInt(),
],
this.validationResult,
asyncMiddleware(this.deleteTime.bind(this)),
this.catchServiceErrors
);
return router;
}
/**
* Project create DTO Schema validation.
*/
get createTimeDTOSchema() {
return [];
}
/**
* Project edit DTO Schema validation.
*/
get editProjectDTOSchema() {
return [
check('contact_id').exists(),
check('name').exists().trim(),
check('deadline').exists({ nullable: true }).isISO8601(),
check('cost_estimate').exists().isDecimal(),
];
}
get accountParamSchema() {
return [param('id').exists().isNumeric().toInt()];
}
/**
* Accounts list validation schema.
*/
get accountsListSchema() {
return [
query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(),
query('sort_order').optional().isIn(['desc', 'asc']),
query('inactive_mode').optional().isBoolean().toBoolean(),
query('search_keyword').optional({ nullable: true }).isString().trim(),
];
}
/**
* Creates a new project.
* @param {Request} req -
* @param {Response} res -
* @param {NextFunction} next -
*/
async createTime(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { taskId } = req.params;
const taskDTO = this.matchedBodyData(req);
try {
const task = await this.timesApplication.createTime(
tenantId,
taskId,
taskDTO
);
return res.status(200).send({
id: task.id,
message: 'The time entry has been created successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Edit project details.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async editTime(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { timeId } = req.params;
const editTaskDTO = this.matchedBodyData(req);
try {
const task = await this.timesApplication.editTime(
tenantId,
timeId,
editTaskDTO
);
return res.status(200).send({
id: task.id,
message: 'The task has been edited successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Get details of the given task.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async getTime(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { timeId } = req.params;
try {
const timeEntry = await this.timesApplication.getTime(tenantId, timeId);
return res.status(200).send({ timeEntry });
} catch (error) {
next(error);
}
}
/**
* Delete the given task.
* @param {Request} req
* @param {Response} res
* @return {Response}
*/
async deleteTime(req: Request, res: Response, next: NextFunction) {
const { timeId } = req.params;
const { tenantId } = req;
try {
await this.timesApplication.deleteTime(tenantId, timeId);
return res.status(200).send({
id: timeId,
message: 'The deleted task has been deleted successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Retrieve accounts datatable list.
* @param {Request} req
* @param {Response} res
* @param {Response}
*/
public async getTimeline(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { projectId } = req.params;
try {
const timeline = await this.timesApplication.getTimeline(
tenantId,
projectId
);
return res.status(200).send({ timeline });
} catch (error) {
next(error);
}
}
/**
* Transforms service errors to response.
* @param {Error}
* @param {Request} req
* @param {Response} res
* @param {ServiceError} error
*/
private catchServiceErrors(
error,
req: Request,
res: Response,
next: NextFunction
) {
if (error instanceof ServiceError) {
}
next(error);
}
}