mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
182 lines
4.8 KiB
TypeScript
182 lines
4.8 KiB
TypeScript
import { Service, Inject } from 'typedi';
|
|
import { Request, Response, NextFunction } from 'express';
|
|
import { castArray, isEmpty } from 'lodash';
|
|
import { ServiceError } from '@/exceptions';
|
|
import { DynamicFilter } from '@/lib/DynamicFilter';
|
|
import {
|
|
IDynamicListFilter,
|
|
IDynamicListService,
|
|
IFilterRole,
|
|
IModel,
|
|
} from '@/interfaces';
|
|
import TenancyService from '@/services/Tenancy/TenancyService';
|
|
import DynamicListFilterRoles from './DynamicListFilterRoles';
|
|
import DynamicListSortBy from './DynamicListSortBy';
|
|
import DynamicListCustomView from './DynamicListCustomView';
|
|
import DynamicListSearch from './DynamicListSearch';
|
|
|
|
@Service()
|
|
export default class DynamicListService implements IDynamicListService {
|
|
@Inject()
|
|
tenancy: TenancyService;
|
|
|
|
@Inject()
|
|
dynamicListFilterRoles: DynamicListFilterRoles;
|
|
|
|
@Inject()
|
|
dynamicListSortBy: DynamicListSortBy;
|
|
|
|
@Inject()
|
|
dynamicListView: DynamicListCustomView;
|
|
|
|
@Inject()
|
|
dynamicListSearch: DynamicListSearch;
|
|
|
|
/**
|
|
* Parses filter DTO.
|
|
* @param {IMode} model -
|
|
* @param {} filterDTO -
|
|
*/
|
|
private parseFilterObject = (model, filterDTO) => {
|
|
return {
|
|
// Merges the default properties with filter object.
|
|
...(model.defaultSort
|
|
? {
|
|
sortOrder: model.defaultSort.sortOrder,
|
|
columnSortBy: model.defaultSort.sortOrder,
|
|
}
|
|
: {}),
|
|
...filterDTO,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Dynamic listing.
|
|
* @param {number} tenantId - Tenant id.
|
|
* @param {IModel} model - Model.
|
|
* @param {IDynamicListFilter} filter - Dynamic filter DTO.
|
|
*/
|
|
public dynamicList = async (
|
|
tenantId: number,
|
|
model: IModel,
|
|
filter: IDynamicListFilter
|
|
) => {
|
|
const dynamicFilter = new DynamicFilter(model);
|
|
|
|
// Parses the filter object.
|
|
const parsedFilter = this.parseFilterObject(model, filter);
|
|
|
|
// Search by keyword.
|
|
if (filter.searchKeyword) {
|
|
const dynamicListSearch = this.dynamicListSearch.dynamicSearch(
|
|
model,
|
|
filter.searchKeyword
|
|
);
|
|
dynamicFilter.setFilter(dynamicListSearch);
|
|
}
|
|
// Custom view filter roles.
|
|
if (filter.viewSlug) {
|
|
const dynamicListCustomView =
|
|
await this.dynamicListView.dynamicListCustomView(
|
|
dynamicFilter,
|
|
filter.viewSlug,
|
|
tenantId
|
|
);
|
|
dynamicFilter.setFilter(dynamicListCustomView);
|
|
}
|
|
// Sort by the given column.
|
|
if (parsedFilter.columnSortBy) {
|
|
const dynmaicListSortBy = this.dynamicListSortBy.dynamicSortBy(
|
|
model,
|
|
parsedFilter.columnSortBy,
|
|
parsedFilter.sortOrder
|
|
);
|
|
dynamicFilter.setFilter(dynmaicListSortBy);
|
|
}
|
|
// Filter roles.
|
|
if (!isEmpty(parsedFilter.filterRoles)) {
|
|
const dynamicFilterRoles = this.dynamicListFilterRoles.dynamicList(
|
|
model,
|
|
parsedFilter.filterRoles
|
|
);
|
|
dynamicFilter.setFilter(dynamicFilterRoles);
|
|
}
|
|
return dynamicFilter;
|
|
};
|
|
|
|
/**
|
|
* Middleware to catch services errors
|
|
* @param {Error} error
|
|
* @param {Request} req
|
|
* @param {Response} res
|
|
* @param {NextFunction} next
|
|
*/
|
|
public handlerErrorsToResponse(
|
|
error: Error,
|
|
req: Request,
|
|
res: Response,
|
|
next: NextFunction
|
|
) {
|
|
if (error instanceof ServiceError) {
|
|
if (error.errorType === 'sort_column_not_found') {
|
|
return res.boom.badRequest(null, {
|
|
errors: [
|
|
{
|
|
type: 'SORT.COLUMN.NOT.FOUND',
|
|
message: 'Sort column not found.',
|
|
code: 200,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
if (error.errorType === 'view_not_found') {
|
|
return res.boom.badRequest(null, {
|
|
errors: [
|
|
{
|
|
type: 'CUSTOM.VIEW.NOT.FOUND',
|
|
message: 'Custom view not found.',
|
|
code: 100,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
if (error.errorType === 'filter_roles_fields_not_found') {
|
|
return res.boom.badRequest(null, {
|
|
errors: [
|
|
{
|
|
type: 'FILTER.ROLES.FIELDS.NOT.FOUND',
|
|
message: 'Filter roles fields not found.',
|
|
code: 300,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
if (error.errorType === 'stringified_filter_roles_invalid') {
|
|
return res.boom.badRequest(null, {
|
|
errors: [
|
|
{
|
|
type: 'STRINGIFIED_FILTER_ROLES_INVALID',
|
|
message: 'Stringified filter roles json invalid.',
|
|
code: 400,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
}
|
|
next(error);
|
|
}
|
|
|
|
/**
|
|
* Parses stringified filter roles.
|
|
* @param {string} stringifiedFilterRoles - Stringified filter roles.
|
|
*/
|
|
public parseStringifiedFilter = (filterRoles: IDynamicListFilter) => {
|
|
return {
|
|
...filterRoles,
|
|
filterRoles: filterRoles.stringifiedFilterRoles
|
|
? castArray(JSON.parse(filterRoles.stringifiedFilterRoles))
|
|
: [],
|
|
};
|
|
};
|
|
}
|