mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
WIP: dynamic list filtering.
This commit is contained in:
@@ -62,6 +62,8 @@ export default class InventoryAdjustmentsController extends BaseController {
|
||||
|
||||
query('page').optional().isNumeric().toInt(),
|
||||
query('page_size').optional().isNumeric().toInt(),
|
||||
|
||||
query('stringified_filter_roles').optional().isJSON(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -59,12 +59,21 @@ export interface IModelMetaEnumerationField {
|
||||
options: IModelMetaEnumerationOption[];
|
||||
}
|
||||
|
||||
export interface IModelMetaRelationField {
|
||||
export interface IModelMetaRelationFieldCommon {
|
||||
fieldType: 'relation';
|
||||
relationToModel: IModel;
|
||||
relationToField: string;
|
||||
}
|
||||
|
||||
export interface IModelMetaRelationEnumerationField {
|
||||
relationType: 'enumeration';
|
||||
relationKey: string;
|
||||
relationEntityLabel: string;
|
||||
relationEntityKey: string;
|
||||
}
|
||||
|
||||
export type IModelMetaRelationField = IModelMetaRelationFieldCommon & (
|
||||
IModelMetaRelationEnumerationField
|
||||
);
|
||||
|
||||
export interface IModelMeta {
|
||||
defaultFilterField: string;
|
||||
defaultSort: IModelMetaDefaultSort;
|
||||
|
||||
@@ -25,6 +25,9 @@ export default class DynamicFilter extends DynamicFilterAbstructor{
|
||||
*/
|
||||
public setFilter = (dynamicFilter: IDynamicFilter) => {
|
||||
dynamicFilter.setModel(this.model);
|
||||
|
||||
dynamicFilter.onInitialize();
|
||||
|
||||
this.dynamicFilters.push(dynamicFilter);
|
||||
}
|
||||
|
||||
@@ -66,11 +69,7 @@ export default class DynamicFilter extends DynamicFilterAbstructor{
|
||||
buildersCallbacks.forEach((builderCallback) => {
|
||||
builderCallback(builder);
|
||||
});
|
||||
|
||||
this.buildFilterRolesJoins(
|
||||
this.model,
|
||||
uniqBy(tableColumns, 'columnKey')
|
||||
)(builder);
|
||||
this.buildFilterRolesJoins(builder);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IModel, IFilterRole } from 'interfaces';
|
||||
import { FIELD_TYPE } from './constants';
|
||||
|
||||
export default class DynamicFilterAbstructor {
|
||||
/**
|
||||
@@ -16,22 +17,24 @@ export default class DynamicFilterAbstructor {
|
||||
* @param {String} tableName - Table name.
|
||||
* @param {Array} roles - Roles.
|
||||
*/
|
||||
protected buildFilterRolesJoins = (model: IModel, roles: IFilterRole[]) => {
|
||||
return (builder) => {
|
||||
roles.forEach((role) => {
|
||||
const field = model.getField(role.fieldKey);
|
||||
protected buildFilterRolesJoins = (builder) => {
|
||||
this.dynamicFilters.forEach((dynamicFilter) => {
|
||||
const relationsFields = dynamicFilter.relationFields;
|
||||
|
||||
if (field.relation) {
|
||||
const joinTable = this.getTableFromRelationColumn(field.relation);
|
||||
this.buildFieldsJoinQueries(builder, relationsFields);
|
||||
});
|
||||
};
|
||||
|
||||
builder.join(
|
||||
joinTable,
|
||||
`${model.tableName}.${field.column}`,
|
||||
'=',
|
||||
field.relation
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
private buildFieldsJoinQueries = (builder, fieldsRelations: string[]) => {
|
||||
fieldsRelations.forEach((fieldRelation) => {
|
||||
const relation = this.model.relationMappings[fieldRelation];
|
||||
|
||||
if (relation) {
|
||||
const splitToRelation = relation.join.to.split('.');
|
||||
const relationTable = splitToRelation[0] || '';
|
||||
|
||||
builder.join(relationTable, relation.join.from, '=', relation.join.to);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,9 +13,14 @@ export default class FilterRoles extends DynamicFilterRoleAbstructor {
|
||||
super();
|
||||
|
||||
this.filterRoles = filterRoles;
|
||||
|
||||
this.setResponseMeta();
|
||||
}
|
||||
|
||||
public onInitialize() {
|
||||
this.setFilterRolesRelations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds filter roles logic expression.
|
||||
* @return {string}
|
||||
@@ -53,4 +58,13 @@ export default class FilterRoles extends DynamicFilterRoleAbstructor {
|
||||
filterRoles: this.filterRoles,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets filter roles relations if field was relation type.
|
||||
*/
|
||||
private setFilterRolesRelations() {
|
||||
this.filterRoles.forEach((relationRole) => {
|
||||
this.setRelationIfRelationField(relationRole.fieldKey);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export default abstract class DynamicFilterAbstructor
|
||||
protected tableName: string;
|
||||
protected model: IModel;
|
||||
protected responseMeta: { [key: string]: any } = {};
|
||||
public relationFields = [];
|
||||
|
||||
/**
|
||||
* Sets model the dynamic filter service.
|
||||
@@ -78,22 +79,50 @@ export default abstract class DynamicFilterAbstructor
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve relation column of comparator fieldز
|
||||
*/
|
||||
private getFieldComparatorRelationColumn(field) {
|
||||
const relation = this.model.relationMappings[field.relationKey];
|
||||
|
||||
if (relation) {
|
||||
const relationModel = relation.modelClass;
|
||||
const relationColumn =
|
||||
field.relationEntityKey === 'id'
|
||||
? 'id'
|
||||
: relationModel.getField(field.relationEntityKey, 'column');
|
||||
|
||||
return `${relationModel.tableName}.${relationColumn}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the comparator field column.
|
||||
* @param {IModel} model -
|
||||
* @param {} -
|
||||
*/
|
||||
private getFieldComparatorColumn = (field) => {
|
||||
return field.fieldType === FIELD_TYPE.RELATION
|
||||
? this.getFieldComparatorRelationColumn(field)
|
||||
: `${this.tableName}.${field.column}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds roles queries.
|
||||
* @param {IModel} model -
|
||||
* @param {Object} role -
|
||||
*/
|
||||
protected buildRoleQuery = (model: IModel, role: IFilterRole) => {
|
||||
const fieldRelation = model.getField(role.fieldKey);
|
||||
const comparatorColumn = `${model.tableName}.${fieldRelation.column}`;
|
||||
const field = model.getField(role.fieldKey);
|
||||
const comparatorColumn = this.getFieldComparatorColumn(field);
|
||||
|
||||
// Field relation custom query.
|
||||
if (typeof fieldRelation.customQuery !== 'undefined') {
|
||||
if (typeof field.filterCustomQuery !== 'undefined') {
|
||||
return (builder) => {
|
||||
fieldRelation.customQuery(builder, role);
|
||||
field.filterCustomQuery(builder, role);
|
||||
};
|
||||
}
|
||||
switch (fieldRelation.fieldType) {
|
||||
switch (field.fieldType) {
|
||||
case FIELD_TYPE.BOOLEAN:
|
||||
case FIELD_TYPE.ENUMERATION:
|
||||
return this.booleanRoleQueryBuilder(role, comparatorColumn);
|
||||
@@ -265,7 +294,7 @@ export default abstract class DynamicFilterAbstructor
|
||||
builder.where(comparatorColumn, '>=', startDate.format(dateFormat));
|
||||
builder.where(comparatorColumn, '<=', endDate.format(dateFormat));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Date query after/before comparator type.
|
||||
@@ -296,5 +325,25 @@ export default abstract class DynamicFilterAbstructor
|
||||
}
|
||||
const comparatorValue = targetDate.format(dateFormat);
|
||||
builder.where(comparatorColumn, comparator, comparatorValue);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers relation field if the given field was relation type
|
||||
* and not registered.
|
||||
* @param {string} fieldKey - Field key.
|
||||
*/
|
||||
protected setRelationIfRelationField = (fieldKey: string): void => {
|
||||
const field = this.model.getField(fieldKey);
|
||||
const isAlreadyRegistered = this.relationFields.some(
|
||||
(field) => field === fieldKey
|
||||
);
|
||||
|
||||
if (
|
||||
!isAlreadyRegistered &&
|
||||
field &&
|
||||
field.fieldType === FIELD_TYPE.RELATION
|
||||
) {
|
||||
this.relationFields.push(field.relationKey);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import DynamicFilterRoleAbstructor from 'lib/DynamicFilter/DynamicFilterRoleAbstructor';
|
||||
import {
|
||||
getRoleFieldColumn,
|
||||
validateFieldKeyExistance,
|
||||
getTableFromRelationColumn,
|
||||
} from 'lib/ViewRolesBuilder';
|
||||
import { FIELD_TYPE } from './constants';
|
||||
|
||||
interface ISortRole {
|
||||
fieldKey: string;
|
||||
@@ -28,17 +24,52 @@ export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
|
||||
this.setResponseMeta();
|
||||
}
|
||||
|
||||
/**
|
||||
* On initialize the dyanmic sort by.
|
||||
*/
|
||||
public onInitialize() {
|
||||
this.setRelationIfRelationField(this.sortRole.fieldKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve field comparator relatin column.
|
||||
* @param field
|
||||
* @returns {string}
|
||||
*/
|
||||
private getFieldComparatorRelationColumn = (field): string => {
|
||||
const relation = this.model.relationMappings[field.relationKey];
|
||||
|
||||
if (relation) {
|
||||
const relationModel = relation.modelClass;
|
||||
const relationField = relationModel.getField(field.relationEntityLabel);
|
||||
|
||||
return `${relationModel.tableName}.${relationField.column}`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the comparator field column.
|
||||
* @param {IModel} field
|
||||
* @returns {string}
|
||||
*/
|
||||
private getFieldComparatorColumn = (field): string => {
|
||||
return field.fieldType === FIELD_TYPE.RELATION
|
||||
? this.getFieldComparatorRelationColumn(field)
|
||||
: `${this.tableName}.${field.column}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds database query of sort by column on the given direction.
|
||||
*/
|
||||
public buildQuery() {
|
||||
public buildQuery = () => {
|
||||
const field = this.model.getField(this.sortRole.fieldKey);
|
||||
const comparatorColumn = `${this.tableName}.${field.column}`;
|
||||
const comparatorColumn = this.getFieldComparatorColumn(field);
|
||||
|
||||
if (typeof field.customSortQuery !== 'undefined') {
|
||||
// Sort custom query.
|
||||
if (typeof field.sortCustomQuery !== 'undefined') {
|
||||
return (builder) => {
|
||||
field.customSortQuery(builder, this.sortRole);
|
||||
field.sortCustomQuery(builder, this.sortRole);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,24 +78,7 @@ export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
|
||||
builder.orderBy(`${comparatorColumn}`, this.sortRole.order);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private joinBuildQuery() {
|
||||
const fieldColumn = getRoleFieldColumn(this.model, this.sortRole.fieldKey);
|
||||
|
||||
return (builder) => {
|
||||
if (fieldColumn.relation) {
|
||||
const joinTable = getTableFromRelationColumn(fieldColumn.relation);
|
||||
|
||||
builder.join(
|
||||
joinTable,
|
||||
`${this.model.tableName}.${fieldColumn.column}`,
|
||||
'=',
|
||||
fieldColumn.relation
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets response meta.
|
||||
|
||||
@@ -33,4 +33,5 @@ export const FIELD_TYPE = {
|
||||
BOOLEAN: 'boolean',
|
||||
RELATION: 'relation',
|
||||
DATE: 'date',
|
||||
COMPUTED: 'computed'
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IModelMeta } from 'interfaces';
|
||||
import { ACCOUNT_TYPES } from 'data/AccountTypes';
|
||||
|
||||
export default {
|
||||
defaultFilterField: 'name',
|
||||
@@ -10,25 +11,26 @@ export default {
|
||||
name: {
|
||||
name: 'Account name',
|
||||
column: 'name',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
description: {
|
||||
name: 'Description',
|
||||
column: 'description',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
slug: {
|
||||
name: 'Account slug',
|
||||
column: 'slug',
|
||||
fieldType: 'text',
|
||||
columnable: false,
|
||||
},
|
||||
code: {
|
||||
name: 'Account code',
|
||||
column: 'code',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
root_type: {
|
||||
name: 'Root type',
|
||||
column: 'root_type',
|
||||
columnable: true,
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'asset', label: 'Asset' },
|
||||
@@ -37,16 +39,37 @@ export default {
|
||||
{ key: 'Income', label: 'Income' },
|
||||
{ key: 'expense', label: 'Expense' },
|
||||
],
|
||||
filterCustomQuery: RootTypeFieldFilterQuery,
|
||||
sortable: false,
|
||||
},
|
||||
normal: {
|
||||
name: 'Account normal',
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'debit', label: 'Debit' },
|
||||
{ key: 'credit', label: 'Credit' },
|
||||
],
|
||||
filterCustomQuery: NormalTypeFieldFilterQuery,
|
||||
sortable: false,
|
||||
},
|
||||
type: {
|
||||
name: 'Type',
|
||||
column: 'account_type',
|
||||
fieldType: 'enumeration',
|
||||
options: ACCOUNT_TYPES.map((accountType) => ({
|
||||
label: accountType.label,
|
||||
key: accountType.key
|
||||
})),
|
||||
},
|
||||
active: {
|
||||
name: 'Active',
|
||||
column: 'active',
|
||||
fieldType: 'boolean',
|
||||
filterable: false,
|
||||
},
|
||||
amount: {
|
||||
balance: {
|
||||
name: 'Account balance',
|
||||
column: 'amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
currency: {
|
||||
@@ -60,4 +83,18 @@ export default {
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
} as IModelMeta;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter query of root type field .
|
||||
*/
|
||||
function RootTypeFieldFilterQuery(query, role) {
|
||||
query.modify('filterByRootType', role.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter query of normal field .
|
||||
*/
|
||||
function NormalTypeFieldFilterQuery(query, role) {
|
||||
query.modify('filterByAccountNormal', role.value);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import DependencyGraph from 'lib/DependencyGraph';
|
||||
import AccountTypesUtils from 'lib/AccountTypes';
|
||||
import AccountSettings from './Account.Settings';
|
||||
import ModelSettings from './ModelSetting';
|
||||
import { ACCOUNT_TYPES } from 'data/AccountTypes';
|
||||
|
||||
export default class Account extends mixin(TenantModel, [ModelSettings]) {
|
||||
/**
|
||||
@@ -98,7 +99,7 @@ export default class Account extends mixin(TenantModel, [ModelSettings]) {
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
query.where('accounts.active', !active);
|
||||
},
|
||||
|
||||
filterAccounts(query, accountIds) {
|
||||
@@ -117,6 +118,28 @@ export default class Account extends mixin(TenantModel, [ModelSettings]) {
|
||||
sortColumnBuilder(query, columnKey, direction) {
|
||||
buildSortColumnQuery(Account.tableName, columnKey, direction)(query);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter by root type.
|
||||
*/
|
||||
filterByRootType(query, rootType) {
|
||||
const filterTypes = ACCOUNT_TYPES.filter(
|
||||
(accountType) => accountType.rootType === rootType
|
||||
).map((accountType) => accountType.key);
|
||||
|
||||
query.whereIn('account_type', filterTypes);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter by account normal
|
||||
*/
|
||||
filterByAccountNormal(query, accountNormal) {
|
||||
const filterTypes = ACCOUNT_TYPES.filter(
|
||||
(accountType) => accountType.normal === accountNormal,
|
||||
).map((accountType) => accountType.key);
|
||||
|
||||
query.whereIn('account_type', filterTypes);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,35 +8,42 @@ export default {
|
||||
sortField: 'bill_date',
|
||||
},
|
||||
fields: {
|
||||
// vendor: {
|
||||
// name: 'Vendor',
|
||||
// column: 'vendor_id',
|
||||
// },
|
||||
'bill_number': {
|
||||
vendor: {
|
||||
name: 'Vendor',
|
||||
column: 'vendor_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'vendor',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
bill_number: {
|
||||
name: 'Bill number',
|
||||
column: 'bill_number',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'bill_date': {
|
||||
bill_date: {
|
||||
name: 'Bill date',
|
||||
column: 'bill_date',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
'due_date': {
|
||||
due_date: {
|
||||
name: 'Due date',
|
||||
column: 'due_date',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
'reference_no': {
|
||||
reference_no: {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'status': {
|
||||
status: {
|
||||
name: 'Status',
|
||||
fieldType: 'enumeration',
|
||||
columnable: true,
|
||||
@@ -48,32 +55,42 @@ export default {
|
||||
{ name: 'Opened', key: 'opened' },
|
||||
{ name: 'Draft', key: 'draft' },
|
||||
],
|
||||
// filterQuery: Bill.statusFieldFilterQuery,
|
||||
// sortQuery: Bill.statusFieldSortQuery,
|
||||
filterCustomQuery: StatusFieldFilterQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
'amount': {
|
||||
amount: {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'payment_amount': {
|
||||
payment_amount: {
|
||||
name: 'Payment amount',
|
||||
column: 'payment_amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'note': {
|
||||
note: {
|
||||
name: 'Note',
|
||||
column: 'note',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'created_at': {
|
||||
created_at: {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
} as IModelMeta;
|
||||
};
|
||||
|
||||
/**
|
||||
* Status field filter custom query.
|
||||
*/
|
||||
function StatusFieldFilterQuery(query, role) {
|
||||
query.modify('statusFilter', role.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status field sort custom query.
|
||||
*/
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
|
||||
@@ -71,15 +71,42 @@ export default class Bill extends mixin(TenantModel, [ModelSetting]) {
|
||||
* Filters the bills from the given date.
|
||||
*/
|
||||
fromDate(query, fromDate) {
|
||||
query.where('bill_date', '<=', fromDate)
|
||||
query.where('bill_date', '<=', fromDate);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sort the bills by full-payment bills.
|
||||
*/
|
||||
sortByStatus(query, order) {
|
||||
sortByStatus(query, order) {
|
||||
query.orderByRaw(`PAYMENT_AMOUNT = AMOUNT ${order}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Status filter.
|
||||
*/
|
||||
statusFilter(query, filterType) {
|
||||
switch (filterType) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'delivered':
|
||||
query.modify('delivered');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
case 'overdue':
|
||||
default:
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'partially-paid':
|
||||
query.modify('partiallyPaid');
|
||||
break;
|
||||
case 'paid':
|
||||
query.modify('paid');
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,7 +130,7 @@ export default class Bill extends mixin(TenantModel, [ModelSetting]) {
|
||||
'remainingDays',
|
||||
'overdueDays',
|
||||
'isOverdue',
|
||||
'unallocatedCostAmount'
|
||||
'unallocatedCostAmount',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -276,32 +303,4 @@ export default class Bill extends mixin(TenantModel, [ModelSetting]) {
|
||||
.where('id', billId)
|
||||
[changeMethod]('payment_amount', Math.abs(amount));
|
||||
}
|
||||
|
||||
|
||||
static statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'opened':
|
||||
query.modify('opened');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'partially-paid':
|
||||
query.modify('partiallyPaid');
|
||||
break;
|
||||
case 'paid':
|
||||
query.modify('paid');
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
static statusFieldSortQuery(query, role) {
|
||||
return query.modify('sortByStatus', role.order);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { IModelMeta } from 'interfaces';
|
||||
|
||||
export default {
|
||||
defaultFilterField: 'vendor',
|
||||
@@ -10,51 +9,58 @@ export default {
|
||||
'vendor': {
|
||||
name: 'Vendor name',
|
||||
column: 'vendor_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'vendor',
|
||||
|
||||
relationEntityLabel: 'display_name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'due_amount': {
|
||||
name: 'Due amount',
|
||||
column: 'due_amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'payment_account': {
|
||||
name: 'Payment account',
|
||||
column: 'payment_account_id',
|
||||
|
||||
fieldType: 'relation',
|
||||
fieldRelation: 'paymentAccount',
|
||||
|
||||
fieldRelationType: 'enumeration',
|
||||
relationLabelField: 'name',
|
||||
relationKeyField: 'slug',
|
||||
},
|
||||
'payment_number': {
|
||||
name: 'Payment number',
|
||||
column: 'payment_number',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'payment_date': {
|
||||
name: 'Payment date',
|
||||
column: 'payment_date',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'description': {
|
||||
name: 'Description',
|
||||
column: 'description',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -31,7 +31,7 @@ export default class BillPayment extends mixin(TenantModel, [ModelSetting]) {
|
||||
static get relationMappings() {
|
||||
const BillPaymentEntry = require("models/BillPaymentEntry");
|
||||
const AccountTransaction = require("models/AccountTransaction");
|
||||
const Contact = require("models/Contact");
|
||||
const Vendor = require("models/Vendor");
|
||||
const Account = require("models/Account");
|
||||
|
||||
return {
|
||||
@@ -46,7 +46,7 @@ export default class BillPayment extends mixin(TenantModel, [ModelSetting]) {
|
||||
|
||||
vendor: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Contact.default,
|
||||
modelClass: Vendor.default,
|
||||
join: {
|
||||
from: "bills_payments.vendorId",
|
||||
to: "contacts.id",
|
||||
|
||||
@@ -16,23 +16,19 @@ export default {
|
||||
'payment_account': {
|
||||
name: 'Payment account',
|
||||
column: 'payment_account_id',
|
||||
|
||||
fieldType: 'relation',
|
||||
fieldRelation: 'paymentAccount',
|
||||
|
||||
fieldRelationType: 'enumeration',
|
||||
relationLabelField: 'name',
|
||||
relationKeyField: 'slug',
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'paymentAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'total_amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
// currency_code: {
|
||||
// name: 'Currency',
|
||||
// column: 'currency_code',
|
||||
// },
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
@@ -55,8 +51,8 @@ export default {
|
||||
{ key: 'draft', name: 'Draft' },
|
||||
{ key: 'published', name: 'Published' },
|
||||
],
|
||||
filterQuery: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
filterCustomQuery: StatusFieldFilterQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
@@ -66,17 +62,10 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('filterByDraft');
|
||||
break;
|
||||
case 'published':
|
||||
query.modify('filterByPublished');
|
||||
break;
|
||||
}
|
||||
function StatusFieldFilterQuery(query, role) {
|
||||
query.modify('filterByStatus', role.value);
|
||||
}
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
return query.modify('sortByStatus', role.order);
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
|
||||
@@ -27,13 +27,8 @@ export default class Expense extends mixin(TenantModel, [ModelSetting]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to mark model as resourceable to viewable and filterable.
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get resourceable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static get virtualAttributes() {
|
||||
return ['isPublished', 'unallocatedCostAmount'];
|
||||
}
|
||||
@@ -92,6 +87,18 @@ export default class Expense extends mixin(TenantModel, [ModelSetting]) {
|
||||
filterByPublished(query) {
|
||||
query.whereNot('published_at', null);
|
||||
},
|
||||
|
||||
filterByStatus(query, status) {
|
||||
switch (status) {
|
||||
case 'draft':
|
||||
query.modify('filterByDraft');
|
||||
break;
|
||||
case 'published':
|
||||
default:
|
||||
query.modify('filterByPublished');
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ export default {
|
||||
name: 'Date',
|
||||
column: 'date',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
'type': {
|
||||
name: 'Adjustment type',
|
||||
@@ -19,42 +18,42 @@ export default {
|
||||
{ key: 'increment', name: 'Increment' },
|
||||
{ key: 'decrement', name: 'Decrement' },
|
||||
],
|
||||
columnable: true,
|
||||
},
|
||||
'adjustment_account': {
|
||||
name: 'Adjustment account',
|
||||
column: 'adjustment_account_id',
|
||||
columnable: true,
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'adjustmentAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'reason': {
|
||||
name: 'Reason',
|
||||
column: 'reason',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
'description': {
|
||||
name: 'Description',
|
||||
column: 'description',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
'published_at': {
|
||||
name: 'Published at',
|
||||
column: 'published_at',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import InventoryAdjustmentSettings from './InventoryAdjustment.Settings';
|
||||
import ModelSetting from './ModelSetting';
|
||||
|
||||
export default class InventoryAdjustment extends TenantModel {
|
||||
export default class InventoryAdjustment extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ export default {
|
||||
'type': {
|
||||
name: 'Item type',
|
||||
column: 'type',
|
||||
columnable: true,
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'inventory', label: 'Inventory', },
|
||||
@@ -19,13 +18,11 @@ export default {
|
||||
'name': {
|
||||
name: 'Name',
|
||||
column: 'name',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'code': {
|
||||
name: 'Code',
|
||||
column: 'code',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'sellable': {
|
||||
@@ -51,15 +48,34 @@ export default {
|
||||
'cost_account': {
|
||||
name: 'Cost account',
|
||||
column: 'cost_account_id',
|
||||
columnable: true,
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'costAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'sell_account': {
|
||||
name: 'Sell account',
|
||||
column: 'sell_account_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'sellAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'inventory_account': {
|
||||
name: 'Inventory account',
|
||||
column: 'inventory_account_id',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'inventoryAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'sell_description': {
|
||||
name: 'Sell description',
|
||||
@@ -80,17 +96,22 @@ export default {
|
||||
name: 'Note',
|
||||
column: 'note',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
'category': {
|
||||
name: 'Category',
|
||||
column: 'category_id',
|
||||
columnable: true,
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'category',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
'active': {
|
||||
name: 'Active',
|
||||
column: 'active',
|
||||
fieldType: 'boolean',
|
||||
filterable: false,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
|
||||
@@ -42,7 +42,7 @@ export default class Item extends mixin(TenantModel, [ModelSetting]) {
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
query.where('items.active', !active);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,22 +15,11 @@ export default {
|
||||
column: 'description',
|
||||
fieldType: 'text',
|
||||
},
|
||||
cost_account: {
|
||||
label: 'Cost account',
|
||||
column: 'cost_account_id',
|
||||
},
|
||||
sell_account: {
|
||||
label: 'Sell account',
|
||||
column: 'sell_account_id',
|
||||
},
|
||||
inventory_account: {
|
||||
label: 'Inventory account',
|
||||
column: 'inventory_account_id',
|
||||
},
|
||||
count: {
|
||||
label: 'Count',
|
||||
column: 'count',
|
||||
sortQuery: this.sortCountQuery,
|
||||
fieldType: 'number',
|
||||
virtualColumn: true,
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import path from 'path';
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import ItemCategorySettings from './ItemCategory.Settings';
|
||||
|
||||
export default class ItemCategory extends TenantModel {
|
||||
export default class ItemCategory extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
@@ -10,10 +11,6 @@ export default class ItemCategory extends TenantModel {
|
||||
return 'items_categories';
|
||||
}
|
||||
|
||||
static get resourceable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
@@ -42,7 +39,24 @@ export default class ItemCategory extends TenantModel {
|
||||
};
|
||||
}
|
||||
|
||||
static sortCountQuery(query, role) {
|
||||
query.orderBy('count', role.order);
|
||||
}
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
sortByCount(query, order = 'asc') {
|
||||
query.orderBy('count', order);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Model meta.
|
||||
*/
|
||||
static get meta() {
|
||||
return ItemCategorySettings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
label: 'Status',
|
||||
column: 'status',
|
||||
fieldType: 'enumeration',
|
||||
sortQuery: statusFieldSortQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
label: 'Created at',
|
||||
@@ -49,6 +49,6 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
return query.modify('sortByStatus', role.order);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@ export default (Model) =>
|
||||
* @param {string} key
|
||||
* @returns {IModelMetaField}
|
||||
*/
|
||||
public static getField(key: string): IModelMetaField {
|
||||
return get(this.meta.fields, key);
|
||||
public static getField(key: string, attribute?:string): IModelMetaField {
|
||||
const field = get(this.meta.fields, key);
|
||||
|
||||
return attribute ? get(field, attribute) : field;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,13 @@ export default {
|
||||
customer: {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'customer',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
payment_date: {
|
||||
name: 'Payment date',
|
||||
@@ -23,6 +30,13 @@ export default {
|
||||
deposit_account: {
|
||||
name: 'Deposit account',
|
||||
column: 'deposit_account_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'depositAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
payment_receive_no: {
|
||||
name: 'Payment receive No.',
|
||||
|
||||
@@ -18,6 +18,13 @@ export default {
|
||||
'customer': {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'customer',
|
||||
|
||||
relationEntityLabel: 'display_name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
'estimate_date': {
|
||||
name: 'Estimate date',
|
||||
@@ -46,8 +53,16 @@ export default {
|
||||
},
|
||||
'status': {
|
||||
name: 'Status',
|
||||
filterQuery: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ name: 'Delivered', key: 'delivered' },
|
||||
{ name: 'Rejected', key: 'rejected' },
|
||||
{ name: 'Approved', key: 'approved' },
|
||||
{ name: 'Delivered', key: 'delivered' },
|
||||
{ name: 'Draft', key: 'draft' },
|
||||
],
|
||||
filterCustomQuery: StatusFieldFilterQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
@@ -57,29 +72,10 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
return query.modify('orderByDraft', role.order);
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
query.modify('orderByStatus', role.order);
|
||||
}
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'delivered':
|
||||
query.modify('delivered');
|
||||
break;
|
||||
case 'approved':
|
||||
query.modify('approved');
|
||||
break;
|
||||
case 'rejected':
|
||||
query.modify('rejected');
|
||||
break;
|
||||
case 'invoiced':
|
||||
query.modify('invoiced');
|
||||
break;
|
||||
case 'expired':
|
||||
query.modify('expired');
|
||||
break;
|
||||
}
|
||||
function StatusFieldFilterQuery(query, role) {
|
||||
query.modify('filterByStatus', role.value);
|
||||
}
|
||||
|
||||
@@ -128,9 +128,34 @@ export default class SaleEstimate extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Sorting the estimates orders by delivery status.
|
||||
*/
|
||||
orderByDraft(query, order) {
|
||||
orderByStatus(query, order) {
|
||||
query.orderByRaw(`delivered_at is null ${order}`);
|
||||
},
|
||||
/**
|
||||
* Filtering the estimates oreders by status field.
|
||||
*/
|
||||
filterByStatus(query, filterType) {
|
||||
switch (filterType) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'delivered':
|
||||
query.modify('delivered');
|
||||
break;
|
||||
case 'approved':
|
||||
query.modify('approved');
|
||||
break;
|
||||
case 'rejected':
|
||||
query.modify('rejected');
|
||||
break;
|
||||
case 'invoiced':
|
||||
query.modify('invoiced');
|
||||
break;
|
||||
case 'expired':
|
||||
query.modify('expired');
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,50 +5,50 @@ export default {
|
||||
sortField: 'created_at',
|
||||
},
|
||||
fields: {
|
||||
// customer: {
|
||||
// name: 'Customer',
|
||||
// column: 'customer_id',
|
||||
// },
|
||||
customer: {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'customer',
|
||||
|
||||
relationEntityLabel: 'display_name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
invoice_date: {
|
||||
name: 'Invoice date',
|
||||
column: 'invoice_date',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
due_date: {
|
||||
name: 'Due date',
|
||||
column: 'due_date',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
invoice_no: {
|
||||
name: 'Invoice No.',
|
||||
column: 'invoice_no',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
reference_no: {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
invoice_message: {
|
||||
name: 'Invoice message',
|
||||
column: 'invoice_message',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
terms_conditions: {
|
||||
name: 'Terms & conditions',
|
||||
column: 'terms_conditions',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
amount: {
|
||||
name: 'Invoice amount',
|
||||
column: 'balance',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
payment_amount: {
|
||||
@@ -56,31 +56,45 @@ export default {
|
||||
column: 'payment_amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
due_amount: {
|
||||
due_amount: { // calculated.
|
||||
name: 'Due amount',
|
||||
column: 'due_amount',
|
||||
fieldType: 'number',
|
||||
// sortQuery: SaleInvoice.dueAmountFieldSortQuery,
|
||||
virtualColumn: true,
|
||||
},
|
||||
status: {
|
||||
name: 'Status',
|
||||
columnable: true,
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'draft', name: 'Draft' },
|
||||
{ key: 'delivered', name: 'Delivered' },
|
||||
{ key: 'unpaid', name: 'Unpaid' },
|
||||
{ key: 'overdue', name: 'Overdue' },
|
||||
{ key: 'partially-paid', name: 'Partially paid' },
|
||||
{ key: 'paid', name: 'Paid' },
|
||||
],
|
||||
filterCustomQuery: StatusFieldFilterQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
created_at: {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
// status: {
|
||||
// name: 'Status',
|
||||
// columnable: true,
|
||||
// fieldType: 'enumeration',
|
||||
// options: [
|
||||
// { key: 'draft', name: 'Draft' },
|
||||
// { key: 'delivered', name: 'Delivered' },
|
||||
// { key: 'unpaid', name: 'Unpaid' },
|
||||
// { key: 'overdue', name: 'Overdue' },
|
||||
// { key: 'partially-paid', name: 'Partially paid' },
|
||||
// { key: 'paid', name: 'Paid' },
|
||||
// ],
|
||||
// // filterQuery: SaleInvoice.statusFieldFilterQuery,
|
||||
// // sortQuery: SaleInvoice.statusFieldSortQuery,
|
||||
// },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Status field filter custom query.
|
||||
*/
|
||||
function StatusFieldFilterQuery(query, role) {
|
||||
query.modify('statusFilter', role.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status field sort custom query.
|
||||
*/
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
@@ -108,10 +108,6 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
return this.getOverdueDays();
|
||||
}
|
||||
|
||||
static get resourceable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} asDate
|
||||
@@ -231,6 +227,33 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
byPrefixAndNumber(query, prefix, number) {
|
||||
query.where('invoice_no', `${prefix}${number}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Status filter.
|
||||
*/
|
||||
statusFilter(query, filterType) {
|
||||
switch (filterType) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'delivered':
|
||||
query.modify('delivered');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
case 'overdue':
|
||||
default:
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'partially-paid':
|
||||
query.modify('partiallyPaid');
|
||||
break;
|
||||
case 'paid':
|
||||
query.modify('paid');
|
||||
break;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -240,7 +263,7 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
static get relationMappings() {
|
||||
const AccountTransaction = require('models/AccountTransaction');
|
||||
const ItemEntry = require('models/ItemEntry');
|
||||
const Contact = require('models/Contact');
|
||||
const Customer = require('models/Customer');
|
||||
const InventoryCostLotTracker = require('models/InventoryCostLotTracker');
|
||||
const PaymentReceiveEntry = require('models/PaymentReceiveEntry');
|
||||
|
||||
@@ -265,7 +288,7 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
*/
|
||||
customer: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Contact.default,
|
||||
modelClass: Customer.default,
|
||||
join: {
|
||||
from: 'sales_invoices.customerId',
|
||||
to: 'contacts.id',
|
||||
@@ -336,31 +359,4 @@ export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
static dueAmountFieldSortQuery(query, role) {
|
||||
query.modify('sortByDueAmount', role.order);
|
||||
}
|
||||
|
||||
static statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'delivered':
|
||||
query.modify('delivered');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'partially-paid':
|
||||
query.modify('partiallyPaid');
|
||||
break;
|
||||
case 'paid':
|
||||
query.modify('paid');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static statusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,53 +9,59 @@ export default {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
fieldType: 'number',
|
||||
columnable: true
|
||||
},
|
||||
'deposit_account': {
|
||||
column: 'deposit_account_id',
|
||||
name: 'Deposit account',
|
||||
columnable: true
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'depositAccount',
|
||||
|
||||
relationEntityLabel: 'name',
|
||||
relationEntityKey: 'slug',
|
||||
},
|
||||
'customer': {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
columnable: true
|
||||
fieldType: 'relation',
|
||||
|
||||
relationType: 'enumeration',
|
||||
relationKey: 'customer',
|
||||
|
||||
relationEntityLabel: 'display_name',
|
||||
relationEntityKey: 'id',
|
||||
},
|
||||
'receipt_date': {
|
||||
name: 'Receipt date',
|
||||
column: 'receipt_date',
|
||||
fieldType: 'date',
|
||||
columnable: true
|
||||
|
||||
},
|
||||
'receipt_number': {
|
||||
name: 'Receipt No.',
|
||||
column: 'receipt_number',
|
||||
fieldType: 'text',
|
||||
columnable: true
|
||||
},
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
fieldType: 'text',
|
||||
columnable: true
|
||||
},
|
||||
'receipt_message': {
|
||||
name: 'Receipt message',
|
||||
column: 'receipt_message',
|
||||
fieldType: 'text',
|
||||
columnable: true
|
||||
},
|
||||
'statement': {
|
||||
name: 'Statement',
|
||||
column: 'statement',
|
||||
fieldType: 'text',
|
||||
columnable: true
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
columnable: true
|
||||
},
|
||||
'status': {
|
||||
name: 'Status',
|
||||
@@ -64,24 +70,16 @@ export default {
|
||||
{ key: 'draft', name: 'Draft' },
|
||||
{ key: 'closed', name: 'Closed' },
|
||||
],
|
||||
query: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
columnable: true
|
||||
filterCustomQuery: StatusFieldFilterQuery,
|
||||
sortCustomQuery: StatusFieldSortQuery,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'closed':
|
||||
query.modify('closed');
|
||||
break;
|
||||
}
|
||||
function StatusFieldFilterQuery(query, role) {
|
||||
query.modify('filterByStatus', role.value);
|
||||
}
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
function StatusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,21 @@ export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
|
||||
sortByStatus(query, order) {
|
||||
query.orderByRaw(`CLOSED_AT IS NULL ${order}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filtering the receipts orders by status.
|
||||
*/
|
||||
filterByStatus(query, status) {
|
||||
switch (status) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'closed':
|
||||
default:
|
||||
query.modify('closed');
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,7 +88,7 @@ export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const Contact = require('models/Contact');
|
||||
const Customer = require('models/Customer');
|
||||
const Account = require('models/Account');
|
||||
const AccountTransaction = require('models/AccountTransaction');
|
||||
const ItemEntry = require('models/ItemEntry');
|
||||
@@ -81,7 +96,7 @@ export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
|
||||
return {
|
||||
customer: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Contact.default,
|
||||
modelClass: Customer.default,
|
||||
join: {
|
||||
from: 'sales_receipts.customerId',
|
||||
to: 'contacts.id',
|
||||
|
||||
@@ -30,6 +30,8 @@ export default class DynamicListService implements IDynamicListService {
|
||||
|
||||
/**
|
||||
* Parses filter DTO.
|
||||
* @param {IMode} model -
|
||||
* @param {} filterDTO -
|
||||
*/
|
||||
private parseFilterObject = (model, filterDTO) => {
|
||||
return {
|
||||
|
||||
@@ -268,8 +268,7 @@ export default class InventoryAdjustmentService {
|
||||
|
||||
/**
|
||||
* Parses inventory adjustments list filter DTO.
|
||||
* @param filterDTO
|
||||
* @returns
|
||||
* @param filterDTO -
|
||||
*/
|
||||
private parseListFilterDTO(filterDTO) {
|
||||
return R.compose(
|
||||
@@ -282,7 +281,7 @@ export default class InventoryAdjustmentService {
|
||||
* @param {number} tenantId
|
||||
* @param {IInventoryAdjustmentsFilter} adjustmentsFilter
|
||||
*/
|
||||
async getInventoryAdjustments(
|
||||
public async getInventoryAdjustments(
|
||||
tenantId: number,
|
||||
filterDTO: IInventoryAdjustmentsFilter
|
||||
): Promise<{
|
||||
|
||||
@@ -412,6 +412,7 @@ export default class ItemCategoriesService implements IItemCategoriesService {
|
||||
filter
|
||||
);
|
||||
|
||||
// Items categories.
|
||||
const itemCategories = await ItemCategory.query().onBuild((query) => {
|
||||
// Subquery to calculate sumation of assocaited items to the item category.
|
||||
query.select('*', ItemCategory.relatedQuery('items').count().as('count'));
|
||||
|
||||
Reference in New Issue
Block a user