mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
feat: retrieve default resource views.
This commit is contained in:
@@ -8,216 +8,68 @@ import { IViewDTO, IViewEditDTO } from 'interfaces';
|
||||
import { ServiceError } from 'exceptions';
|
||||
|
||||
@Service()
|
||||
export default class ViewsController extends BaseController{
|
||||
export default class ViewsController extends BaseController {
|
||||
@Inject()
|
||||
viewsService: ViewsService;
|
||||
|
||||
|
||||
/**
|
||||
* Router constructor.
|
||||
*/
|
||||
router() {
|
||||
const router = Router();
|
||||
|
||||
router.get('/resource/:resource_model', [
|
||||
...this.viewsListSchemaValidation,
|
||||
],
|
||||
router.get(
|
||||
'/resource/:resource_model',
|
||||
[...this.viewsListSchemaValidation],
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.listResourceViews.bind(this)),
|
||||
this.handlerServiceErrors,
|
||||
);
|
||||
router.post('/', [
|
||||
...this.viewDTOSchemaValidation,
|
||||
],
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.createView.bind(this)),
|
||||
this.handlerServiceErrors
|
||||
);
|
||||
router.post('/:id', [
|
||||
...this.viewParamSchemaValidation,
|
||||
...this.viewEditDTOSchemaValidation,
|
||||
],
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.editView.bind(this)),
|
||||
this.handlerServiceErrors,
|
||||
);
|
||||
router.delete('/:id', [
|
||||
...this.viewParamSchemaValidation
|
||||
],
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.deleteView.bind(this)),
|
||||
this.handlerServiceErrors,
|
||||
);
|
||||
router.get('/:id', [
|
||||
...this.viewParamSchemaValidation
|
||||
],
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.getView.bind(this)),
|
||||
this.handlerServiceErrors,
|
||||
);
|
||||
return router;
|
||||
}
|
||||
|
||||
/**
|
||||
* New view DTO schema validation.
|
||||
* Custom views list validation schema.
|
||||
*/
|
||||
get viewDTOSchemaValidation() {
|
||||
return [
|
||||
check('resource_model').exists().escape().trim(),
|
||||
check('name').exists().escape().trim(),
|
||||
check('logic_expression').exists().trim().escape(),
|
||||
|
||||
check('roles').isArray({ min: 1 }),
|
||||
check('roles.*.field_key').exists().escape().trim(),
|
||||
check('roles.*.comparator').exists(),
|
||||
check('roles.*.value').exists(),
|
||||
check('roles.*.index').exists().isNumeric().toInt(),
|
||||
|
||||
check('columns').exists().isArray({ min: 1 }),
|
||||
check('columns.*.field_key').exists().escape().trim(),
|
||||
check('columns.*.index').exists().isNumeric().toInt(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit view DTO schema validation.
|
||||
*/
|
||||
get viewEditDTOSchemaValidation() {
|
||||
return [
|
||||
check('name').exists().escape().trim(),
|
||||
check('logic_expression').exists().trim().escape(),
|
||||
|
||||
check('roles').isArray({ min: 1 }),
|
||||
check('roles.*.field_key').exists().escape().trim(),
|
||||
check('roles.*.comparator').exists(),
|
||||
check('roles.*.value').exists(),
|
||||
check('roles.*.index').exists().isNumeric().toInt(),
|
||||
|
||||
check('columns').exists().isArray({ min: 1 }),
|
||||
check('columns.*.field_key').exists().escape().trim(),
|
||||
check('columns.*.index').exists().isNumeric().toInt(),
|
||||
];
|
||||
}
|
||||
|
||||
get viewParamSchemaValidation() {
|
||||
return [
|
||||
param('id').exists().isNumeric().toInt(),
|
||||
];
|
||||
}
|
||||
|
||||
get viewsListSchemaValidation() {
|
||||
return [
|
||||
param('resource_model').exists().trim().escape(),
|
||||
]
|
||||
return [param('resource_model').exists().trim().escape()];
|
||||
}
|
||||
|
||||
/**
|
||||
* List all views that associated with the given resource.
|
||||
* @param {Request} req -
|
||||
* @param {Response} res -
|
||||
* @param {NextFunction} next -
|
||||
* @param {Request} req -
|
||||
* @param {Response} res -
|
||||
* @param {NextFunction} next -
|
||||
*/
|
||||
async listResourceViews(req: Request, res: Response, next: NextFunction) {
|
||||
const { tenantId } = req;
|
||||
const { resource_model: resourceModel } = req.params;
|
||||
|
||||
try {
|
||||
const views = await this.viewsService.listResourceViews(tenantId, resourceModel);
|
||||
const views = await this.viewsService.listResourceViews(
|
||||
tenantId,
|
||||
resourceModel
|
||||
);
|
||||
|
||||
return res.status(200).send({ views });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve view details with assocaited roles and columns.
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
*/
|
||||
async getView(req: Request, res: Response, next: NextFunction) {
|
||||
const { tenantId } = req;
|
||||
const { id: viewId } = req.params;
|
||||
|
||||
try {
|
||||
const view = await this.viewsService.getView(tenantId, viewId);
|
||||
return res.status(200).send({ view });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new view.
|
||||
* @param {Request} req -
|
||||
* @param {Response} res -
|
||||
* @param {NextFunction} next -
|
||||
*/
|
||||
async createView(req: Request, res: Response, next: NextFunction) {
|
||||
const { tenantId } = req;
|
||||
const viewDTO: IViewDTO = this.matchedBodyData(req);
|
||||
|
||||
try {
|
||||
const view = await this.viewsService.newView(tenantId, viewDTO);
|
||||
return res.status(200).send({
|
||||
id: view.id,
|
||||
message: 'The view has been created successfully.',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits views metadata.
|
||||
* @param {Request} req -
|
||||
* @param {Response} res -
|
||||
* @param {NextFunction} next -
|
||||
*/
|
||||
async editView(req: Request, res: Response, next: NextFunction) {
|
||||
const { tenantId } = req;
|
||||
const { id: viewId } = req.params;
|
||||
const viewEditDTO: IViewEditDTO = this.matchedBodyData(req);
|
||||
|
||||
try {
|
||||
await this.viewsService.editView(tenantId, viewId, viewEditDTO);
|
||||
return res.status(200).send({
|
||||
id: viewId,
|
||||
message: 'The given view has been edited succcessfully.',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given view.
|
||||
* @param {Request} req -
|
||||
* @param {Response} res -
|
||||
* @param {NextFunction} next -
|
||||
*/
|
||||
async deleteView(req: Request, res: Response, next: NextFunction) {
|
||||
const { tenantId } = req;
|
||||
const { id: viewId } = req.params;
|
||||
|
||||
try {
|
||||
await this.viewsService.deleteView(tenantId, viewId);
|
||||
return res.status(200).send({
|
||||
id: viewId,
|
||||
message: 'The view has been deleted successfully.',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles service errors.
|
||||
* @param {Error} error
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
* @param {Error} error
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
*/
|
||||
handlerServiceErrors(error: Error, req: Request, res: Response, next: NextFunction) {
|
||||
handlerServiceErrors(
|
||||
error: Error,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
if (error instanceof ServiceError) {
|
||||
if (error.errorType === 'VIEW_NAME_NOT_UNIQUE') {
|
||||
return res.boom.badRequest(null, {
|
||||
@@ -226,7 +78,7 @@ export default class ViewsController extends BaseController{
|
||||
}
|
||||
if (error.errorType === 'RESOURCE_MODEL_NOT_FOUND') {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'RESOURCE_MODEL_NOT_FOUND', code: 150, }],
|
||||
errors: [{ type: 'RESOURCE_MODEL_NOT_FOUND', code: 150 }],
|
||||
});
|
||||
}
|
||||
if (error.errorType === 'INVALID_LOGIC_EXPRESSION') {
|
||||
@@ -253,18 +105,18 @@ export default class ViewsController extends BaseController{
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'PREDEFINED_VIEW', code: 200 }],
|
||||
});
|
||||
}
|
||||
}
|
||||
if (error.errorType === 'RESOURCE_FIELDS_KEYS_NOT_FOUND') {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'RESOURCE_FIELDS_KEYS_NOT_FOUND', code: 300 }],
|
||||
})
|
||||
});
|
||||
}
|
||||
if (error.errorType === 'RESOURCE_COLUMNS_KEYS_NOT_FOUND') {
|
||||
return res.boom.badRequest(null, {
|
||||
errors: [{ type: 'RESOURCE_COLUMNS_KEYS_NOT_FOUND', code: 310 }],
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,4 +13,8 @@ export default (Model) =>
|
||||
static getDefaultViewBySlug(viewSlug) {
|
||||
return this.defaultViews.find((view) => view.slug === viewSlug) || null;
|
||||
}
|
||||
|
||||
static getDefaultViews() {
|
||||
return this.defaultViews;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,29 +1,11 @@
|
||||
import { Service, Inject } from "typedi";
|
||||
import { difference } from 'lodash';
|
||||
import { ServiceError } from 'exceptions';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import {
|
||||
IViewsService,
|
||||
IViewDTO,
|
||||
IView,
|
||||
IViewEditDTO,
|
||||
IModel,
|
||||
IViewColumnDTO,
|
||||
IViewRoleDTO,
|
||||
} from 'interfaces';
|
||||
import { getModelFieldsKeys } from 'lib/ViewRolesBuilder';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import ResourceService from "services/Resource/ResourceService";
|
||||
import { validateRolesLogicExpression } from 'lib/ViewRolesBuilder';
|
||||
|
||||
const ERRORS = {
|
||||
VIEW_NOT_FOUND: 'VIEW_NOT_FOUND',
|
||||
VIEW_PREDEFINED: 'VIEW_PREDEFINED',
|
||||
VIEW_NAME_NOT_UNIQUE: 'VIEW_NAME_NOT_UNIQUE',
|
||||
LOGIC_EXPRESSION_INVALID: 'INVALID_LOGIC_EXPRESSION',
|
||||
RESOURCE_FIELDS_KEYS_NOT_FOUND: 'RESOURCE_FIELDS_KEYS_NOT_FOUND',
|
||||
RESOURCE_COLUMNS_KEYS_NOT_FOUND: 'RESOURCE_COLUMNS_KEYS_NOT_FOUND',
|
||||
RESOURCE_MODEL_NOT_FOUND: 'RESOURCE_MODEL_NOT_FOUND'
|
||||
};
|
||||
import ResourceService from 'services/Resource/ResourceService';
|
||||
|
||||
@Service()
|
||||
export default class ViewsService implements IViewsService {
|
||||
@@ -38,281 +20,33 @@ export default class ViewsService implements IViewsService {
|
||||
|
||||
/**
|
||||
* Listing resource views.
|
||||
* @param {number} tenantId -
|
||||
* @param {string} resourceModel -
|
||||
* @param {number} tenantId -
|
||||
* @param {string} resourceModel -
|
||||
*/
|
||||
public async listResourceViews(
|
||||
tenantId: number,
|
||||
resourceModelName: string,
|
||||
resourceModelName: string
|
||||
): Promise<IView[]> {
|
||||
this.logger.info('[views] trying to retrieve resource views.', { tenantId, resourceModelName });
|
||||
|
||||
// Validate the resource model name is valid.
|
||||
const resourceModel = this.getResourceModelOrThrowError(tenantId, resourceModelName);
|
||||
const resourceModel = this.getResourceModelOrThrowError(
|
||||
tenantId,
|
||||
resourceModelName
|
||||
);
|
||||
// Default views.
|
||||
const defaultViews = resourceModel.getDefaultViews();
|
||||
|
||||
const { viewRepository } = this.tenancy.repositories(tenantId);
|
||||
return viewRepository.allByResource(resourceModel.name, 'roles');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate model resource conditions fields existance.
|
||||
* @param {string} resourceName
|
||||
* @param {IViewRoleDTO[]} viewRoles
|
||||
*/
|
||||
private validateResourceRolesFieldsExistance(
|
||||
ResourceModel: IModel,
|
||||
viewRoles: IViewRoleDTO[],
|
||||
) {
|
||||
const resourceFieldsKeys = getModelFieldsKeys(ResourceModel);
|
||||
|
||||
const fieldsKeys = viewRoles.map(viewRole => viewRole.fieldKey);
|
||||
const notFoundFieldsKeys = difference(fieldsKeys, resourceFieldsKeys);
|
||||
|
||||
if (notFoundFieldsKeys.length > 0) {
|
||||
throw new ServiceError(ERRORS.RESOURCE_FIELDS_KEYS_NOT_FOUND);
|
||||
}
|
||||
return notFoundFieldsKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates model resource columns existance.
|
||||
* @param {string} resourceName
|
||||
* @param {IViewColumnDTO[]} viewColumns
|
||||
*/
|
||||
private validateResourceColumnsExistance(
|
||||
ResourceModel: IModel,
|
||||
viewColumns: IViewColumnDTO[],
|
||||
) {
|
||||
const resourceFieldsKeys = getModelFieldsKeys(ResourceModel);
|
||||
|
||||
const fieldsKeys = viewColumns.map((viewColumn: IViewColumnDTO) => viewColumn.fieldKey);
|
||||
const notFoundFieldsKeys = difference(fieldsKeys, resourceFieldsKeys);
|
||||
|
||||
if (notFoundFieldsKeys.length > 0) {
|
||||
throw new ServiceError(ERRORS.RESOURCE_COLUMNS_KEYS_NOT_FOUND);
|
||||
}
|
||||
return notFoundFieldsKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given view details with associated conditions and columns.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} viewId - View id.
|
||||
*/
|
||||
public getView(tenantId: number, viewId: number): Promise<IView> {
|
||||
this.logger.info('[view] trying to get view from storage.', { tenantId, viewId });
|
||||
return this.getViewOrThrowError(tenantId, viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve view or throw not found error.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} viewId - View id.
|
||||
*/
|
||||
private async getViewOrThrowError(tenantId: number, viewId: number): Promise<IView> {
|
||||
const { viewRepository } = this.tenancy.repositories(tenantId);
|
||||
|
||||
this.logger.info('[view] trying to get view from storage.', { tenantId, viewId });
|
||||
const view = await viewRepository.findOneById(viewId);
|
||||
|
||||
if (!view) {
|
||||
this.logger.info('[view] view not found.', { tenantId, viewId });
|
||||
throw new ServiceError(ERRORS.VIEW_NOT_FOUND);
|
||||
}
|
||||
return view;
|
||||
return defaultViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve resource model from resource name or throw not found error.
|
||||
* @param {number} tenantId
|
||||
* @param {number} resourceModel
|
||||
* @param {number} tenantId
|
||||
* @param {number} resourceModel
|
||||
*/
|
||||
private getResourceModelOrThrowError(
|
||||
tenantId: number,
|
||||
resourceModel: string,
|
||||
resourceModel: string
|
||||
): IModel {
|
||||
return this.resourceService.getResourceModel(tenantId, resourceModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates view name uniqiness in the given resource.
|
||||
* @param {number} tenantId
|
||||
* @param {stirng} resourceModel
|
||||
* @param {string} viewName
|
||||
* @param {number} notViewId
|
||||
*/
|
||||
private async validateViewNameUniquiness(
|
||||
tenantId: number,
|
||||
resourceModel: string,
|
||||
viewName: string,
|
||||
notViewId?: number
|
||||
): void {
|
||||
const { View } = this.tenancy.models(tenantId);
|
||||
|
||||
this.logger.info('[views] trying to validate view name uniqiness.', {
|
||||
tenantId, resourceModel, viewName,
|
||||
});
|
||||
const foundViews = await View.query()
|
||||
.where('resource_model', resourceModel)
|
||||
.where('name', viewName)
|
||||
.onBuild((builder) => {
|
||||
if (notViewId) {
|
||||
builder.whereNot('id', notViewId);
|
||||
}
|
||||
});
|
||||
|
||||
if (foundViews.length > 0) {
|
||||
throw new ServiceError(ERRORS.VIEW_NAME_NOT_UNIQUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new custom view to specific resource.
|
||||
* ----––––––
|
||||
* Precedures.
|
||||
* ----––––––
|
||||
* - Validate resource fields existance.
|
||||
* - Validate resource columns existance.
|
||||
* - Validate view logic expression.
|
||||
* - Store view to the storage.
|
||||
* - Store view columns to the storage.
|
||||
* - Store view roles/conditions to the storage.
|
||||
* ---------
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {IViewDTO} viewDTO - New view DTO.
|
||||
*
|
||||
* @return {Promise<IView>}
|
||||
*/
|
||||
public async newView(tenantId: number, viewDTO: IViewDTO): Promise<IView> {
|
||||
const { viewRepository } = this.tenancy.repositories(tenantId);
|
||||
this.logger.info('[views] trying to create a new view.', { tenantId, viewDTO });
|
||||
|
||||
// Validate the resource name is exists and resourcable.
|
||||
const ResourceModel = this.getResourceModelOrThrowError(tenantId, viewDTO.resourceModel);
|
||||
|
||||
// Validate view name uniquiness.
|
||||
await this.validateViewNameUniquiness(tenantId, viewDTO.resourceModel, viewDTO.name);
|
||||
|
||||
// Validate the given fields keys exist on the storage.
|
||||
this.validateResourceRolesFieldsExistance(ResourceModel, viewDTO.roles);
|
||||
|
||||
// Validate the given columnable fields keys exists on the storage.
|
||||
this.validateResourceColumnsExistance(ResourceModel, viewDTO.columns);
|
||||
|
||||
// Validates the view conditional logic expression.
|
||||
if (!validateRolesLogicExpression(viewDTO.logicExpression, viewDTO.roles)) {
|
||||
throw new ServiceError(ERRORS.LOGIC_EXPRESSION_INVALID);
|
||||
}
|
||||
// Save view details.
|
||||
this.logger.info('[views] trying to insert to storage.', { tenantId, viewDTO })
|
||||
const view = await viewRepository.create({
|
||||
predefined: false,
|
||||
name: viewDTO.name,
|
||||
rolesLogicExpression: viewDTO.logicExpression,
|
||||
resourceModel: ResourceModel.name,
|
||||
roles: viewDTO.roles,
|
||||
columns: viewDTO.columns,
|
||||
});
|
||||
this.logger.info('[views] inserted to the storage successfully.', { tenantId, viewDTO });
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits view details, roles and columns on the storage.
|
||||
* --------
|
||||
* Precedures.
|
||||
* --------
|
||||
* - Validate view existance.
|
||||
* - Validate view resource fields existance.
|
||||
* - Validate view resource columns existance.
|
||||
* - Validate view logic expression.
|
||||
* - Delete old view columns and roles.
|
||||
* - Re-save view columns and roles.
|
||||
*
|
||||
* @param {number} tenantId -
|
||||
* @param {number} viewId -
|
||||
* @param {IViewEditDTO} viewEditDTO -
|
||||
* @return {Promise<IView>}
|
||||
*/
|
||||
public async editView(tenantId: number, viewId: number, viewEditDTO: IViewEditDTO): Promise<IView> {
|
||||
const { viewRepository } = this.tenancy.repositories(tenantId);
|
||||
this.logger.info('[view] trying to edit custom view.', { tenantId, viewId });
|
||||
|
||||
// Retrieve view details or throw not found error.
|
||||
const oldView = await this.getViewOrThrowError(tenantId, viewId);
|
||||
|
||||
// Validate the resource name is exists and resourcable.
|
||||
const ResourceModel = this.getResourceModelOrThrowError(tenantId, oldView.resourceModel);
|
||||
|
||||
// Validate view name uniquiness.
|
||||
await this.validateViewNameUniquiness(tenantId, oldView.resourceModel, viewEditDTO.name, viewId);
|
||||
|
||||
// Validate the given fields keys exist on the storage.
|
||||
this.validateResourceRolesFieldsExistance(ResourceModel, viewEditDTO.roles);
|
||||
|
||||
// Validate the given columnable fields keys exists on the storage.
|
||||
this.validateResourceColumnsExistance(ResourceModel, viewEditDTO.columns);
|
||||
|
||||
// Validates the view conditional logic expression.
|
||||
if (!validateRolesLogicExpression(viewEditDTO.logicExpression, viewEditDTO.roles)) {
|
||||
throw new ServiceError(ERRORS.LOGIC_EXPRESSION_INVALID);
|
||||
}
|
||||
// Update view details.
|
||||
this.logger.info('[views] trying to update view details.', { tenantId, viewId });
|
||||
const view = await viewRepository.upsertGraph({
|
||||
id: viewId,
|
||||
predefined: false,
|
||||
name: viewEditDTO.name,
|
||||
rolesLogicExpression: viewEditDTO.logicExpression,
|
||||
roles: viewEditDTO.roles,
|
||||
columns: viewEditDTO.columns,
|
||||
})
|
||||
this.logger.info('[view] edited successfully.', { tenantId, viewId });
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve views details of the given id or throw not found error.
|
||||
* @private
|
||||
* @param {number} tenantId
|
||||
* @param {number} viewId
|
||||
* @return {Promise<IView>}
|
||||
*/
|
||||
private async getViewByIdOrThrowError(tenantId: number, viewId: number): Promise<IView> {
|
||||
const { View } = this.tenancy.models(tenantId);
|
||||
|
||||
this.logger.info('[views] get stored view.', { tenantId, viewId });
|
||||
const view = await View.query().findById(viewId);
|
||||
|
||||
if (!view) {
|
||||
this.logger.info('[views] the given id not found.', { tenantId, viewId });
|
||||
throw new ServiceError(ERRORS.VIEW_NOT_FOUND);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given view with associated roles and columns.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} viewId - View id.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async deleteView(tenantId: number, viewId: number): Promise<void> {
|
||||
const { View } = this.tenancy.models(tenantId);
|
||||
|
||||
this.logger.info('[views] trying to delete the given view.', { tenantId, viewId });
|
||||
const view = await this.getViewByIdOrThrowError(tenantId, viewId);
|
||||
|
||||
if (view.predefined) {
|
||||
this.logger.info('[views] cannot delete predefined.', { tenantId, viewId });
|
||||
throw new ServiceError(ERRORS.VIEW_PREDEFINED);
|
||||
}
|
||||
await Promise.all([
|
||||
view.$relatedQuery('roles').delete(),
|
||||
view.$relatedQuery('columns').delete(),
|
||||
]);
|
||||
await View.query().where('id', view.id).delete();
|
||||
this.logger.info('[views] deleted successfully.', { tenantId, viewId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user