mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
feat: optimize dynamic list service.
feat: inactive mode for accounts, items, customers and vendors services.
This commit is contained in:
63
server/src/models/Account.Settings.ts
Normal file
63
server/src/models/Account.Settings.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { IModelMeta } from 'interfaces';
|
||||
|
||||
export default {
|
||||
defaultFilterField: 'name',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'name',
|
||||
},
|
||||
fields: {
|
||||
name: {
|
||||
name: 'Account name',
|
||||
column: 'name',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
description: {
|
||||
name: 'Description',
|
||||
column: 'description',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
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' },
|
||||
{ key: 'liability', label: 'Liability' },
|
||||
{ key: 'equity', label: 'Equity' },
|
||||
{ key: 'Income', label: 'Income' },
|
||||
{ key: 'expense', label: 'Expense' },
|
||||
],
|
||||
},
|
||||
active: {
|
||||
name: 'Active',
|
||||
column: 'active',
|
||||
fieldType: 'boolean',
|
||||
},
|
||||
amount: {
|
||||
name: 'Account balance',
|
||||
column: 'amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
currency: {
|
||||
name: 'Currency',
|
||||
column: 'currency_code',
|
||||
fieldType: 'text',
|
||||
},
|
||||
created_at: {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
} as IModelMeta;
|
||||
@@ -1,16 +1,15 @@
|
||||
/* eslint-disable global-require */
|
||||
import { Model } from 'objection';
|
||||
import { flatten, castArray } from 'lodash';
|
||||
import { mixin, Model } from 'objection';
|
||||
import { castArray } from 'lodash';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import {
|
||||
buildFilterQuery,
|
||||
buildSortColumnQuery,
|
||||
} from 'lib/ViewRolesBuilder';
|
||||
import { buildFilterQuery, buildSortColumnQuery } from 'lib/ViewRolesBuilder';
|
||||
import { flatToNestedArray } from 'utils';
|
||||
import DependencyGraph from 'lib/DependencyGraph';
|
||||
import AccountTypesUtils from 'lib/AccountTypes'
|
||||
import AccountTypesUtils from 'lib/AccountTypes';
|
||||
import AccountSettings from './Account.Settings';
|
||||
import ModelSettings from './ModelSetting';
|
||||
|
||||
export default class Account extends TenantModel {
|
||||
export default class Account extends mixin(TenantModel, [ModelSettings]) {
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
@@ -21,7 +20,7 @@ export default class Account extends TenantModel {
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
static get timestamps() {
|
||||
return ['createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
@@ -35,7 +34,7 @@ export default class Account extends TenantModel {
|
||||
'accountRootType',
|
||||
'accountNormal',
|
||||
'isBalanceSheetAccount',
|
||||
'isPLSheet'
|
||||
'isPLSheet',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -95,6 +94,13 @@ export default class Account extends TenantModel {
|
||||
const TABLE_NAME = Account.tableName;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
},
|
||||
|
||||
filterAccounts(query, accountIds) {
|
||||
if (accountIds.length > 0) {
|
||||
query.whereIn(`${TABLE_NAME}.id`, accountIds);
|
||||
@@ -134,10 +140,10 @@ export default class Account extends TenantModel {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detarmines whether the given type equals the account type.
|
||||
* @param {string} accountType
|
||||
* @param {string} accountType
|
||||
* @return {boolean}
|
||||
*/
|
||||
isAccountType(accountType) {
|
||||
@@ -147,7 +153,7 @@ export default class Account extends TenantModel {
|
||||
|
||||
/**
|
||||
* Detarmines whether the given root type equals the account type.
|
||||
* @param {string} rootType
|
||||
* @param {string} rootType
|
||||
* @return {boolean}
|
||||
*/
|
||||
isRootType(rootType) {
|
||||
@@ -156,11 +162,14 @@ export default class Account extends TenantModel {
|
||||
|
||||
/**
|
||||
* Detarmine whether the given parent type equals the account type.
|
||||
* @param {string} parentType
|
||||
* @param {string} parentType
|
||||
* @return {boolean}
|
||||
*/
|
||||
isParentType(parentType) {
|
||||
return AccountTypesUtils.isParentTypeEqualsKey(this.accountType, parentType);
|
||||
return AccountTypesUtils.isParentTypeEqualsKey(
|
||||
this.accountType,
|
||||
parentType
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,105 +197,32 @@ export default class Account extends TenantModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts flatten accounts list to nested array.
|
||||
* @param {Array} accounts
|
||||
* @param {Object} options
|
||||
* Converts flatten accounts list to nested array.
|
||||
* @param {Array} accounts
|
||||
* @param {Object} options
|
||||
*/
|
||||
static toNestedArray(accounts, options = { children: 'children' }) {
|
||||
return flatToNestedArray(accounts, { id: 'id', parentId: 'parentAccountId' })
|
||||
return flatToNestedArray(accounts, {
|
||||
id: 'id',
|
||||
parentId: 'parentAccountId',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transformes the accounts list to depenedency graph structure.
|
||||
* @param {IAccount[]} accounts
|
||||
*/
|
||||
* @param {IAccount[]} accounts
|
||||
*/
|
||||
static toDependencyGraph(accounts) {
|
||||
return DependencyGraph.fromArray(
|
||||
accounts, { itemId: 'id', parentItemId: 'parentAccountId' }
|
||||
);
|
||||
return DependencyGraph.fromArray(accounts, {
|
||||
itemId: 'id',
|
||||
parentItemId: 'parentAccountId',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
* Model settings.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
name: {
|
||||
label: 'Account name',
|
||||
column: 'name',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
type: {
|
||||
label: 'Account type',
|
||||
column: 'account_type',
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
columnType: 'string',
|
||||
|
||||
fieldType: 'text',
|
||||
},
|
||||
code: {
|
||||
label: 'Account code',
|
||||
column: 'code',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
root_type: {
|
||||
label: 'Root type',
|
||||
options: [
|
||||
{ key: 'asset', label: 'Asset', },
|
||||
{ key: 'liability', label: 'Liability' },
|
||||
{ key: 'equity', label: 'Equity' },
|
||||
{ key: 'Income', label: 'Income' },
|
||||
{ key: 'expense', label: 'Expense' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
const accountsTypes = AccountTypesUtils.getTypesByRootType(role.value);
|
||||
const accountsTypesKeys = accountsTypes.map(type => type.key);
|
||||
|
||||
query.whereIn('account_type', accountsTypesKeys);
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
active: {
|
||||
label: 'Active',
|
||||
column: 'active',
|
||||
columnType: 'boolean',
|
||||
fieldType: 'checkbox',
|
||||
},
|
||||
balance: {
|
||||
label: 'Balance',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
currency: {
|
||||
label: 'Currency',
|
||||
column: 'currency_code',
|
||||
fieldType: 'options',
|
||||
optionsResource: 'currency',
|
||||
optionsKey: 'currency_code',
|
||||
optionsLabel: 'currency_name',
|
||||
},
|
||||
normal: {
|
||||
label: 'Account normal',
|
||||
column: 'account_type_id',
|
||||
fieldType: 'options',
|
||||
relation: 'account_types.id',
|
||||
relationColumn: 'account_types.normal',
|
||||
options: [
|
||||
{ key: 'credit', label: 'Credit' },
|
||||
{ key: 'debit', label: 'Debit' },
|
||||
],
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return AccountSettings;
|
||||
}
|
||||
}
|
||||
|
||||
79
server/src/models/Bill.Settings.ts
Normal file
79
server/src/models/Bill.Settings.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { IModelMeta } from 'interfaces';
|
||||
import Bill from './Bill';
|
||||
|
||||
export default {
|
||||
defaultFilterField: 'vendor',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'bill_date',
|
||||
},
|
||||
fields: {
|
||||
// vendor: {
|
||||
// name: 'Vendor',
|
||||
// column: 'vendor_id',
|
||||
// },
|
||||
'bill_number': {
|
||||
name: 'Bill number',
|
||||
column: 'bill_number',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'bill_date': {
|
||||
name: 'Bill date',
|
||||
column: 'bill_date',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
'due_date': {
|
||||
name: 'Due date',
|
||||
column: 'due_date',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'status': {
|
||||
name: 'Status',
|
||||
fieldType: 'enumeration',
|
||||
columnable: true,
|
||||
options: [
|
||||
{ name: 'Paid', key: 'paid' },
|
||||
{ name: 'Partially paid', key: 'partially-paid' },
|
||||
{ name: 'Overdue', key: 'overdue' },
|
||||
{ name: 'Unpaid', key: 'unpaid' },
|
||||
{ name: 'Opened', key: 'opened' },
|
||||
{ name: 'Draft', key: 'draft' },
|
||||
],
|
||||
// filterQuery: Bill.statusFieldFilterQuery,
|
||||
// sortQuery: Bill.statusFieldSortQuery,
|
||||
},
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'payment_amount': {
|
||||
name: 'Payment amount',
|
||||
column: 'payment_amount',
|
||||
columnable: true,
|
||||
fieldType: 'number',
|
||||
},
|
||||
'note': {
|
||||
name: 'Note',
|
||||
column: 'note',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
columnable: true,
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
} as IModelMeta;
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Model, raw } from 'objection';
|
||||
import { Model, raw, mixin } from 'objection';
|
||||
import moment from 'moment';
|
||||
import { difference } from 'lodash';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { query } from 'winston';
|
||||
import BillSettings from './Bill.Settings';
|
||||
import ModelSetting from './ModelSetting';
|
||||
|
||||
export default class Bill extends TenantModel {
|
||||
export default class Bill extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -12,10 +13,9 @@ export default class Bill extends TenantModel {
|
||||
return 'bills';
|
||||
}
|
||||
|
||||
static get resourceable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
@@ -198,6 +198,13 @@ export default class Bill extends TenantModel {
|
||||
return Math.max(date.diff(dueDate, 'days'), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bill model settings.
|
||||
*/
|
||||
static get meta() {
|
||||
return BillSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
@@ -270,87 +277,31 @@ export default class Bill extends TenantModel {
|
||||
[changeMethod]('payment_amount', Math.abs(amount));
|
||||
}
|
||||
|
||||
static get fields() {
|
||||
return {
|
||||
vendor: {
|
||||
label: 'Vendor',
|
||||
column: 'vendor_id',
|
||||
relation: 'contacts.id',
|
||||
relationColumn: 'contacts.display_name',
|
||||
},
|
||||
bill_number: {
|
||||
label: 'Bill number',
|
||||
column: 'bill_number',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
bill_date: {
|
||||
label: 'Bill date',
|
||||
column: 'bill_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
due_date: {
|
||||
label: 'Due date',
|
||||
column: 'due_date',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [],
|
||||
query: (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;
|
||||
}
|
||||
},
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
},
|
||||
},
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
payment_amount: {
|
||||
label: 'Payment amount',
|
||||
column: 'payment_amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
note: {
|
||||
label: 'Note',
|
||||
column: 'note',
|
||||
},
|
||||
user: {},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
61
server/src/models/BillPayment.Settings.ts
Normal file
61
server/src/models/BillPayment.Settings.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { IModelMeta } from 'interfaces';
|
||||
|
||||
export default {
|
||||
defaultFilterField: 'vendor',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'bill_date',
|
||||
},
|
||||
fields: {
|
||||
'vendor': {
|
||||
name: 'Vendor name',
|
||||
column: 'vendor_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',
|
||||
},
|
||||
'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',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Model } from "objection";
|
||||
import { Model, mixin } from "objection";
|
||||
import TenantModel from "models/TenantModel";
|
||||
import ModelSetting from "./ModelSetting";
|
||||
import BillPaymentSettings from "./BillPayment.Settings";
|
||||
|
||||
export default class BillPayment extends TenantModel {
|
||||
export default class BillPayment extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -16,8 +18,11 @@ export default class BillPayment extends TenantModel {
|
||||
return ["createdAt", "updatedAt"];
|
||||
}
|
||||
|
||||
static get resourceable() {
|
||||
return true;
|
||||
/**
|
||||
* Model settings.
|
||||
*/
|
||||
static get meta() {
|
||||
return BillPaymentSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,70 +78,4 @@ export default class BillPayment extends TenantModel {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource fields.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
vendor: {
|
||||
label: "Vendor name",
|
||||
column: "vendor_id",
|
||||
relation: "contacts.id",
|
||||
relationColumn: "contacts.display_name",
|
||||
},
|
||||
amount: {
|
||||
label: "Amount",
|
||||
column: "amount",
|
||||
columnType: "number",
|
||||
fieldType: "number",
|
||||
},
|
||||
due_amount: {
|
||||
label: "Due amount",
|
||||
column: "due_amount",
|
||||
columnType: "number",
|
||||
fieldType: "number",
|
||||
},
|
||||
payment_account: {
|
||||
label: "Payment account",
|
||||
column: "payment_account_id",
|
||||
relation: "accounts.id",
|
||||
relationColumn: "accounts.name",
|
||||
|
||||
fieldType: "options",
|
||||
optionsResource: "Account",
|
||||
optionsKey: "id",
|
||||
optionsLabel: "name",
|
||||
},
|
||||
payment_number: {
|
||||
label: "Payment number",
|
||||
column: "payment_number",
|
||||
columnType: "string",
|
||||
fieldType: "text",
|
||||
},
|
||||
payment_date: {
|
||||
label: "Payment date",
|
||||
column: "payment_date",
|
||||
columnType: "date",
|
||||
fieldType: "date",
|
||||
},
|
||||
reference_no: {
|
||||
label: "Reference No.",
|
||||
column: "reference",
|
||||
columnType: "string",
|
||||
fieldType: "text",
|
||||
},
|
||||
description: {
|
||||
label: "Description",
|
||||
column: "description",
|
||||
columnType: "string",
|
||||
fieldType: "text",
|
||||
},
|
||||
created_at: {
|
||||
label: "Created at",
|
||||
column: "created_at",
|
||||
columnType: "date",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
98
server/src/models/Customer.Settings.ts
Normal file
98
server/src/models/Customer.Settings.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
export default {
|
||||
fields: {
|
||||
display_name: {
|
||||
name: 'Display name',
|
||||
column: 'display_name',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
email: {
|
||||
name: 'Email',
|
||||
column: 'email',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
work_phone: {
|
||||
name: 'Work phone',
|
||||
column: 'work_phone',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
personal_phone: {
|
||||
name: 'Personal phone',
|
||||
column: 'personal_phone',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
company_name: {
|
||||
name: 'Company name',
|
||||
column: 'company_name',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
website: {
|
||||
name: 'Website',
|
||||
column: 'website',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
created_at: {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
balance: {
|
||||
name: 'Balance',
|
||||
column: 'balance',
|
||||
fieldType: 'number',
|
||||
columnable: true,
|
||||
},
|
||||
opening_balance: {
|
||||
name: 'Opening balance',
|
||||
column: 'opening_balance',
|
||||
fieldType: 'number',
|
||||
columnable: true,
|
||||
},
|
||||
opening_balance_at: {
|
||||
name: 'Opening balance at',
|
||||
column: 'opening_balance_at',
|
||||
filterable: false,
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
currency_code: {
|
||||
column: 'currency_code',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'active', label: 'Active' },
|
||||
{ key: 'inactive', label: 'Inactive' },
|
||||
{ key: 'overdue', label: 'Overdue' },
|
||||
{ key: 'unpaid', label: 'Unpaid' },
|
||||
],
|
||||
columnable: true,
|
||||
filterQuery: statusFieldFilterQuery,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'active':
|
||||
query.modify('active');
|
||||
break;
|
||||
case 'inactive':
|
||||
query.modify('inactive');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import PaginationQueryBuilder from './Pagination';
|
||||
import QueryParser from 'lib/LogicEvaluation/QueryParser';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import CustomerSettings from './Customer.Settings';
|
||||
|
||||
class CustomerQueryBuilder extends PaginationQueryBuilder {
|
||||
constructor(...args) {
|
||||
@@ -15,7 +17,7 @@ class CustomerQueryBuilder extends PaginationQueryBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
export default class Customer extends TenantModel {
|
||||
export default class Customer extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Query builder.
|
||||
*/
|
||||
@@ -63,6 +65,13 @@ export default class Customer extends TenantModel {
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters the active customers.
|
||||
*/
|
||||
@@ -81,10 +90,9 @@ export default class Customer extends TenantModel {
|
||||
overdue(query) {
|
||||
query.select(
|
||||
'*',
|
||||
Customer
|
||||
.relatedQuery('overDueInvoices', query.knex())
|
||||
Customer.relatedQuery('overDueInvoices', query.knex())
|
||||
.count()
|
||||
.as('countOverdue'),
|
||||
.as('countOverdue')
|
||||
);
|
||||
query.having('countOverdue', '>', 0);
|
||||
},
|
||||
@@ -93,7 +101,7 @@ export default class Customer extends TenantModel {
|
||||
*/
|
||||
unpaid(query) {
|
||||
query.whereRaw('`BALANCE` + `OPENING_BALANCE` <> 0');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -122,77 +130,12 @@ export default class Customer extends TenantModel {
|
||||
},
|
||||
filter: (query) => {
|
||||
query.modify('overdue');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static get fields() {
|
||||
return {
|
||||
contact_service: {
|
||||
column: 'contact_service',
|
||||
},
|
||||
display_name: {
|
||||
column: 'display_name',
|
||||
},
|
||||
email: {
|
||||
column: 'email',
|
||||
},
|
||||
work_phone: {
|
||||
column: 'work_phone',
|
||||
},
|
||||
personal_phone: {
|
||||
column: 'personal_phone',
|
||||
},
|
||||
company_name: {
|
||||
column: 'company_name',
|
||||
},
|
||||
website: {
|
||||
column: 'website'
|
||||
},
|
||||
created_at: {
|
||||
column: 'created_at',
|
||||
},
|
||||
balance: {
|
||||
column: 'balance',
|
||||
},
|
||||
opening_balance: {
|
||||
column: 'opening_balance',
|
||||
},
|
||||
opening_balance_at: {
|
||||
column: 'opening_balance_at',
|
||||
},
|
||||
currency_code: {
|
||||
column: 'currency_code',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'active', label: 'Active' },
|
||||
{ key: 'inactive', label: 'Inactive' },
|
||||
{ key: 'overdue', label: 'Overdue' },
|
||||
{ key: 'unpaid', label: 'Unpaid' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
switch(role.value) {
|
||||
case 'active':
|
||||
query.modify('active');
|
||||
break;
|
||||
case 'inactive':
|
||||
query.modify('inactive');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
column: 'created_at',
|
||||
}
|
||||
};
|
||||
static get meta() {
|
||||
return CustomerSettings;
|
||||
}
|
||||
}
|
||||
|
||||
82
server/src/models/Expense.Settings.ts
Normal file
82
server/src/models/Expense.Settings.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Expense - Settings.
|
||||
*/
|
||||
export default {
|
||||
defaultFilterField: 'description',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'name',
|
||||
},
|
||||
fields: {
|
||||
'payment_date': {
|
||||
name: 'Payment date',
|
||||
column: 'payment_date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'payment_account': {
|
||||
name: 'Payment account',
|
||||
column: 'payment_account_id',
|
||||
|
||||
fieldType: 'relation',
|
||||
fieldRelation: 'paymentAccount',
|
||||
|
||||
fieldRelationType: 'enumeration',
|
||||
relationLabelField: 'name',
|
||||
relationKeyField: 'slug',
|
||||
},
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'total_amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
// currency_code: {
|
||||
// name: 'Currency',
|
||||
// column: 'currency_code',
|
||||
// },
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'description': {
|
||||
name: 'Description',
|
||||
column: 'description',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'published': {
|
||||
name: 'Published',
|
||||
column: 'published_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'status': {
|
||||
name: 'Status',
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'draft', name: 'Draft' },
|
||||
{ key: 'published', name: 'Published' },
|
||||
],
|
||||
filterQuery: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('filterByDraft');
|
||||
break;
|
||||
case 'published':
|
||||
query.modify('filterByPublished');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
return query.modify('sortByStatus', role.order);
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { viewRolesBuilder } from 'lib/ViewRolesBuilder';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import ExpenseSettings from './Expense.Settings';
|
||||
|
||||
export default class Expense extends TenantModel {
|
||||
export default class Expense extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -31,12 +33,6 @@ export default class Expense extends TenantModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static get media() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static get virtualAttributes() {
|
||||
return ['isPublished', 'unallocatedCostAmount'];
|
||||
@@ -142,71 +138,7 @@ export default class Expense extends TenantModel {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
payment_date: {
|
||||
label: 'Payment date',
|
||||
column: 'payment_date',
|
||||
columnType: 'date',
|
||||
},
|
||||
payment_account: {
|
||||
label: 'Payment account',
|
||||
column: 'payment_account_id',
|
||||
relation: 'accounts.id',
|
||||
optionsResource: 'account',
|
||||
},
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'total_amount',
|
||||
columnType: 'number',
|
||||
},
|
||||
currency_code: {
|
||||
label: 'Currency',
|
||||
column: 'currency_code',
|
||||
optionsResource: 'currency',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'string',
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
columnType: 'string',
|
||||
},
|
||||
published: {
|
||||
label: 'Published',
|
||||
column: 'published_at',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'draft', label: 'Draft' },
|
||||
{ key: 'published', label: 'Published' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('filterByDraft');
|
||||
break;
|
||||
case 'published':
|
||||
query.modify('filterByPublished');
|
||||
break;
|
||||
}
|
||||
},
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return ExpenseSettings;
|
||||
}
|
||||
}
|
||||
|
||||
60
server/src/models/InventoryAdjustment.Settings.ts
Normal file
60
server/src/models/InventoryAdjustment.Settings.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
export default {
|
||||
defaultFilterField: 'date',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'date',
|
||||
},
|
||||
fields: {
|
||||
'date': {
|
||||
name: 'Date',
|
||||
column: 'date',
|
||||
fieldType: 'date',
|
||||
columnable: true,
|
||||
},
|
||||
'type': {
|
||||
name: 'Adjustment type',
|
||||
column: 'type',
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'increment', name: 'Increment' },
|
||||
{ key: 'decrement', name: 'Decrement' },
|
||||
],
|
||||
columnable: true,
|
||||
},
|
||||
'adjustment_account': {
|
||||
name: 'Adjustment account',
|
||||
column: 'adjustment_account_id',
|
||||
columnable: true,
|
||||
},
|
||||
'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,5 +1,6 @@
|
||||
import { Model } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import InventoryAdjustmentSettings from './InventoryAdjustment.Settings';
|
||||
|
||||
export default class InventoryAdjustment extends TenantModel {
|
||||
/**
|
||||
@@ -40,8 +41,8 @@ export default class InventoryAdjustment extends TenantModel {
|
||||
|
||||
static getInventoryDirection(type) {
|
||||
const directions = {
|
||||
'increment': 'IN',
|
||||
'decrement': 'OUT',
|
||||
increment: 'IN',
|
||||
decrement: 'OUT',
|
||||
};
|
||||
return directions[type] || '';
|
||||
}
|
||||
@@ -81,52 +82,9 @@ export default class InventoryAdjustment extends TenantModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
* Model settings.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
date: {
|
||||
label: 'Date',
|
||||
column: 'date',
|
||||
columnType: 'date',
|
||||
},
|
||||
type: {
|
||||
label: 'Adjustment type',
|
||||
column: 'type',
|
||||
options: [
|
||||
{ key: 'increment', label: 'Increment', },
|
||||
{ key: 'decrement', label: 'Decrement' },
|
||||
],
|
||||
},
|
||||
adjustment_account: {
|
||||
column: 'adjustment_account_id',
|
||||
},
|
||||
reason: {
|
||||
label: 'Reason',
|
||||
column: 'reason',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
},
|
||||
user: {
|
||||
label: 'User',
|
||||
column: 'user_id',
|
||||
},
|
||||
published_at: {
|
||||
label: 'Published at',
|
||||
column: 'published_at'
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return InventoryAdjustmentSettings;
|
||||
}
|
||||
}
|
||||
|
||||
102
server/src/models/Item.Settings.ts
Normal file
102
server/src/models/Item.Settings.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
export default {
|
||||
defaultFilterField: 'name',
|
||||
defaultSort: {
|
||||
sortField: 'name',
|
||||
sortOrder: 'DESC',
|
||||
},
|
||||
fields: {
|
||||
'type': {
|
||||
name: 'Item type',
|
||||
column: 'type',
|
||||
columnable: true,
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'inventory', label: 'Inventory', },
|
||||
{ key: 'service', label: 'Service' },
|
||||
{ key: 'non-inventory', label: 'Non Inventory', },
|
||||
],
|
||||
},
|
||||
'name': {
|
||||
name: 'Name',
|
||||
column: 'name',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'code': {
|
||||
name: 'Code',
|
||||
column: 'code',
|
||||
columnable: true,
|
||||
fieldType: 'text',
|
||||
},
|
||||
'sellable': {
|
||||
name: 'Sellable',
|
||||
column: 'sellable',
|
||||
fieldType: 'boolean',
|
||||
},
|
||||
'purchasable': {
|
||||
name: 'Purchasable',
|
||||
column: 'purchasable',
|
||||
fieldType: 'boolean',
|
||||
},
|
||||
'sell_price': {
|
||||
name: 'Sell price',
|
||||
column: 'sell_price',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'cost_price': {
|
||||
name: 'Cost price',
|
||||
column: 'cost_price',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'cost_account': {
|
||||
name: 'Cost account',
|
||||
column: 'cost_account_id',
|
||||
columnable: true,
|
||||
},
|
||||
'sell_account': {
|
||||
name: 'Sell account',
|
||||
column: 'sell_account_id',
|
||||
},
|
||||
'inventory_account': {
|
||||
name: 'Inventory account',
|
||||
column: 'inventory_account_id',
|
||||
},
|
||||
'sell_description': {
|
||||
name: 'Sell description',
|
||||
column: 'sell_description',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'purchase_description': {
|
||||
name: 'Purchase description',
|
||||
column: 'purchase_description',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'quantity_on_hand': {
|
||||
name: 'Quantity on hand',
|
||||
column: 'quantity_on_hand',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'note': {
|
||||
name: 'Note',
|
||||
column: 'note',
|
||||
fieldType: 'text',
|
||||
columnable: true,
|
||||
},
|
||||
'category': {
|
||||
name: 'Category',
|
||||
column: 'category_id',
|
||||
columnable: true,
|
||||
},
|
||||
'active': {
|
||||
name: 'Active',
|
||||
column: 'active',
|
||||
fieldType: 'boolean',
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,20 +1,22 @@
|
||||
import { Model } from "objection";
|
||||
import TenantModel from "models/TenantModel";
|
||||
import { buildFilterQuery } from "lib/ViewRolesBuilder";
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { buildFilterQuery } from 'lib/ViewRolesBuilder';
|
||||
import ItemSettings from './Item.Settings';
|
||||
import ModelSetting from './ModelSetting';
|
||||
|
||||
export default class Item extends TenantModel {
|
||||
export default class Item extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return "items";
|
||||
return 'items';
|
||||
}
|
||||
|
||||
/**
|
||||
* Model timestamps.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ["createdAt", "updatedAt"];
|
||||
return ['createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,6 +37,13 @@ export default class Item extends TenantModel {
|
||||
viewRolesBuilder(query, conditions, logicExpression) {
|
||||
buildFilterQuery(Item.tableName, conditions, logicExpression)(query);
|
||||
},
|
||||
|
||||
/**
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -42,9 +51,9 @@ export default class Item extends TenantModel {
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const Media = require("models/Media");
|
||||
const Account = require("models/Account");
|
||||
const ItemCategory = require("models/ItemCategory");
|
||||
const Media = require('models/Media');
|
||||
const Account = require('models/Account');
|
||||
const ItemCategory = require('models/ItemCategory');
|
||||
|
||||
return {
|
||||
/**
|
||||
@@ -54,8 +63,8 @@ export default class Item extends TenantModel {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: ItemCategory.default,
|
||||
join: {
|
||||
from: "items.categoryId",
|
||||
to: "items_categories.id",
|
||||
from: 'items.categoryId',
|
||||
to: 'items_categories.id',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -63,8 +72,8 @@ export default class Item extends TenantModel {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Account.default,
|
||||
join: {
|
||||
from: "items.costAccountId",
|
||||
to: "accounts.id",
|
||||
from: 'items.costAccountId',
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -72,8 +81,8 @@ export default class Item extends TenantModel {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Account.default,
|
||||
join: {
|
||||
from: "items.sellAccountId",
|
||||
to: "accounts.id",
|
||||
from: 'items.sellAccountId',
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -81,8 +90,8 @@ export default class Item extends TenantModel {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Account.default,
|
||||
join: {
|
||||
from: "items.inventoryAccountId",
|
||||
to: "accounts.id",
|
||||
from: 'items.inventoryAccountId',
|
||||
to: 'accounts.id',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -90,110 +99,21 @@ export default class Item extends TenantModel {
|
||||
relation: Model.ManyToManyRelation,
|
||||
modelClass: Media.default,
|
||||
join: {
|
||||
from: "items.id",
|
||||
from: 'items.id',
|
||||
through: {
|
||||
from: "media_links.model_id",
|
||||
to: "media_links.media_id",
|
||||
from: 'media_links.model_id',
|
||||
to: 'media_links.media_id',
|
||||
},
|
||||
to: "media.id",
|
||||
to: 'media.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Item fields.
|
||||
* Model settings.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
type: {
|
||||
label: "Type",
|
||||
column: "type",
|
||||
},
|
||||
name: {
|
||||
label: "Name",
|
||||
column: "name",
|
||||
},
|
||||
code: {
|
||||
label: "Code",
|
||||
column: "code",
|
||||
},
|
||||
sellable: {
|
||||
label: "Sellable",
|
||||
column: "sellable",
|
||||
},
|
||||
purchasable: {
|
||||
label: "Purchasable",
|
||||
column: "purchasable",
|
||||
},
|
||||
sell_price: {
|
||||
label: "Sell price",
|
||||
column: "sell_price",
|
||||
},
|
||||
cost_price: {
|
||||
label: "Cost price",
|
||||
column: "cost_price",
|
||||
},
|
||||
currency_code: {
|
||||
label: "Currency",
|
||||
column: "currency_code",
|
||||
},
|
||||
cost_account: {
|
||||
label: "Cost account",
|
||||
column: "cost_account_id",
|
||||
relation: "accounts.id",
|
||||
relationColumn: "accounts.name",
|
||||
},
|
||||
sell_account: {
|
||||
label: "Sell account",
|
||||
column: "sell_account_id",
|
||||
relation: "accounts.id",
|
||||
relationColumn: "accounts.name",
|
||||
},
|
||||
inventory_account: {
|
||||
label: "Inventory account",
|
||||
column: "inventory_account_id",
|
||||
relation: "accounts.id",
|
||||
relationColumn: "accounts.name",
|
||||
},
|
||||
sell_description: {
|
||||
label: "Sell description",
|
||||
column: "sell_description",
|
||||
},
|
||||
purchase_description: {
|
||||
label: "Purchase description",
|
||||
column: "purchase_description",
|
||||
},
|
||||
quantity_on_hand: {
|
||||
label: "Quantity on hand",
|
||||
column: "quantity_on_hand",
|
||||
},
|
||||
note: {
|
||||
label: "Note",
|
||||
column: "note",
|
||||
},
|
||||
category: {
|
||||
label: "Category",
|
||||
column: "category_id",
|
||||
relation: "items_categories.id",
|
||||
relationColumn: "items_categories.name",
|
||||
},
|
||||
active: {
|
||||
label: "Active",
|
||||
column: "active",
|
||||
},
|
||||
// user: {
|
||||
// label: 'User',
|
||||
// column: 'user_id',
|
||||
// relation: 'users.id',
|
||||
// relationColumn: 'users.',
|
||||
// },
|
||||
created_at: {
|
||||
label: "Created at",
|
||||
column: "created_at",
|
||||
columnType: "date",
|
||||
fieldType: "date",
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return ItemSettings;
|
||||
}
|
||||
}
|
||||
|
||||
41
server/src/models/ItemCategory.Settings.ts
Normal file
41
server/src/models/ItemCategory.Settings.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export default {
|
||||
defaultFilterField: 'name',
|
||||
defaultSort: {
|
||||
sortField: 'name',
|
||||
sortOrder: 'DESC',
|
||||
},
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
column: 'name',
|
||||
fieldType: 'text',
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
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,
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -42,68 +42,6 @@ export default class ItemCategory extends TenantModel {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Item category fields.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
name: {
|
||||
label: 'Name',
|
||||
column: 'name',
|
||||
columnType: 'string'
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
columnType: 'string'
|
||||
},
|
||||
user: {
|
||||
label: 'User',
|
||||
column: 'user_id',
|
||||
relation: 'users.id',
|
||||
relationColumn: 'users.id',
|
||||
},
|
||||
cost_account: {
|
||||
label: 'Cost account',
|
||||
column: 'cost_account_id',
|
||||
relation: 'accounts.id',
|
||||
optionsResource: 'account'
|
||||
},
|
||||
sell_account: {
|
||||
label: 'Sell account',
|
||||
column: 'sell_account_id',
|
||||
relation: 'accounts.id',
|
||||
optionsResource: 'account'
|
||||
},
|
||||
inventory_account: {
|
||||
label: 'Inventory account',
|
||||
column: 'inventory_account_id',
|
||||
relation: 'accounts.id',
|
||||
optionsResource: 'account'
|
||||
},
|
||||
cost_method: {
|
||||
label: 'Cost method',
|
||||
column: 'cost_method',
|
||||
options: [{
|
||||
key: 'FIFO', label: 'First-in first-out (FIFO)',
|
||||
key: 'LIFO', label: 'Last-in first-out (LIFO)',
|
||||
key: 'average', label: 'Average rate',
|
||||
}],
|
||||
columnType: 'string',
|
||||
},
|
||||
count: {
|
||||
label: 'Count',
|
||||
column: 'count',
|
||||
sortQuery: this.sortCountQuery
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static sortCountQuery(query, role) {
|
||||
query.orderBy('count', role.order);
|
||||
}
|
||||
|
||||
54
server/src/models/ManualJournal.Settings.ts
Normal file
54
server/src/models/ManualJournal.Settings.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
export default {
|
||||
defaultFilterField: 'date',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'name',
|
||||
},
|
||||
fields: {
|
||||
'date': {
|
||||
label: 'Date',
|
||||
column: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'journal_number': {
|
||||
label: 'Journal number',
|
||||
column: 'journal_number',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'reference': {
|
||||
label: 'Reference No.',
|
||||
column: 'reference',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'journal_type': {
|
||||
label: 'Journal type',
|
||||
column: 'journal_type',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'amount': {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
},
|
||||
'description': {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'status': {
|
||||
label: 'Status',
|
||||
column: 'status',
|
||||
fieldType: 'enumeration',
|
||||
sortQuery: statusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
return query.modify('sortByStatus', role.order);
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { formatNumber } from 'utils';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import ManualJournalSettings from './ManualJournal.Settings';
|
||||
|
||||
export default class ManualJournal extends TenantModel {
|
||||
export default class ManualJournal extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
@@ -99,52 +101,7 @@ export default class ManualJournal extends TenantModel {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
date: {
|
||||
label: 'Date',
|
||||
column: 'date',
|
||||
columnType: 'date',
|
||||
},
|
||||
journal_number: {
|
||||
label: 'Journal number',
|
||||
column: 'journal_number',
|
||||
columnType: 'string',
|
||||
},
|
||||
reference: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference',
|
||||
columnType: 'string',
|
||||
},
|
||||
journal_type: {
|
||||
label: 'Journal type',
|
||||
column: 'journal_type',
|
||||
columnType: 'string',
|
||||
},
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
column: 'description',
|
||||
columnType: 'string',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
column: 'status',
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return ManualJournalSettings;
|
||||
}
|
||||
}
|
||||
|
||||
54
server/src/models/ModelSetting.ts
Normal file
54
server/src/models/ModelSetting.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { get } from 'lodash';
|
||||
import { IModelMeta, IModelMetaField, IModelMetaDefaultSort } from 'interfaces';
|
||||
|
||||
export default (Model) =>
|
||||
class ModelSettings extends Model {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static get meta(): IModelMeta {
|
||||
throw new Error('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve specific model field meta of the given field key.
|
||||
* @param {string} key
|
||||
* @returns {IModelMetaField}
|
||||
*/
|
||||
public static getField(key: string): IModelMetaField {
|
||||
return get(this.meta.fields, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the specific model meta.
|
||||
* @param {string} key
|
||||
* @returns
|
||||
*/
|
||||
public static getMeta(key: string) {
|
||||
return get(this.meta, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model meta fields.
|
||||
* @return {{ [key: string]: IModelMetaField }}
|
||||
*/
|
||||
public static get fields(): { [key: string]: IModelMetaField } {
|
||||
return this.getMeta('fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model default sort settings.
|
||||
* @return {IModelMetaDefaultSort}
|
||||
*/
|
||||
public static get defaultSort(): IModelMetaDefaultSort {
|
||||
return this.getMeta('defaultSort');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default filter field key.
|
||||
* @return {string}
|
||||
*/
|
||||
public static get defaultFilterField(): string {
|
||||
return this.getMeta('defaultFilterField');
|
||||
}
|
||||
};
|
||||
43
server/src/models/PaymentReceive.Settings.ts
Normal file
43
server/src/models/PaymentReceive.Settings.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
export default {
|
||||
fields: {
|
||||
customer: {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
},
|
||||
payment_date: {
|
||||
name: 'Payment date',
|
||||
column: 'payment_date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
amount: {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
reference_no: {
|
||||
name: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
fieldType: 'text',
|
||||
},
|
||||
deposit_account: {
|
||||
name: 'Deposit account',
|
||||
column: 'deposit_account_id',
|
||||
},
|
||||
payment_receive_no: {
|
||||
name: 'Payment receive No.',
|
||||
column: 'payment_receive_no',
|
||||
fieldType: 'text',
|
||||
},
|
||||
statement: {
|
||||
name: 'Statement',
|
||||
column: 'statement',
|
||||
fieldType: 'text',
|
||||
},
|
||||
created_at: {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldDate: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import PaymentReceiveSettings from './PaymentReceive.Settings';
|
||||
|
||||
export default class PaymentReceive extends TenantModel {
|
||||
export default class PaymentReceive extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
@@ -75,63 +77,9 @@ export default class PaymentReceive extends TenantModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
*
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
customer: {
|
||||
label: 'Customer',
|
||||
column: 'customer_id',
|
||||
relation: 'contacts.id',
|
||||
relationColumn: 'contacts.displayName',
|
||||
|
||||
fieldType: 'options',
|
||||
optionsResource: 'customers',
|
||||
optionsKey: 'id',
|
||||
optionsLable: 'displayName',
|
||||
},
|
||||
payment_date: {
|
||||
label: 'Payment date',
|
||||
column: 'payment_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
deposit_account: {
|
||||
column: 'deposit_account_id',
|
||||
lable: 'Deposit account',
|
||||
relation: "accounts.id",
|
||||
relationColumn: 'accounts.name',
|
||||
optionsResource: "account",
|
||||
},
|
||||
payment_receive_no: {
|
||||
label: 'Payment receive No.',
|
||||
column: 'payment_receive_no',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
description: {
|
||||
label: 'description',
|
||||
column: 'description',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return PaymentReceiveSettings;
|
||||
}
|
||||
}
|
||||
|
||||
85
server/src/models/SaleEstimate.Settings.ts
Normal file
85
server/src/models/SaleEstimate.Settings.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
export default {
|
||||
defaultFilterField: 'estimate_date',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'estimate_date',
|
||||
},
|
||||
fields: {
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'estimate_number': {
|
||||
name: 'Estimate number',
|
||||
column: 'estimate_number',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'customer': {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
},
|
||||
'estimate_date': {
|
||||
name: 'Estimate date',
|
||||
column: 'estimate_date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'expiration_date': {
|
||||
name: 'Expiration date',
|
||||
column: 'expiration_date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'reference_no': {
|
||||
name: 'Reference No.',
|
||||
column: 'reference',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'note': {
|
||||
name: 'Note',
|
||||
column: 'note',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'terms_conditions': {
|
||||
name: 'Terms & conditions',
|
||||
column: 'terms_conditions',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'status': {
|
||||
name: 'Status',
|
||||
filterQuery: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
return query.modify('orderByDraft', 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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import moment from 'moment';
|
||||
import { Model } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import { defaultToTransform } from 'utils';
|
||||
import HasItemEntries from 'services/Sales/HasItemsEntries';
|
||||
import { query } from 'winston';
|
||||
import SaleEstimateSettings from './SaleEstimate.Settings';
|
||||
import ModelSetting from './ModelSetting';
|
||||
|
||||
export default class SaleEstimate extends TenantModel {
|
||||
export default class SaleEstimate extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -29,9 +29,9 @@ export default class SaleEstimate extends TenantModel {
|
||||
'isExpired',
|
||||
'isConvertedToInvoice',
|
||||
'isApproved',
|
||||
'isRejected'
|
||||
'isRejected',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detarmines whether the sale estimate converted to sale invoice.
|
||||
@@ -57,7 +57,7 @@ export default class SaleEstimate extends TenantModel {
|
||||
return defaultToTransform(
|
||||
this.expirationDate,
|
||||
moment().isAfter(this.expirationDate, 'day'),
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -123,14 +123,14 @@ export default class SaleEstimate extends TenantModel {
|
||||
* Filters the approved estimates transactions.
|
||||
*/
|
||||
approved(query) {
|
||||
query.whereNot('approved_at', null)
|
||||
query.whereNot('approved_at', null);
|
||||
},
|
||||
/**
|
||||
* Sorting the estimates orders by delivery status.
|
||||
*/
|
||||
orderByDraft(query, order) {
|
||||
query.orderByRaw(`delivered_at is null ${order}`)
|
||||
}
|
||||
query.orderByRaw(`delivered_at is null ${order}`);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ export default class SaleEstimate extends TenantModel {
|
||||
},
|
||||
filter(query) {
|
||||
query.where('contact_service', 'customer');
|
||||
}
|
||||
},
|
||||
},
|
||||
entries: {
|
||||
relation: Model.HasManyRelation,
|
||||
@@ -168,91 +168,9 @@ export default class SaleEstimate extends TenantModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
* Model settings.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
estimate_number: {
|
||||
label: 'Estimate number',
|
||||
column: 'estimate_number',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
customer: {
|
||||
label: 'Customer',
|
||||
column: 'customer_id',
|
||||
relation: 'contacts.id',
|
||||
relationColumn: 'contacts.displayName',
|
||||
|
||||
fieldType: 'options',
|
||||
optionsResource: 'customers',
|
||||
optionsKey: 'id',
|
||||
optionsLable: 'displayName',
|
||||
},
|
||||
estimate_date: {
|
||||
label: 'Estimate date',
|
||||
column: 'estimate_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
expiration_date: {
|
||||
label: 'Expiration date',
|
||||
column: 'expiration_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
reference_no: {
|
||||
label: "Reference No.",
|
||||
column: "reference",
|
||||
columnType: "number",
|
||||
fieldType: "number",
|
||||
},
|
||||
note: {
|
||||
label: 'Note',
|
||||
column: 'note',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
terms_conditions: {
|
||||
label: 'Terms & conditions',
|
||||
column: 'terms_conditions',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
query: (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;
|
||||
}
|
||||
},
|
||||
sortQuery: (query, role) => {
|
||||
query.modify('orderByDraft', role.order);
|
||||
}
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
};
|
||||
static get meta() {
|
||||
return SaleEstimateSettings;
|
||||
}
|
||||
}
|
||||
|
||||
86
server/src/models/SaleInvoice.Settings.ts
Normal file
86
server/src/models/SaleInvoice.Settings.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
export default {
|
||||
defaultFilterField: 'customer',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'created_at',
|
||||
},
|
||||
fields: {
|
||||
// customer: {
|
||||
// name: 'Customer',
|
||||
// column: 'customer_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: {
|
||||
name: 'Payment amount',
|
||||
column: 'payment_amount',
|
||||
fieldType: 'number',
|
||||
},
|
||||
due_amount: {
|
||||
name: 'Due amount',
|
||||
column: 'due_amount',
|
||||
fieldType: 'number',
|
||||
// sortQuery: SaleInvoice.dueAmountFieldSortQuery,
|
||||
},
|
||||
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,
|
||||
// },
|
||||
},
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Model, raw } from 'objection';
|
||||
import { mixin, Model, raw } from 'objection';
|
||||
import moment from 'moment';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import SaleInvoiceMeta from './SaleInvoice.Settings';
|
||||
|
||||
export default class SaleInvoice extends TenantModel {
|
||||
export default class SaleInvoice extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -243,6 +245,9 @@ export default class SaleInvoice extends TenantModel {
|
||||
const PaymentReceiveEntry = require('models/PaymentReceiveEntry');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Sale invoice associated entries.
|
||||
*/
|
||||
entries: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: ItemEntry.default,
|
||||
@@ -255,6 +260,9 @@ export default class SaleInvoice extends TenantModel {
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Belongs to customer model.
|
||||
*/
|
||||
customer: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Contact.default,
|
||||
@@ -267,6 +275,9 @@ export default class SaleInvoice extends TenantModel {
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoice has associated account transactions.
|
||||
*/
|
||||
transactions: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: AccountTransaction.default,
|
||||
@@ -316,125 +327,40 @@ export default class SaleInvoice extends TenantModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
* Sale invoice meta.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
customer: {
|
||||
label: 'Customer',
|
||||
column: 'customer_id',
|
||||
relation: 'contacts.id',
|
||||
relationColumn: 'contacts.displayName',
|
||||
static get meta() {
|
||||
return SaleInvoiceMeta;
|
||||
}
|
||||
|
||||
fieldType: 'options',
|
||||
optionsResource: 'customers',
|
||||
optionsKey: 'id',
|
||||
optionsLable: 'displayName',
|
||||
},
|
||||
invoice_date: {
|
||||
label: 'Invoice date',
|
||||
column: 'invoice_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
due_date: {
|
||||
label: 'Due date',
|
||||
column: 'due_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
invoice_no: {
|
||||
label: 'Invoice No.',
|
||||
column: 'invoice_no',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
invoice_message: {
|
||||
label: 'Invoice message',
|
||||
column: 'invoice_message',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
terms_conditions: {
|
||||
label: 'Terms & conditions',
|
||||
column: 'terms_conditions',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
invoice_amount: {
|
||||
label: 'Invoice amount',
|
||||
column: 'invoice_amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
payment_amount: {
|
||||
label: 'Payment amount',
|
||||
column: 'payment_amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
balance: {
|
||||
label: 'Balance',
|
||||
column: 'balance',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
due_amount: {
|
||||
label: 'Due amount',
|
||||
column: 'due_amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByDueAmount', role.order);
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'draft', label: 'Draft' },
|
||||
{ key: 'delivered', label: 'Delivered' },
|
||||
{ key: 'unpaid', label: 'Unpaid' },
|
||||
{ key: 'overdue', label: 'Overdue' },
|
||||
{ key: 'partially-paid', label: 'Partially paid' },
|
||||
{ key: 'paid', label: 'Paid' },
|
||||
],
|
||||
query: (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;
|
||||
}
|
||||
},
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
},
|
||||
},
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
87
server/src/models/SaleReceipt.Settings.ts
Normal file
87
server/src/models/SaleReceipt.Settings.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
export default {
|
||||
defaultFilterField: 'receipt_date',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'created_at',
|
||||
},
|
||||
fields: {
|
||||
'amount': {
|
||||
name: 'Amount',
|
||||
column: 'amount',
|
||||
fieldType: 'number',
|
||||
columnable: true
|
||||
},
|
||||
'deposit_account': {
|
||||
column: 'deposit_account_id',
|
||||
name: 'Deposit account',
|
||||
columnable: true
|
||||
},
|
||||
'customer': {
|
||||
name: 'Customer',
|
||||
column: 'customer_id',
|
||||
columnable: true
|
||||
},
|
||||
'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',
|
||||
fieldType: 'enumeration',
|
||||
options: [
|
||||
{ key: 'draft', name: 'Draft' },
|
||||
{ key: 'closed', name: 'Closed' },
|
||||
],
|
||||
query: statusFieldFilterQuery,
|
||||
sortQuery: statusFieldSortQuery,
|
||||
columnable: true
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function statusFieldFilterQuery(query, role) {
|
||||
switch (role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'closed':
|
||||
query.modify('closed');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function statusFieldSortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import SaleReceiptSettings from './SaleReceipt.Settings';
|
||||
|
||||
export default class SaleReceipt extends TenantModel {
|
||||
export default class SaleReceipt extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
@@ -16,14 +18,11 @@ export default class SaleReceipt extends TenantModel {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return [
|
||||
'isClosed',
|
||||
'isDraft',
|
||||
];
|
||||
return ['isClosed', 'isDraft'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +65,7 @@ export default class SaleReceipt extends TenantModel {
|
||||
*/
|
||||
sortByStatus(query, order) {
|
||||
query.orderByRaw(`CLOSED_AT IS NULL ${order}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ export default class SaleReceipt extends TenantModel {
|
||||
},
|
||||
filter(query) {
|
||||
query.where('contact_service', 'customer');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
depositAccount: {
|
||||
@@ -118,95 +117,19 @@ export default class SaleReceipt extends TenantModel {
|
||||
modelClass: AccountTransaction.default,
|
||||
join: {
|
||||
from: 'sales_receipts.id',
|
||||
to: 'accounts_transactions.referenceId'
|
||||
to: 'accounts_transactions.referenceId',
|
||||
},
|
||||
filter(builder) {
|
||||
builder.where('reference_type', 'SaleReceipt');
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Model defined fields.
|
||||
* Sale invoice meta.
|
||||
*/
|
||||
static get fields() {
|
||||
return {
|
||||
amount: {
|
||||
label: 'Amount',
|
||||
column: 'amount',
|
||||
columnType: 'number',
|
||||
fieldType: 'number',
|
||||
},
|
||||
deposit_account: {
|
||||
column: 'deposit_account_id',
|
||||
label: 'Deposit account',
|
||||
relation: "accounts.id",
|
||||
optionsResource: "account",
|
||||
},
|
||||
customer: {
|
||||
label: 'Customer',
|
||||
column: 'customer_id',
|
||||
fieldType: 'options',
|
||||
optionsResource: 'customers',
|
||||
optionsKey: 'id',
|
||||
optionsLable: 'displayName',
|
||||
},
|
||||
receipt_date: {
|
||||
label: 'Receipt date',
|
||||
column: 'receipt_date',
|
||||
columnType: 'date',
|
||||
fieldType: 'date',
|
||||
},
|
||||
receipt_number: {
|
||||
label: 'Receipt No.',
|
||||
column: 'receipt_number',
|
||||
columnType: 'string',
|
||||
fieldType: 'text',
|
||||
},
|
||||
reference_no: {
|
||||
label: 'Reference No.',
|
||||
column: 'reference_no',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
receipt_message: {
|
||||
label: 'Receipt message',
|
||||
column: 'receipt_message',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
statement: {
|
||||
label: 'Statement',
|
||||
column: 'statement',
|
||||
columnType: 'text',
|
||||
fieldType: 'text',
|
||||
},
|
||||
created_at: {
|
||||
label: 'Created at',
|
||||
column: 'created_at',
|
||||
columnType: 'date',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'draft', label: 'Draft', },
|
||||
{ key: 'closed', label: 'Closed' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
switch(role.value) {
|
||||
case 'draft':
|
||||
query.modify('draft');
|
||||
break;
|
||||
case 'closed':
|
||||
query.modify('closed');
|
||||
break;
|
||||
}
|
||||
},
|
||||
sortQuery(query, role) {
|
||||
query.modify('sortByStatus', role.order);
|
||||
}
|
||||
}
|
||||
};
|
||||
static get meta() {
|
||||
return SaleReceiptSettings;
|
||||
}
|
||||
}
|
||||
|
||||
89
server/src/models/Vendor.Settings.ts
Normal file
89
server/src/models/Vendor.Settings.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
export default {
|
||||
defaultFilterField: 'display_name',
|
||||
defaultSort: {
|
||||
sortOrder: 'DESC',
|
||||
sortField: 'created_at',
|
||||
},
|
||||
fields: {
|
||||
'display_name': {
|
||||
name: 'Display name',
|
||||
column: 'display_name',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'email': {
|
||||
name: 'Email',
|
||||
column: 'email',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'work_phone': {
|
||||
name: 'Work phone',
|
||||
column: 'work_phone',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'personal_phone': {
|
||||
name: 'Personal phone',
|
||||
column: 'personal_phone',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'company_name': {
|
||||
name: 'Company name',
|
||||
column: 'company_name',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'website': {
|
||||
name: 'Website',
|
||||
column: 'website',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'created_at': {
|
||||
name: 'Created at',
|
||||
column: 'created_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'balance': {
|
||||
name: 'Balance',
|
||||
column: 'balance',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'opening_balance': {
|
||||
name: 'Opening balance',
|
||||
column: 'opening_balance',
|
||||
fieldType: 'number',
|
||||
},
|
||||
'opening_balance_at': {
|
||||
name: 'Opening balance at',
|
||||
column: 'opening_balance_at',
|
||||
fieldType: 'date',
|
||||
},
|
||||
'currency_code': {
|
||||
name: 'Currency code',
|
||||
column: 'currency_code',
|
||||
fieldType: 'text',
|
||||
},
|
||||
'status': {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'active', label: 'Active' },
|
||||
{ key: 'inactive', label: 'Inactive' },
|
||||
{ key: 'overdue', label: 'Overdue' },
|
||||
{ key: 'unpaid', label: 'Unpaid' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
switch (role.value) {
|
||||
case 'active':
|
||||
query.modify('active');
|
||||
break;
|
||||
case 'inactive':
|
||||
query.modify('inactive');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Model, QueryBuilder } from 'objection';
|
||||
import { Model, mixin } from 'objection';
|
||||
import TenantModel from 'models/TenantModel';
|
||||
import PaginationQueryBuilder from './Pagination';
|
||||
import ModelSetting from './ModelSetting';
|
||||
import VendorSettings from './Vendor.Settings';
|
||||
|
||||
class VendorQueryBuilder extends PaginationQueryBuilder {
|
||||
constructor(...args) {
|
||||
@@ -14,7 +16,7 @@ class VendorQueryBuilder extends PaginationQueryBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
export default class Vendor extends TenantModel {
|
||||
export default class Vendor extends mixin(TenantModel, [ModelSetting]) {
|
||||
/**
|
||||
* Query builder.
|
||||
*/
|
||||
@@ -62,6 +64,13 @@ export default class Vendor extends TenantModel {
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
* Inactive/Active mode.
|
||||
*/
|
||||
inactiveMode(query, active = false) {
|
||||
query.where('active', !active);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters the active customers.
|
||||
*/
|
||||
@@ -125,72 +134,7 @@ export default class Vendor extends TenantModel {
|
||||
};
|
||||
}
|
||||
|
||||
static get fields() {
|
||||
return {
|
||||
contact_service: {
|
||||
column: 'contact_service',
|
||||
},
|
||||
display_name: {
|
||||
column: 'display_name',
|
||||
},
|
||||
email: {
|
||||
column: 'email',
|
||||
},
|
||||
work_phone: {
|
||||
column: 'work_phone',
|
||||
},
|
||||
personal_phone: {
|
||||
column: 'personal_phone',
|
||||
},
|
||||
company_name: {
|
||||
column: 'company_name',
|
||||
},
|
||||
website: {
|
||||
column: 'website'
|
||||
},
|
||||
created_at: {
|
||||
column: 'created_at',
|
||||
},
|
||||
balance: {
|
||||
column: 'balance',
|
||||
},
|
||||
opening_balance: {
|
||||
column: 'opening_balance',
|
||||
},
|
||||
opening_balance_at: {
|
||||
column: 'opening_balance_at',
|
||||
},
|
||||
currency_code: {
|
||||
column: 'currency_code',
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
options: [
|
||||
{ key: 'active', label: 'Active' },
|
||||
{ key: 'inactive', label: 'Inactive' },
|
||||
{ key: 'overdue', label: 'Overdue' },
|
||||
{ key: 'unpaid', label: 'Unpaid' },
|
||||
],
|
||||
query: (query, role) => {
|
||||
switch(role.value) {
|
||||
case 'active':
|
||||
query.modify('active');
|
||||
break;
|
||||
case 'inactive':
|
||||
query.modify('inactive');
|
||||
break;
|
||||
case 'overdue':
|
||||
query.modify('overdue');
|
||||
break;
|
||||
case 'unpaid':
|
||||
query.modify('unpaid');
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
column: 'created_at',
|
||||
}
|
||||
};
|
||||
static get meta() {
|
||||
return VendorSettings;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user