feat: custom view dynamic filter.

This commit is contained in:
a.bouhuolia
2021-08-04 15:01:43 +02:00
parent 3fc30d5240
commit 2822270ac3
42 changed files with 647 additions and 97 deletions

View File

@@ -127,9 +127,12 @@ export default class AccountsController extends BaseController {
return [param('id').exists().isNumeric().toInt()]; return [param('id').exists().isNumeric().toInt()];
} }
/**
* Accounts list validation schema.
*/
get accountsListSchema() { get accountsListSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),

View File

@@ -118,7 +118,7 @@ export default class CustomersController extends ContactsController {
query('page').optional().isNumeric().toInt(), query('page').optional().isNumeric().toInt(),
query('page_size').optional().isNumeric().toInt(), query('page_size').optional().isNumeric().toInt(),
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('inactive_mode').optional().isBoolean().toBoolean(), query('inactive_mode').optional().isBoolean().toBoolean(),

View File

@@ -92,7 +92,7 @@ export default class VendorsController extends ContactsController {
*/ */
get vendorsListSchema() { get vendorsListSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),

View File

@@ -174,7 +174,7 @@ export default class ExpensesController extends BaseController {
*/ */
get expensesListSchema() { get expensesListSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),

View File

@@ -183,7 +183,7 @@ export default class ItemsController extends BaseController {
query('page').optional().isNumeric().toInt(), query('page').optional().isNumeric().toInt(),
query('page_size').optional().isNumeric().toInt(), query('page_size').optional().isNumeric().toInt(),
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('inactive_mode').optional().isBoolean().toBoolean(), query('inactive_mode').optional().isBoolean().toBoolean(),

View File

@@ -165,7 +165,7 @@ export default class BillsController extends BaseController {
*/ */
get billsListingValidationSchema() { get billsListingValidationSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('page').optional().isNumeric().toInt(), query('page').optional().isNumeric().toInt(),
query('page_size').optional().isNumeric().toInt(), query('page_size').optional().isNumeric().toInt(),

View File

@@ -115,7 +115,7 @@ export default class PaymentReceivesController extends BaseController {
*/ */
get validatePaymentReceiveList(): ValidationChain[] { get validatePaymentReceiveList(): ValidationChain[] {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),
query('sort_order').optional().isIn(['desc', 'asc']), query('sort_order').optional().isIn(['desc', 'asc']),

View File

@@ -129,7 +129,7 @@ export default class SalesEstimatesController extends BaseController {
*/ */
get validateEstimateListSchema() { get validateEstimateListSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),
query('sort_order').optional().isIn(['desc', 'asc']), query('sort_order').optional().isIn(['desc', 'asc']),

View File

@@ -129,7 +129,7 @@ export default class SaleInvoicesController extends BaseController {
*/ */
get saleInvoiceListValidationSchema() { get saleInvoiceListValidationSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional({ nullable: true }).isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),
query('sort_order').optional().isIn(['desc', 'asc']), query('sort_order').optional().isIn(['desc', 'asc']),

View File

@@ -118,7 +118,7 @@ export default class SalesReceiptsController extends BaseController {
*/ */
get listSalesReceiptsValidationSchema() { get listSalesReceiptsValidationSchema() {
return [ return [
query('custom_view_id').optional().isNumeric().toInt(), query('view_slug').optional().isString().trim(),
query('stringified_filter_roles').optional().isJSON(), query('stringified_filter_roles').optional().isJSON(),
query('column_sort_by').optional(), query('column_sort_by').optional(),
query('sort_order').optional().isIn(['desc', 'asc']), query('sort_order').optional().isIn(['desc', 'asc']),

View File

@@ -13,6 +13,7 @@ export interface IExpensesFilter {
filterRoles?: IFilterRole[]; filterRoles?: IFilterRole[];
columnSortBy: string; columnSortBy: string;
sortOrder: string; sortOrder: string;
viewSlug?: string;
} }
export interface IExpense { export interface IExpense {

View File

@@ -73,6 +73,7 @@ export interface IItemsFilter extends IDynamicListFilterDTO {
page: number, page: number,
pageSize: number, pageSize: number,
inactiveMode: boolean, inactiveMode: boolean,
viewSlug?: string,
}; };
export interface IItemsAutoCompleteFilter { export interface IItemsAutoCompleteFilter {

View File

@@ -2,6 +2,7 @@
export interface IView { export interface IView {
id: number, id: number,
name: string, name: string,
slug: string;
predefined: boolean, predefined: boolean,
resourceModel: string, resourceModel: string,
favourite: boolean, favourite: boolean,
@@ -13,7 +14,7 @@ export interface IView {
export interface IViewRole { export interface IViewRole {
id: number, id: number,
fieldId: number, fieldKey: string,
index: number, index: number,
comparator: string, comparator: string,
value: string, value: string,

View File

@@ -37,4 +37,8 @@ export default class DynamicFilterAbstructor {
} }
}); });
}; };
getModel() {
return this.model;
}
} }

View File

@@ -346,4 +346,12 @@ export default abstract class DynamicFilterAbstructor
this.relationFields.push(field.relationKey); this.relationFields.push(field.relationKey);
} }
}; };
getModel() {
return this.model;
}
onInitialize() {
}
} }

View File

@@ -1,12 +1,12 @@
import { omit } from 'lodash'; import { omit } from 'lodash';
import { IView, IViewRole } from 'interfaces'; import { IView, IViewRole } from 'interfaces';
import DynamicFilterRoleAbstructor from 'lib/DynamicFilter/DynamicFilterRoleAbstructor'; import DynamicFilterRoleAbstructor from './DynamicFilterRoleAbstructor';
import { buildFilterQuery } from 'lib/ViewRolesBuilder';
export default class DynamicFilterViews extends DynamicFilterRoleAbstructor { export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
viewId: number; private viewSlug: string;
logicExpression: string; private logicExpression: string;
filterRoles: IViewRole[]; private filterRoles: IViewRole[];
private viewColumns = [];
/** /**
* Constructor method. * Constructor method.
@@ -15,8 +15,9 @@ export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
constructor(view: IView) { constructor(view: IView) {
super(); super();
this.viewId = view.id; this.viewSlug = view.slug;
this.filterRoles = view.roles; this.filterRoles = view.roles;
this.viewColumns = view.columns;
this.logicExpression = view.rolesLogicExpression this.logicExpression = view.rolesLogicExpression
.replace('AND', '&&') .replace('AND', '&&')
.replace('OR', '||'); .replace('OR', '||');
@@ -24,19 +25,12 @@ export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
this.setResponseMeta(); this.setResponseMeta();
} }
/**
* Retrieve logic expression.
*/
buildLogicExpression() {
return this.logicExpression;
}
/** /**
* Builds database query of view roles. * Builds database query of view roles.
*/ */
buildQuery() { public buildQuery() {
return (builder) => { return (builder) => {
buildFilterQuery( this.buildFilterQuery(
this.model, this.model,
this.filterRoles, this.filterRoles,
this.logicExpression this.logicExpression
@@ -47,14 +41,15 @@ export default class DynamicFilterViews extends DynamicFilterRoleAbstructor {
/** /**
* Sets response meta. * Sets response meta.
*/ */
setResponseMeta() { public setResponseMeta() {
this.responseMeta = { this.responseMeta = {
view: { view: {
logicExpression: this.logicExpression, logicExpression: this.logicExpression,
filterRoles: this.filterRoles.map((filterRole) => ({ filterRoles: this.filterRoles.map((filterRole) => ({
...omit(filterRole, ['id', 'viewId']), ...omit(filterRole, ['id', 'viewId']),
})), })),
customViewId: this.viewId, viewSlug: this.viewSlug,
viewColumns: this.viewColumns,
}, },
}; };
} }

View File

@@ -9,8 +9,13 @@ import AccountTypesUtils from 'lib/AccountTypes';
import AccountSettings from './Account.Settings'; import AccountSettings from './Account.Settings';
import ModelSettings from './ModelSetting'; import ModelSettings from './ModelSetting';
import { ACCOUNT_TYPES } from 'data/AccountTypes'; import { ACCOUNT_TYPES } from 'data/AccountTypes';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Accounts/constants';
export default class Account extends mixin(TenantModel, [ModelSettings]) { export default class Account extends mixin(TenantModel, [
ModelSettings,
CustomViewBaseModel,
]) {
/** /**
* Table name. * Table name.
*/ */
@@ -135,7 +140,7 @@ export default class Account extends mixin(TenantModel, [ModelSettings]) {
*/ */
filterByAccountNormal(query, accountNormal) { filterByAccountNormal(query, accountNormal) {
const filterTypes = ACCOUNT_TYPES.filter( const filterTypes = ACCOUNT_TYPES.filter(
(accountType) => accountType.normal === accountNormal, (accountType) => accountType.normal === accountNormal
).map((accountType) => accountType.key); ).map((accountType) => accountType.key);
query.whereIn('account_type', filterTypes); query.whereIn('account_type', filterTypes);
@@ -248,4 +253,11 @@ export default class Account extends mixin(TenantModel, [ModelSettings]) {
static get meta() { static get meta() {
return AccountSettings; return AccountSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -4,8 +4,13 @@ import { difference } from 'lodash';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import BillSettings from './Bill.Settings'; import BillSettings from './Bill.Settings';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Purchases/constants';
export default class Bill extends mixin(TenantModel, [ModelSetting]) { export default class Bill extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -303,4 +308,11 @@ export default class Bill extends mixin(TenantModel, [ModelSetting]) {
.where('id', billId) .where('id', billId)
[changeMethod]('payment_amount', Math.abs(amount)); [changeMethod]('payment_amount', Math.abs(amount));
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -0,0 +1,16 @@
export default (Model) =>
class CustomViewBaseModel extends Model {
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return [];
}
/**
* Retrieve the default view by the given slug.
*/
static getDefaultViewBySlug(viewSlug) {
return this.defaultViews.find((view) => view.slug === viewSlug) || null;
}
};

View File

@@ -75,19 +75,13 @@ export default {
{ key: 'unpaid', label: 'Unpaid' }, { key: 'unpaid', label: 'Unpaid' },
], ],
columnable: true, columnable: true,
filterQuery: statusFieldFilterQuery, filterCustomQuery: statusFieldFilterQuery,
}, },
}, },
}; };
function statusFieldFilterQuery(query, role) { function statusFieldFilterQuery(query, role) {
switch (role.value) { switch (role.value) {
case 'active':
query.modify('active');
break;
case 'inactive':
query.modify('inactive');
break;
case 'overdue': case 'overdue':
query.modify('overdue'); query.modify('overdue');
break; break;

View File

@@ -1,9 +1,10 @@
import { Model, mixin } from 'objection'; import { Model, mixin } from 'objection';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import PaginationQueryBuilder from './Pagination'; import PaginationQueryBuilder from './Pagination';
import QueryParser from 'lib/LogicEvaluation/QueryParser';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import CustomerSettings from './Customer.Settings'; import CustomerSettings from './Customer.Settings';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Contacts/Customers/constants';
class CustomerQueryBuilder extends PaginationQueryBuilder { class CustomerQueryBuilder extends PaginationQueryBuilder {
constructor(...args) { constructor(...args) {
@@ -17,7 +18,10 @@ class CustomerQueryBuilder extends PaginationQueryBuilder {
} }
} }
export default class Customer extends mixin(TenantModel, [ModelSetting]) { export default class Customer extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Query builder. * Query builder.
*/ */
@@ -138,4 +142,11 @@ export default class Customer extends mixin(TenantModel, [ModelSetting]) {
static get meta() { static get meta() {
return CustomerSettings; return CustomerSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -3,8 +3,13 @@ import TenantModel from 'models/TenantModel';
import { viewRolesBuilder } from 'lib/ViewRolesBuilder'; import { viewRolesBuilder } from 'lib/ViewRolesBuilder';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import ExpenseSettings from './Expense.Settings'; import ExpenseSettings from './Expense.Settings';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Expenses/constants';
export default class Expense extends mixin(TenantModel, [ModelSetting]) { export default class Expense extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -148,4 +153,11 @@ export default class Expense extends mixin(TenantModel, [ModelSetting]) {
static get meta() { static get meta() {
return ExpenseSettings; return ExpenseSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -3,8 +3,13 @@ import TenantModel from 'models/TenantModel';
import { buildFilterQuery } from 'lib/ViewRolesBuilder'; import { buildFilterQuery } from 'lib/ViewRolesBuilder';
import ItemSettings from './Item.Settings'; import ItemSettings from './Item.Settings';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Items/constants';
export default class Item extends mixin(TenantModel, [ModelSetting]) { export default class Item extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -116,4 +121,11 @@ export default class Item extends mixin(TenantModel, [ModelSetting]) {
static get meta() { static get meta() {
return ItemSettings; return ItemSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -4,8 +4,13 @@ import TenantModel from 'models/TenantModel';
import { defaultToTransform } from 'utils'; import { defaultToTransform } from 'utils';
import SaleEstimateSettings from './SaleEstimate.Settings'; import SaleEstimateSettings from './SaleEstimate.Settings';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Sales/Estimates/constants';
export default class SaleEstimate extends mixin(TenantModel, [ModelSetting]) { export default class SaleEstimate extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -155,7 +160,7 @@ export default class SaleEstimate extends mixin(TenantModel, [ModelSetting]) {
query.modify('expired'); query.modify('expired');
break; break;
} }
} },
}; };
} }
@@ -198,4 +203,11 @@ export default class SaleEstimate extends mixin(TenantModel, [ModelSetting]) {
static get meta() { static get meta() {
return SaleEstimateSettings; return SaleEstimateSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -3,8 +3,13 @@ import moment from 'moment';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import SaleInvoiceMeta from './SaleInvoice.Settings'; import SaleInvoiceMeta from './SaleInvoice.Settings';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Sales/constants';
export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) { export default class SaleInvoice extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -359,4 +364,11 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
static dueAmountFieldSortQuery(query, role) { static dueAmountFieldSortQuery(query, role) {
query.modify('sortByDueAmount', role.order); query.modify('sortByDueAmount', role.order);
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -2,8 +2,13 @@ import { Model, mixin } from 'objection';
import TenantModel from 'models/TenantModel'; import TenantModel from 'models/TenantModel';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import SaleReceiptSettings from './SaleReceipt.Settings'; import SaleReceiptSettings from './SaleReceipt.Settings';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Sales/Receipts/constants';
export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) { export default class SaleReceipt extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Table name * Table name
*/ */
@@ -80,7 +85,7 @@ export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
query.modify('closed'); query.modify('closed');
break; break;
} }
} },
}; };
} }
@@ -147,4 +152,11 @@ export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
static get meta() { static get meta() {
return SaleReceiptSettings; return SaleReceiptSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -63,19 +63,11 @@ export default {
'status': { 'status': {
label: 'Status', label: 'Status',
options: [ options: [
{ key: 'active', label: 'Active' },
{ key: 'inactive', label: 'Inactive' },
{ key: 'overdue', label: 'Overdue' }, { key: 'overdue', label: 'Overdue' },
{ key: 'unpaid', label: 'Unpaid' }, { key: 'unpaid', label: 'Unpaid' },
], ],
query: (query, role) => { filterCustomQuery: (query, role) => {
switch (role.value) { switch (role.value) {
case 'active':
query.modify('active');
break;
case 'inactive':
query.modify('inactive');
break;
case 'overdue': case 'overdue':
query.modify('overdue'); query.modify('overdue');
break; break;

View File

@@ -3,6 +3,8 @@ import TenantModel from 'models/TenantModel';
import PaginationQueryBuilder from './Pagination'; import PaginationQueryBuilder from './Pagination';
import ModelSetting from './ModelSetting'; import ModelSetting from './ModelSetting';
import VendorSettings from './Vendor.Settings'; import VendorSettings from './Vendor.Settings';
import CustomViewBaseModel from './CustomViewBaseModel';
import { DEFAULT_VIEWS } from 'services/Contacts/Vendors/constants';
class VendorQueryBuilder extends PaginationQueryBuilder { class VendorQueryBuilder extends PaginationQueryBuilder {
constructor(...args) { constructor(...args) {
@@ -16,7 +18,10 @@ class VendorQueryBuilder extends PaginationQueryBuilder {
} }
} }
export default class Vendor extends mixin(TenantModel, [ModelSetting]) { export default class Vendor extends mixin(TenantModel, [
ModelSetting,
CustomViewBaseModel,
]) {
/** /**
* Query builder. * Query builder.
*/ */
@@ -67,7 +72,7 @@ export default class Vendor extends mixin(TenantModel, [ModelSetting]) {
/** /**
* Inactive/Active mode. * Inactive/Active mode.
*/ */
inactiveMode(query, active = false) { inactiveMode(query, active = false) {
query.where('active', !active); query.where('active', !active);
}, },
@@ -89,10 +94,9 @@ export default class Vendor extends mixin(TenantModel, [ModelSetting]) {
overdue(query) { overdue(query) {
query.select( query.select(
'*', '*',
Vendor Vendor.relatedQuery('overdueBills', query.knex())
.relatedQuery('overdueBills', query.knex())
.count() .count()
.as('countOverdue'), .as('countOverdue')
); );
query.having('countOverdue', '>', 0); query.having('countOverdue', '>', 0);
}, },
@@ -101,7 +105,7 @@ export default class Vendor extends mixin(TenantModel, [ModelSetting]) {
*/ */
unpaid(query) { unpaid(query) {
query.whereRaw('`BALANCE` + `OPENING_BALANCE` <> 0'); query.whereRaw('`BALANCE` + `OPENING_BALANCE` <> 0');
} },
}; };
} }
@@ -129,12 +133,19 @@ export default class Vendor extends mixin(TenantModel, [ModelSetting]) {
}, },
filter: (query) => { filter: (query) => {
query.modify('overdue'); query.modify('overdue');
} },
} },
}; };
} }
static get meta() { static get meta() {
return VendorSettings; return VendorSettings;
} }
/**
* Retrieve the default custom views, roles and columns.
*/
static get defaultViews() {
return DEFAULT_VIEWS;
}
} }

View File

@@ -638,10 +638,7 @@ export default class AccountsService {
Account, Account,
filter filter
); );
this.logger.info('[accounts] trying to get accounts datatable list.', { // Retrieve accounts model based on the given query.
tenantId,
filter,
});
const accounts = await Account.query().onBuild((builder) => { const accounts = await Account.query().onBuild((builder) => {
dynamicList.buildQuery()(builder); dynamicList.buildQuery()(builder);
builder.modify('inactiveMode', filter.inactiveMode); builder.modify('inactiveMode', filter.inactiveMode);

View File

@@ -14,3 +14,62 @@ export const ERRORS = {
'close_account_and_to_account_not_same_type', 'close_account_and_to_account_not_same_type',
ACCOUNTS_NOT_FOUND: 'accounts_not_found', ACCOUNTS_NOT_FOUND: 'accounts_not_found',
}; };
// Default views columns.
export const DEFAULT_VIEW_COLUMNS = [
{ key: 'name', label: 'Account name' },
{ key: 'code', label: 'Account code' },
{ key: 'account_type_label', label: 'Account type' },
{ key: 'account_normal', label: 'Account normal' },
{ key: 'amount', label: 'Balance' },
{ key: 'currencyCode', label: 'Currency' },
];
// Accounts default views.
export const DEFAULT_VIEWS = [
{
name: 'Assets',
slug: 'assets',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'root_type', comparator: 'equals', value: 'asset' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Liabilities',
slug: 'liabilities',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'liability' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Equity',
slug: 'equity',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'equity' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Income',
slug: 'income',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'income' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Expenses',
slug: 'expenses',
rolesLogicExpression: '1',
roles: [
{ fieldKey: 'root_type', index: 1, comparator: 'equals', value: 'expense' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -0,0 +1,22 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Overdue',
slug: 'overdue',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'overdue' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Unpaid',
slug: 'unpaid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'unpaid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -0,0 +1,22 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Overdue',
slug: 'overdue',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'overdue' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Unpaid',
slug: 'unpaid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'unpaid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -286,11 +286,12 @@ export default class VendorsService {
Vendor, Vendor,
filter filter
); );
// Vendors list. // Vendors list.
const { results, pagination } = await Vendor.query() const { results, pagination } = await Vendor.query()
.onBuild((builder) => { .onBuild((builder) => {
dynamicList.buildQuery()(builder); dynamicList.buildQuery()(builder);
// Switches between active/inactive modes.
builder.modify('inactiveMode', filter.inactiveMode); builder.modify('inactiveMode', filter.inactiveMode);
}) })
.pagination(filter.page - 1, filter.pageSize); .pagination(filter.page - 1, filter.pageSize);

View File

@@ -0,0 +1,22 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Overdue',
slug: 'overdue',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'overdue' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Unpaid',
slug: 'unpaid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'unpaid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -3,8 +3,8 @@ import DynamicListAbstruct from './DynamicListAbstruct';
import DynamicFilterViews from 'lib/DynamicFilter/DynamicFilterViews'; import DynamicFilterViews from 'lib/DynamicFilter/DynamicFilterViews';
import { ServiceError } from 'exceptions'; import { ServiceError } from 'exceptions';
import HasTenancyService from 'services/Tenancy/TenancyService'; import HasTenancyService from 'services/Tenancy/TenancyService';
import {ERRORS } from './constants'; import { ERRORS } from './constants';
import { IModel }from 'interfaces'; import { IModel } from 'interfaces';
@Service() @Service()
export default class DynamicListCustomView extends DynamicListAbstruct { export default class DynamicListCustomView extends DynamicListAbstruct {
@@ -19,16 +19,18 @@ export default class DynamicListCustomView extends DynamicListAbstruct {
*/ */
private getCustomViewOrThrowError = async ( private getCustomViewOrThrowError = async (
tenantId: number, tenantId: number,
viewId: number, viewSlug: string,
model: IModel model: IModel
) => { ) => {
const { viewRepository } = this.tenancy.repositories(tenantId); const { View } = this.tenancy.models(tenantId);
const view = await viewRepository.findOneById(viewId, 'roles');
if (!view || view.resourceModel !== model.name) { // Finds the default view by the given view slug.
const defaultView = model.getDefaultViewBySlug(viewSlug);
if (!defaultView) {
throw new ServiceError(ERRORS.VIEW_NOT_FOUND); throw new ServiceError(ERRORS.VIEW_NOT_FOUND);
} }
return view; return defaultView;
}; };
/** /**
@@ -38,14 +40,17 @@ export default class DynamicListCustomView extends DynamicListAbstruct {
* @returns * @returns
*/ */
public dynamicListCustomView = async ( public dynamicListCustomView = async (
tenantId: number, dynamicFilter: any,
model, customViewSlug: string,
customViewId: number tenantId: number
) => { ) => {
const model = dynamicFilter.getModel();
// Retrieve the custom view or throw not found.
const view = await this.getCustomViewOrThrowError( const view = await this.getCustomViewOrThrowError(
tenantId, tenantId,
customViewId, customViewSlug,
model model,
); );
return new DynamicFilterViews(view); return new DynamicFilterViews(view);
}; };

View File

@@ -30,16 +30,18 @@ export default class DynamicListService implements IDynamicListService {
/** /**
* Parses filter DTO. * Parses filter DTO.
* @param {IMode} model - * @param {IMode} model -
* @param {} filterDTO - * @param {} filterDTO -
*/ */
private parseFilterObject = (model, filterDTO) => { private parseFilterObject = (model, filterDTO) => {
return { return {
// Merges the default properties with filter object. // Merges the default properties with filter object.
...model.defaultSort ? { ...(model.defaultSort
sortOrder: model.defaultSort.sortOrder, ? {
columnSortBy: model.defaultSort.sortOrder, sortOrder: model.defaultSort.sortOrder,
} : {}, columnSortBy: model.defaultSort.sortOrder,
}
: {}),
...filterDTO, ...filterDTO,
}; };
}; };
@@ -61,17 +63,21 @@ export default class DynamicListService implements IDynamicListService {
const parsedFilter = this.parseFilterObject(model, filter); const parsedFilter = this.parseFilterObject(model, filter);
// Custom view filter roles. // Custom view filter roles.
// if (filter.customViewId) { if (filter.viewSlug) {
// const dynamicListCustomView = this.dynamicListView.dynamicListCustomView(); const dynamicListCustomView =
await this.dynamicListView.dynamicListCustomView(
// dynamicFilter.setFilter(dynamicListCustomView); dynamicFilter,
// } filter.viewSlug,
tenantId
);
dynamicFilter.setFilter(dynamicListCustomView);
}
// Sort by the given column. // Sort by the given column.
if (parsedFilter.columnSortBy) { if (parsedFilter.columnSortBy) {
const dynmaicListSortBy = this.dynamicListSortBy.dynamicSortBy( const dynmaicListSortBy = this.dynamicListSortBy.dynamicSortBy(
model, model,
parsedFilter.columnSortBy, parsedFilter.columnSortBy,
parsedFilter.sortOrder, parsedFilter.sortOrder
); );
dynamicFilter.setFilter(dynmaicListSortBy); dynamicFilter.setFilter(dynmaicListSortBy);
} }

View File

@@ -0,0 +1,26 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Draft',
slug: 'draft',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Published',
slug: 'published',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'published',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -1,3 +1,4 @@
export const ERRORS = { export const ERRORS = {
NOT_FOUND: 'NOT_FOUND', NOT_FOUND: 'NOT_FOUND',
ITEMS_NOT_FOUND: 'ITEMS_NOT_FOUND', ITEMS_NOT_FOUND: 'ITEMS_NOT_FOUND',
@@ -21,3 +22,38 @@ export const ERRORS = {
TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS', TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS: 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS',
INVENTORY_ACCOUNT_CANNOT_MODIFIED: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED' INVENTORY_ACCOUNT_CANNOT_MODIFIED: 'INVENTORY_ACCOUNT_CANNOT_MODIFIED'
}; };
export const DEFAULT_VIEW_COLUMNS = [
];
export const DEFAULT_VIEWS = [
{
name: 'Services',
slug: 'services',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'type', comparator: 'equals', value: 'service' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Inventory',
slug: 'inventory',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'type', comparator: 'equals', value: 'inventory' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Non Inventory',
slug: 'non-inventory',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'type', comparator: 'equals', value: 'non-inventory' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
]

View File

@@ -11,7 +11,65 @@ export const ERRORS = {
BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES: 'BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES', BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES: 'BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES',
VENDOR_HAS_BILLS: 'VENDOR_HAS_BILLS', VENDOR_HAS_BILLS: 'VENDOR_HAS_BILLS',
BILL_HAS_ASSOCIATED_LANDED_COSTS: 'BILL_HAS_ASSOCIATED_LANDED_COSTS', BILL_HAS_ASSOCIATED_LANDED_COSTS: 'BILL_HAS_ASSOCIATED_LANDED_COSTS',
BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED: 'BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED', BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED:
LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES: 'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES', 'BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED',
LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS: 'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS' LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES:
'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES',
LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS:
'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS',
}; };
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Draft',
slug: 'draft',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Opended',
slug: 'opened',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'opened' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Unpaid',
slug: 'unpaid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'unpaid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Overdue',
slug: 'overdue',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'overdue' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Partially Paid',
slug: 'partially-paid',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'partially-paid',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -0,0 +1,96 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Draft',
slug: 'draft',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Delivered',
slug: 'delivered',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'delivered',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Approved',
slug: 'approved',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'approved',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Rejected',
slug: 'rejected',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'rejected',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Invoiced',
slug: 'invoiced',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'invoiced',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Expired',
slug: 'expired',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'expired',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Closed',
slug: 'closed',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'closed',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -0,0 +1,21 @@
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Draft',
slug: 'draft',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Closed',
slug: 'closed',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'closed' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];

View File

@@ -10,5 +10,63 @@ export const ERRORS = {
INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES: INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES:
'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES', 'INVOICE_HAS_ASSOCIATED_PAYMENT_ENTRIES',
SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED', SALE_INVOICE_NO_IS_REQUIRED: 'SALE_INVOICE_NO_IS_REQUIRED',
CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES' CUSTOMER_HAS_SALES_INVOICES: 'CUSTOMER_HAS_SALES_INVOICES',
}; };
export const DEFAULT_VIEW_COLUMNS = [];
export const DEFAULT_VIEWS = [
{
name: 'Draft',
slug: 'draft',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Delivered',
slug: 'delivered',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'delivered',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Unpaid',
slug: 'unpaid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'unpaid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Partially paid',
slug: 'partially-paid',
rolesLogicExpression: '1',
roles: [
{
index: 1,
fieldKey: 'status',
comparator: 'equals',
value: 'partially-paid',
},
],
columns: DEFAULT_VIEW_COLUMNS,
},
{
name: 'Paid',
slug: 'paid',
rolesLogicExpression: '1',
roles: [
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'paid' },
],
columns: DEFAULT_VIEW_COLUMNS,
},
];