mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
- feat: Update react-query package to V 2.1.1.
- feat: Favicon setup. - feat: Fix accounts inactivate/activate 1 account. - feat: Seed accounts, expenses and manual journals resource fields. - feat: Validate make journal receivable/payable without contact. - feat: Validate make journal contact without receivable or payable. - feat: More components abstractions. - feat: Use reselect.js to memorize components properties. - fix: Journal type of manual journal. - fix: Sidebar style optimization. - fix: Data-table check-box style optimization. - fix: Data-table spinner style dimensions. - fix: Submit journal with contact_id and contact_type.
This commit is contained in:
@@ -3,17 +3,29 @@
|
||||
export default {
|
||||
// Expenses.
|
||||
'expenses': {
|
||||
'expense_account': {
|
||||
column: ' ',
|
||||
relation: 'accounts.name',
|
||||
payment_date: {
|
||||
column: 'payment_date',
|
||||
},
|
||||
'payment_account': {
|
||||
payment_account: {
|
||||
column: 'payment_account_id',
|
||||
relation: 'accounts.id',
|
||||
},
|
||||
'account_type': {
|
||||
column: 'account_type_id',
|
||||
relation: 'account_types.id',
|
||||
total_amount: {
|
||||
column: 'total_amount',
|
||||
},
|
||||
reference_no: {
|
||||
column: 'reference_no'
|
||||
},
|
||||
description: {
|
||||
column: 'description',
|
||||
},
|
||||
published: {
|
||||
column: 'published',
|
||||
},
|
||||
user: {
|
||||
column: 'user_id',
|
||||
relation: 'users.id',
|
||||
relationColumn: 'users.id',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -43,8 +55,18 @@ export default {
|
||||
columnType: 'date',
|
||||
},
|
||||
active: {
|
||||
column: 'active',
|
||||
|
||||
column: 'active',
|
||||
},
|
||||
balance: {
|
||||
column: 'balance',
|
||||
},
|
||||
currency: {
|
||||
column: 'currency_code',
|
||||
},
|
||||
normal: {
|
||||
column: 'account_type_id',
|
||||
relation: 'account_types.id',
|
||||
relationColumn: 'account_types.normal'
|
||||
},
|
||||
},
|
||||
|
||||
@@ -59,24 +81,35 @@ export default {
|
||||
},
|
||||
|
||||
// Manual Journals
|
||||
'manual_journals': {
|
||||
'type': {
|
||||
column: 'transaction_type',
|
||||
},
|
||||
'status': {
|
||||
column: 'status',
|
||||
},
|
||||
'date': {
|
||||
manual_journals: {
|
||||
date: {
|
||||
column: 'date',
|
||||
},
|
||||
'journal_number': {
|
||||
created_at: {
|
||||
column: 'created_at',
|
||||
},
|
||||
journal_number: {
|
||||
column: 'journal_number',
|
||||
},
|
||||
'amount': {
|
||||
reference: {
|
||||
column: 'reference',
|
||||
},
|
||||
status: {
|
||||
column: 'status',
|
||||
},
|
||||
amount: {
|
||||
column: 'amount',
|
||||
},
|
||||
'created_at': {
|
||||
column: 'created_at',
|
||||
description: {
|
||||
column: 'description',
|
||||
},
|
||||
user: {
|
||||
column: 'user_id',
|
||||
relation: 'users.id',
|
||||
relationColumn: 'users.id',
|
||||
},
|
||||
journal_type: {
|
||||
column: 'journal_type',
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,8 +3,8 @@ exports.up = function (knex) {
|
||||
return knex.schema.createTable('accounts', (table) => {
|
||||
table.bigIncrements('id').comment('Auto-generated id');;
|
||||
table.string('name');
|
||||
table.integer('account_type_id');
|
||||
table.integer('parent_account_id');
|
||||
table.integer('account_type_id').unsigned();
|
||||
table.integer('parent_account_id').unsigned();
|
||||
table.string('code', 10);
|
||||
table.text('description');
|
||||
table.boolean('active').defaultTo(true);
|
||||
|
||||
@@ -4,7 +4,7 @@ exports.up = function(knex) {
|
||||
table.increments();
|
||||
table.string('journal_number');
|
||||
table.string('reference');
|
||||
table.string('transaction_type');
|
||||
table.string('journal_type');
|
||||
table.decimal('amount');
|
||||
table.date('date');
|
||||
table.boolean('status').defaultTo(false);
|
||||
|
||||
@@ -68,40 +68,189 @@ exports.seed = (knex) => {
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
resource_id: 1,
|
||||
data_type: 'numeric',
|
||||
label_name: 'Balance',
|
||||
key: 'balance',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
resource_id: 1,
|
||||
data_type: 'options',
|
||||
label_name: 'Currency',
|
||||
key: 'currency',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
data_resource: 'currencies',
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
resource_id: 1,
|
||||
data_type: 'options',
|
||||
label_name: 'Normal',
|
||||
key: 'normal',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
options: JSON.stringify([
|
||||
{ key: 'credit', label: 'Credit' },
|
||||
{ key: 'debit', label: 'Debit' },
|
||||
])
|
||||
},
|
||||
|
||||
// Manual Journals
|
||||
{
|
||||
id: 18,
|
||||
resource_id: 4,
|
||||
data_type: 'date',
|
||||
label_name: 'Date',
|
||||
key: 'date',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
resource_id: 4,
|
||||
data_type: 'date',
|
||||
label_name: 'Created At',
|
||||
key: 'created_at',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
resource_id: 4,
|
||||
data_type: 'textbox',
|
||||
label_name: 'Journal Number',
|
||||
key: 'journal_number',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
resource_id: 4,
|
||||
data_type: 'boolean',
|
||||
label_name: 'Active',
|
||||
key: 'status',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
resource_id: 4,
|
||||
data_type: 'textbox',
|
||||
label_name: 'Reference',
|
||||
key: 'reference',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
resource_id: 4,
|
||||
data_type: 'textbox',
|
||||
label_name: 'Description',
|
||||
key: 'description',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
resource_id: 4,
|
||||
data_type: 'numeric',
|
||||
label_name: 'Amount',
|
||||
key: 'amount',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
resource_id: 4,
|
||||
data_type: 'optons',
|
||||
label_name: 'User',
|
||||
key: 'user',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
data_resource: 'users',
|
||||
},
|
||||
{
|
||||
id: 26,
|
||||
resource_id: 4,
|
||||
data_type: 'textbox',
|
||||
label_name: 'Journal Type',
|
||||
key: 'journal_type',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
|
||||
// Expenses
|
||||
{
|
||||
id: 7,
|
||||
resource_id: 3,
|
||||
label_name: 'Date',
|
||||
label_name: 'Payment Date',
|
||||
key: 'payment_date',
|
||||
data_type: 'date',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
resource_id: 3,
|
||||
label_name: 'Expense Account',
|
||||
data_type: 'options',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
resource_id: 3,
|
||||
key: 'payment_account',
|
||||
label_name: 'Payment Account',
|
||||
data_type: 'options',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
data_resource: 'accounts',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
resource_id: 3,
|
||||
key: 'total_amount',
|
||||
label_name: 'Amount',
|
||||
data_type: 'number',
|
||||
data_type: 'numeric',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 27,
|
||||
resource_id: 3,
|
||||
label_name: 'Reference No.',
|
||||
key: 'reference_no',
|
||||
data_type: 'textbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
resource_id: 3,
|
||||
key: 'description',
|
||||
label_name: 'Description',
|
||||
data_type: 'textbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 29,
|
||||
resource_id: 3,
|
||||
key: 'published',
|
||||
label_name: 'Published',
|
||||
data_type: 'checkbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
resource_id: 3,
|
||||
key: 'user',
|
||||
data_type: 'options',
|
||||
label_name: 'User',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
data_resource: 'users',
|
||||
},
|
||||
|
||||
// Items
|
||||
{
|
||||
@@ -113,7 +262,7 @@ exports.seed = (knex) => {
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
{
|
||||
id: 12,
|
||||
resource_id: 2,
|
||||
label_name: 'Type',
|
||||
@@ -122,35 +271,6 @@ exports.seed = (knex) => {
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
|
||||
// Manual Journals
|
||||
{
|
||||
id: 13,
|
||||
resource_id: 4,
|
||||
label_name: 'Transaction type',
|
||||
key: 'transaction_key',
|
||||
data_type: 'textbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
resource_id: 4,
|
||||
label_name: 'Amount',
|
||||
key: 'amount',
|
||||
data_type: 'textbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
resource_id: 4,
|
||||
label_name: 'Journal No.',
|
||||
key: 'journal_number',
|
||||
data_type: 'textbox',
|
||||
predefined: 1,
|
||||
columnable: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -22,6 +22,11 @@ exports.seed = (knex) => {
|
||||
{ id: 9, name: 'Journal', roles_logic_expression: '1', resource_id: 4, predefined: true },
|
||||
{ id: 10, name: 'Credit', roles_logic_expression: '1', resource_id: 4, predefined: true },
|
||||
{ id: 11, name: 'Reconciliation', roles_logic_expression: '1', resource_id: 4, predefined: true },
|
||||
|
||||
// Expenses
|
||||
{ id: 12, name: 'Interest', roles_logic_expression: '1', resource_id: 3, predefined: false, },
|
||||
{ id: 13, name: 'Depreciation', roles_logic_expression: '1', resource_id: 3, predefined: false, },
|
||||
{ id: 14, name: 'Payroll', roles_logic_expression: '1', resource_id: '3', predefined: false },
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -18,9 +18,12 @@ exports.seed = (knex) => {
|
||||
{ id: 8, field_id: 12, index: 1, comparator: 'equals', value: 'non-inventory', view_id: 8 },
|
||||
|
||||
// Manual Journals
|
||||
{ id: 9, field_id: 13, index: 1, comparator: 'equals', value: 'Journal', view_id: 9 },
|
||||
{ id: 10, field_id: 13, index: 1, comparator: 'equals', value: 'CreditNote', view_id: 10 },
|
||||
{ id: 11, field_id: 13, index: 1, comparator: 'equals', value: 'Reconciliation', view_id: 11 },
|
||||
{ id: 9, field_id: 26, index: 1, comparator: 'equals', value: 'Journal', view_id: 9 },
|
||||
{ id: 10, field_id: 26, index: 1, comparator: 'equals', value: 'CreditNote', view_id: 10 },
|
||||
{ id: 11, field_id: 26, index: 1, comparator: 'equals', value: 'Reconciliation', view_id: 11 },
|
||||
|
||||
// Expenses
|
||||
// { id: 12, field_id: index: }
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -75,6 +75,10 @@ export default {
|
||||
query('page').optional().isNumeric().toInt(),
|
||||
query('page_size').optional().isNumeric().toInt(),
|
||||
query('custom_view_id').optional().isNumeric().toInt(),
|
||||
|
||||
query('column_sort_by').optional(),
|
||||
query('sort_order').optional().isIn(['desc', 'asc']),
|
||||
|
||||
query('stringified_filter_roles').optional().isJSON(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
@@ -89,6 +93,7 @@ export default {
|
||||
filter_roles: [],
|
||||
page: 1,
|
||||
page_size: 999,
|
||||
sort_order: 'asc',
|
||||
...req.query,
|
||||
};
|
||||
if (filter.stringified_filter_roles) {
|
||||
@@ -135,7 +140,6 @@ export default {
|
||||
}
|
||||
dynamicFilter.setFilter(viewFilter);
|
||||
}
|
||||
|
||||
// Dynamic filter with filter roles.
|
||||
if (filter.filter_roles.length > 0) {
|
||||
// Validate the accounts resource fields.
|
||||
@@ -150,12 +154,12 @@ export default {
|
||||
}
|
||||
}
|
||||
// Dynamic filter with column sort order.
|
||||
if (filter.column_sort_order) {
|
||||
if (resourceFieldsKeys.indexOf(filter.column_sort_order) === -1) {
|
||||
if (filter.column_sort_by) {
|
||||
if (resourceFieldsKeys.indexOf(filter.column_sort_by) === -1) {
|
||||
errorReasons.push({ type: 'COLUMN.SORT.ORDER.NOT.FOUND', code: 300 });
|
||||
}
|
||||
const sortByFilter = new DynamicFilterSortBy(
|
||||
filter.column_sort_order,
|
||||
filter.column_sort_by,
|
||||
filter.sort_order,
|
||||
);
|
||||
dynamicFilter.setFilter(sortByFilter);
|
||||
@@ -169,7 +173,14 @@ export default {
|
||||
}).pagination(filter.page - 1, filter.page_size);
|
||||
|
||||
return res.status(200).send({
|
||||
manualJournals,
|
||||
manualJournals: {
|
||||
...manualJournals,
|
||||
...(view) ? {
|
||||
viewMeta: {
|
||||
customViewId: view.id,
|
||||
}
|
||||
} : {},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -201,31 +212,71 @@ export default {
|
||||
|
||||
/**
|
||||
* Validate form entries with contact customers and vendors.
|
||||
*
|
||||
* - Validate the entries that with receivable has no customer contact.
|
||||
* - Validate the entries that with payable has no vendor contact.
|
||||
* - Validate the entries with customers contacts that not found on the storage.
|
||||
* - Validate the entries with vendors contacts that not found on the storage.
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {Function} next
|
||||
*/
|
||||
async validateContactEntries(req, res, next) {
|
||||
const form = { entries: [], ...req.body };
|
||||
const { AccountType, Vendor, Customer } = req.models;
|
||||
const { Account, AccountType, Vendor, Customer } = req.models;
|
||||
const errorReasons = [];
|
||||
|
||||
// Validate the entries contact type and ids.
|
||||
const customersContacts = form.entries.filter(e => e.contact_type === 'customer');
|
||||
const vendorsContacts = form.entries.filter(e => e.contact_type === 'vendor');
|
||||
const formEntriesCustomersIds = form.entries.filter(e => e.contact_type === 'customer');
|
||||
const formEntriesVendorsIds = form.entries.filter(e => e.contact_type === 'vendor');
|
||||
|
||||
const accountsTypes = await AccountType.query();
|
||||
|
||||
const payableAccountsType = accountsTypes.find(t => t.key === 'accounts_payable');;
|
||||
const receivableAccountsType = accountsTypes.find(t => t.key === 'accounts_receivable');
|
||||
|
||||
const receivableAccountOper = Account.query().where('account_type_id', receivableAccountsType.id).first();
|
||||
const payableAccountOper = Account.query().where('account_type_id', payableAccountsType.id).first();
|
||||
|
||||
const [receivableAccount, payableAccount] = await Promise.all([
|
||||
receivableAccountOper, payableAccountOper,
|
||||
]);
|
||||
|
||||
const entriesHasNoReceivableAccount = form.entries
|
||||
.filter(e =>
|
||||
(e.account_id === receivableAccount.id) &&
|
||||
(!e.contact_id || e.contact_type !== 'customer')
|
||||
);
|
||||
|
||||
if (entriesHasNoReceivableAccount.length > 0) {
|
||||
errorReasons.push({
|
||||
type: 'RECEIVABLE.ENTRIES.HAS.NO.CUSTOMERS',
|
||||
code: 900,
|
||||
indexes: entriesHasNoReceivableAccount.map(e => e.index),
|
||||
});
|
||||
}
|
||||
|
||||
const entriesHasNoVendorContact = form.entries
|
||||
.filter(e =>
|
||||
(e.account_id === payableAccount.id) &&
|
||||
(!e.contact_id || e.contact_type !== 'contact')
|
||||
);
|
||||
|
||||
if (entriesHasNoVendorContact.length > 0) {
|
||||
errorReasons.push({
|
||||
type: 'PAYABLE.ENTRIES.HAS.NO.VENDORS',
|
||||
code: 1000,
|
||||
indexes: entriesHasNoVendorContact.map(e => e.index),
|
||||
});
|
||||
}
|
||||
|
||||
// Validate customers contacts.
|
||||
if (customersContacts.length > 0) {
|
||||
const customersContactsIds = customersContacts.map(c => c.contact_id);
|
||||
if (formEntriesCustomersIds.length > 0) {
|
||||
const customersContactsIds = formEntriesCustomersIds.map(c => c.contact_id);
|
||||
const storedContacts = await Customer.query().whereIn('id', customersContactsIds);
|
||||
|
||||
const storedContactsIds = storedContacts.map(c => c.id);
|
||||
const formEntriesCustomersIds = form.entries.filter(e => e.contact_type === 'customer');
|
||||
|
||||
const notFoundContactsIds = difference(
|
||||
formEntriesCustomersIds.map(c => c.contact_id),
|
||||
@@ -236,24 +287,23 @@ export default {
|
||||
}
|
||||
|
||||
const notReceivableAccounts = formEntriesCustomersIds.filter(
|
||||
c => receivableAccountsType && c.contact_id !== receivableAccountsType.id);
|
||||
|
||||
c => c.account_id !== receivableAccount.id
|
||||
);
|
||||
if (notReceivableAccounts.length > 0) {
|
||||
errorReasons.push({
|
||||
type: 'CUSTOMERS.ACCOUNTS.NOT.RECEIVABLE.TYPE',
|
||||
type: 'CUSTOMERS.NOT.WITH.RECEIVABLE.ACCOUNT',
|
||||
code: 700,
|
||||
indexes: notReceivableAccounts.map(a => a.index),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate vendors contacts.
|
||||
if (vendorsContacts.length > 0) {
|
||||
const vendorsContactsIds = vendorsContacts.map(c => c.contact_id);
|
||||
if (formEntriesVendorsIds.length > 0) {
|
||||
const vendorsContactsIds = formEntriesVendorsIds.map(c => c.contact_id);
|
||||
const storedContacts = await Vendor.query().where('id', vendorsContactsIds);
|
||||
|
||||
const storedContactsIds = storedContacts.map(c => c.id);
|
||||
const formEntriesVendorsIds = form.entries.filter(e => e.contact_type === 'vendor');
|
||||
|
||||
const notFoundContactsIds = difference(
|
||||
formEntriesVendorsIds.map(v => v.contact_id),
|
||||
@@ -261,21 +311,23 @@ export default {
|
||||
);
|
||||
if (notFoundContactsIds.length > 0) {
|
||||
errorReasons.push({
|
||||
type: 'VENDORS.CONTACTS.NOT.FOUND', code: 600, ids: notFoundContactsIds,
|
||||
type: 'VENDORS.CONTACTS.NOT.FOUND',
|
||||
code: 600,
|
||||
ids: notFoundContactsIds,
|
||||
});
|
||||
}
|
||||
const notPayableAccounts = formEntriesVendorsIds.filter(
|
||||
v => payableAccountsType && v.contact_id === payableAccountsType.id
|
||||
v => v.contact_id === payableAccount.id
|
||||
);
|
||||
if (notPayableAccounts.length > 0) {
|
||||
errorReasons.push({
|
||||
type: 'VENDORS.ACCOUNTS.NOT.PAYABLE.TYPE',
|
||||
type: 'VENDORS.NOT.WITH.PAYABLE.ACCOUNT',
|
||||
code: 800,
|
||||
indexes: notPayableAccounts.map(a => a.index),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
req.errorReasons = Array.isArray(req.errorReasons) && req.errorReasons.length
|
||||
? req.errorReasons.push(...errorReasons) : errorReasons;
|
||||
|
||||
@@ -289,7 +341,7 @@ export default {
|
||||
validation: [
|
||||
check('date').exists().isISO8601(),
|
||||
check('journal_number').exists().trim().escape(),
|
||||
check('transaction_type').optional({ nullable: true }).trim().escape(),
|
||||
check('journal_type').optional({ nullable: true }).trim().escape(),
|
||||
check('reference').optional({ nullable: true }),
|
||||
check('description').optional().trim().escape(),
|
||||
check('status').optional().isBoolean().toBoolean(),
|
||||
@@ -299,7 +351,7 @@ export default {
|
||||
check('entries.*.debit').optional({ nullable: true }).isNumeric().toInt(),
|
||||
check('entries.*.account_id').isNumeric().toInt(),
|
||||
check('entries.*.note').optional(),
|
||||
check('entries.*.contact_id').optional().isNumeric().toInt(),
|
||||
check('entries.*.contact_id').optional({ nullable: true }).isNumeric().toInt(),
|
||||
check('entries.*.contact_type').optional().isIn(['vendor', 'customer']),
|
||||
check('media_ids').optional().isArray(),
|
||||
check('media_ids.*').exists().isNumeric().toInt(),
|
||||
@@ -314,7 +366,7 @@ export default {
|
||||
}
|
||||
const form = {
|
||||
date: new Date(),
|
||||
transaction_type: 'journal',
|
||||
journal_type: 'journal',
|
||||
reference: '',
|
||||
media_ids: [],
|
||||
...req.body,
|
||||
@@ -351,16 +403,13 @@ export default {
|
||||
errorReasons.push({ type: 'CREDIT.DEBIT.NOT.EQUALS', code: 100 });
|
||||
}
|
||||
const formEntriesAccountsIds = entries.map((entry) => entry.account_id);
|
||||
const formEntriesContactsIds = entries.map((entry) => entry.contact_id);
|
||||
|
||||
const accounts = await Account.query()
|
||||
.whereIn('id', formEntriesAccountsIds)
|
||||
.withGraphFetched('type')
|
||||
.remember();
|
||||
.withGraphFetched('type');
|
||||
|
||||
const storedAccountsIds = accounts.map((account) => account.id);
|
||||
|
||||
|
||||
if (difference(formEntriesAccountsIds, storedAccountsIds).length > 0) {
|
||||
errorReasons.push({ type: 'ACCOUNTS.IDS.NOT.FOUND', code: 200 });
|
||||
}
|
||||
@@ -378,7 +427,7 @@ export default {
|
||||
// Save manual journal tansaction.
|
||||
const manualJournal = await ManualJournal.query().insert({
|
||||
reference: form.reference,
|
||||
transaction_type: 'Journal',
|
||||
journal_type: form.journal_type,
|
||||
journal_number: form.journal_number,
|
||||
amount: totalCredit,
|
||||
date: formattedDate,
|
||||
|
||||
@@ -497,7 +497,7 @@ export default {
|
||||
|
||||
deleteBulkAccounts: {
|
||||
validation: [
|
||||
query('ids').isArray(),
|
||||
query('ids').isArray({ min: 1 }),
|
||||
query('ids.*').isNumeric().toInt(),
|
||||
],
|
||||
async handler(req, res) {
|
||||
@@ -573,7 +573,7 @@ export default {
|
||||
*/
|
||||
bulkInactivateAccounts: {
|
||||
validation: [
|
||||
query('ids').isArray({ min: 2 }),
|
||||
query('ids').isArray({ min: 1 }),
|
||||
query('ids.*').isNumeric().toInt(),
|
||||
param('type').exists().isIn(['activate', 'inactivate']),
|
||||
],
|
||||
|
||||
@@ -346,13 +346,15 @@ export default {
|
||||
}).pagination(filter.page - 1, filter.page_size);;
|
||||
|
||||
return res.status(200).send({
|
||||
expenses,
|
||||
page_size: filter.page_size,
|
||||
page: filter.page,
|
||||
...(view) ? {
|
||||
viewColumns: view.columns,
|
||||
customViewId: view.id,
|
||||
} : {},
|
||||
expenses: {
|
||||
...expenses,
|
||||
...(view) ? {
|
||||
viewMeta: {
|
||||
viewColumns: view.columns,
|
||||
customViewId: view.id,
|
||||
}
|
||||
} : {},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor';
|
||||
import {
|
||||
getRoleFieldColumn,
|
||||
} from '@/lib/ViewRolesBuilder';
|
||||
import { getRoleFieldColumn } from '@/lib/ViewRolesBuilder';
|
||||
|
||||
export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
|
||||
|
||||
constructor(sortByFieldKey, sortDirection) {
|
||||
super();
|
||||
|
||||
@@ -18,13 +15,17 @@ export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor {
|
||||
/**
|
||||
* Builds database query of sort by column on the given direction.
|
||||
*/
|
||||
buildQuery() {
|
||||
buildQuery() {
|
||||
const { columnKey = null, value = null } = this.filterRoles;
|
||||
|
||||
return (builder) => {
|
||||
const fieldRelation = getRoleFieldColumn(this.tableName, columnKey);
|
||||
const comparatorColumn =
|
||||
fieldRelation.relationColumn ||
|
||||
`${this.tableName}.${fieldRelation.column}`;
|
||||
|
||||
if (columnKey) {
|
||||
builder.orderBy(`${this.tableName}.${fieldRelation.column}`, value.toLowerCase());
|
||||
builder.orderBy(`${comparatorColumn}`, value.toLowerCase());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,8 +88,6 @@ export function getRoleFieldColumn(tableName, columnKey) {
|
||||
return (tableFields[columnKey]) ? tableFields[columnKey] : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builds roles queries.
|
||||
* @param {String} tableName -
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class ManualJournal extends TenantModel {
|
||||
/**
|
||||
* Model timestamps.
|
||||
*/
|
||||
static get timestamps() {
|
||||
get timestamps() {
|
||||
return ['createdAt', 'updatedAt'];
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import DateSession from '@/models/DateSession';
|
||||
|
||||
export default class ModelBase extends mixin(Model, [DateSession]) {
|
||||
|
||||
static get timestamps() {
|
||||
get timestamps() {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user