feat: optimize dynamic list service.

feat: inactive mode for accounts, items, customers and vendors services.
This commit is contained in:
a.bouhuolia
2021-07-29 08:46:41 +02:00
parent 720dc5b7d7
commit 9186076676
80 changed files with 2748 additions and 1806 deletions

View 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;

View File

@@ -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;
}
}

View 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;

View File

@@ -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);
};
}

View 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',
},
},
};

View File

@@ -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",
},
};
}
}

View 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;
}
}

View File

@@ -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;
}
}

View 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);
}

View File

@@ -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;
}
}

View 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,
},
},
};

View File

@@ -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;
}
}

View 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',
},
},
};

View File

@@ -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;
}
}

View 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',
},
},
};

View File

@@ -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);
}

View 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);
}

View File

@@ -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;
}
}

View 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');
}
};

View 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',
},
},
};

View File

@@ -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;
}
}

View 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;
}
}

View File

@@ -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;
}
}

View 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,
// },
},
};

View File

@@ -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);
}
}

View 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);
}

View File

@@ -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;
}
}

View 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;
}
},
},
},
};

View File

@@ -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;
}
}