fix: accounts types with new design.

This commit is contained in:
a.bouhuolia
2021-01-26 12:51:13 +02:00
parent a871aea84d
commit d789228038
24 changed files with 101 additions and 100 deletions

View File

@@ -50,7 +50,6 @@ export default function DataTable(props) {
rowClassNames, rowClassNames,
payload, payload,
expandable = false, expandable = false,
expandToggleColumn = 2,
noInitialFetch = false, noInitialFetch = false,
pagesCount: controlledPageCount, pagesCount: controlledPageCount,
@@ -58,8 +57,6 @@ export default function DataTable(props) {
// Pagination props. // Pagination props.
initialPageIndex = 0, initialPageIndex = 0,
initialPageSize = 10, initialPageSize = 10,
rowContextMenu,
expandColumnSpace = 1.5,
updateDebounceTime = 200, updateDebounceTime = 200,
selectionColumnWidth = 42, selectionColumnWidth = 42,
@@ -180,6 +177,9 @@ DataTable.defaultProps = {
pagination: false, pagination: false,
spinnerProps: { size: 30 }, spinnerProps: { size: 30 },
expandToggleColumn: 1,
expandColumnSpace: 0.8,
autoResetPage: true, autoResetPage: true,
autoResetExpanded: true, autoResetExpanded: true,
autoResetGroupBy: true, autoResetGroupBy: true,

View File

@@ -7,11 +7,17 @@ import TableContext from './TableContext';
/** /**
* Tabl cell. * Tabl cell.
*/ */
export default function TableCell({ cell, row, index }) { export default function TableCell({
cell,
row: { depth, getToggleRowExpandedProps, isExpanded },
index,
}) {
const { const {
props: { expandToggleColumn, expandable } props: { expandToggleColumn, expandColumnSpace, expandable },
} = useContext(TableContext); } = useContext(TableContext);
const isExpandColumn = expandToggleColumn === index;
return ( return (
<div <div
{...cell.getCellProps({ {...cell.getCellProps({
@@ -19,34 +25,35 @@ export default function TableCell({ cell, row, index }) {
'is-text-overview': cell.column.textOverview, 'is-text-overview': cell.column.textOverview,
}), }),
})} })}
>
<div
className={classNames({
'text-overview': cell.column.textOverview,
})}
style={{
'padding-left':
isExpandColumn && expandable
? `${depth * expandColumnSpace}rem`
: '',
}}
> >
{ {
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter // Use the row.canExpand and row.getToggleRowExpandedProps prop getter
// to build the toggle for expanding a row // to build the toggle for expanding a row
} }
<If <If condition={cell.row.canExpand && expandable && isExpandColumn}>
condition={ <span {...getToggleRowExpandedProps({ className: 'expand-toggle' })}>
cell.row.canExpand && expandable && index === expandToggleColumn
}
>
<span
{...row.getToggleRowExpandedProps({ className: 'expand-toggle' })}
>
<span <span
className={classNames({ className={classNames({
'arrow-down': row.isExpanded, 'arrow-down': isExpanded,
'arrow-right': !row.isExpanded, 'arrow-right': !isExpanded,
})} })}
/> />
</span> </span>
</If> </If>
<ConditionalWrapper
condition={cell.column.textOverview}
wrapper={(children) => <span class="text-overview">{children}</span>}
>
{cell.render('Cell')} {cell.render('Cell')}
</ConditionalWrapper> </div>
</div> </div>
); );
} }

View File

@@ -12,7 +12,7 @@ export default function TablePage() {
loading, loading,
TableRowsRenderer, TableRowsRenderer,
TableLoadingRenderer, TableLoadingRenderer,
TableNoResultsRow, TableNoResultsRowRenderer,
}, },
} = useContext(TableContext); } = useContext(TableContext);
@@ -20,7 +20,7 @@ export default function TablePage() {
return <TableLoadingRenderer spinnerProps={spinnerProps} />; return <TableLoadingRenderer spinnerProps={spinnerProps} />;
} }
if (page.length === 0) { if (page.length === 0) {
return <TableNoResultsRow />; return <TableNoResultsRowRenderer />;
} }
return (<TableRowsRenderer />); return (<TableRowsRenderer />);
} }

View File

@@ -103,7 +103,7 @@ function BalanceSheetTable({
expanded={expandedRows} expanded={expandedRows}
expandToggleColumn={1} expandToggleColumn={1}
expandColumnSpace={0.8} expandColumnSpace={0.8}
sticky={true} // sticky={true}
/> />
</FinancialSheet> </FinancialSheet>
); );

View File

@@ -101,6 +101,7 @@ function ProfitLossSheetTable({
rowClassNames={rowClassNames} rowClassNames={rowClassNames}
expandable={true} expandable={true}
expandToggleColumn={1} expandToggleColumn={1}
sticky={true} sticky={true}
/> />
</FinancialSheet> </FinancialSheet>

View File

@@ -1,4 +1,7 @@
import { IBalanceSheetStructureSection } from 'interfaces'; import { IBalanceSheetStructureSection } from 'interfaces';
import {
ACCOUNT_TYPE
} from 'data/AccountTypes';
const balanceSheetStructure: IBalanceSheetStructureSection[] = [ const balanceSheetStructure: IBalanceSheetStructureSection[] = [
{ {
@@ -14,22 +17,22 @@ const balanceSheetStructure: IBalanceSheetStructureSection[] = [
{ {
name: 'Cash and cash equivalents', name: 'Cash and cash equivalents',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['cash', 'bank'], accountsTypes: [ACCOUNT_TYPE.CASH, ACCOUNT_TYPE.BANK],
}, },
{ {
name: 'Accounts Receivable', name: 'Accounts Receivable',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['accounts_receivable'], accountsTypes: [ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE],
}, },
{ {
name: 'Inventories', name: 'Inventories',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['inventory'], accountsTypes: [ACCOUNT_TYPE.INVENTORY],
}, },
{ {
name: 'Other current assets', name: 'Other current assets',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['other_current_asset'], accountsTypes: [ACCOUNT_TYPE.OTHER_CURRENT_ASSET],
}, },
], ],
alwaysShow: true, alwaysShow: true,
@@ -37,12 +40,12 @@ const balanceSheetStructure: IBalanceSheetStructureSection[] = [
{ {
name: 'Fixed Asset', name: 'Fixed Asset',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['fixed_asset'], accountsTypes: [ACCOUNT_TYPE.FIXED_ASSET],
}, },
{ {
name: 'Non-Current Assets', name: 'Non-Current Assets',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['non_current_asset'], accountsTypes: [ACCOUNT_TYPE.NON_CURRENT_ASSET],
} }
], ],
alwaysShow: true, alwaysShow: true,
@@ -61,21 +64,21 @@ const balanceSheetStructure: IBalanceSheetStructureSection[] = [
name: 'Current Liabilties', name: 'Current Liabilties',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: [ accountsTypes: [
'accounts_payable', ACCOUNT_TYPE.ACCOUNTS_PAYABLE,
'tax_payable', ACCOUNT_TYPE.TAX_PAYABLE,
'credit_card', ACCOUNT_TYPE.CREDIT_CARD,
'other_current_liability' ACCOUNT_TYPE.OTHER_CURRENT_LIABILITY,
], ],
}, },
{ {
name: 'Long-Term Liabilities', name: 'Long-Term Liabilities',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['long_term_liability'], accountsTypes: [ACCOUNT_TYPE.LOGN_TERM_LIABILITY],
}, },
{ {
name: 'Non-Current Liabilities', name: 'Non-Current Liabilities',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['non_current_liability'], accountsTypes: [ACCOUNT_TYPE.NON_CURRENT_LIABILITY],
} }
], ],
}, },
@@ -83,7 +86,7 @@ const balanceSheetStructure: IBalanceSheetStructureSection[] = [
name: 'Equity', name: 'Equity',
sectionType: 'equity', sectionType: 'equity',
type: 'accounts_section', type: 'accounts_section',
accountsTypes: ['equity'], accountsTypes: [ACCOUNT_TYPE.EQUITY],
}, },
], ],
alwaysShow: true, alwaysShow: true,

View File

@@ -10,6 +10,9 @@ exports.up = function(knex) {
table.integer('account_id').unsigned().index().references('id').inTable('accounts'); table.integer('account_id').unsigned().index().references('id').inTable('accounts');
table.string('contact_type').nullable().index(); table.string('contact_type').nullable().index();
table.integer('contact_id').unsigned().nullable().index(); table.integer('contact_id').unsigned().nullable().index();
table.string('transaction_number').nullable().index();
table.string('reference_number').nullable().index();
table.integer('item_id').unsigned().nullable().index();
table.string('note'); table.string('note');
table.integer('user_id').unsigned().index(); table.integer('user_id').unsigned().index();
table.integer('index').unsigned(); table.integer('index').unsigned();

View File

@@ -118,8 +118,8 @@ export default [
predefined: 0, predefined: 0,
}, },
{ {
name:'Opening Balance Adjustments', name:'Opening Balance Liabilities',
slug: 'opening-balance-adjustments', slug: 'opening-balance-liabilities',
account_type: 'other-current-liability', account_type: 'other-current-liability',
code: '20004', code: '20004',
description:'This account will hold the difference in the debits and credits entered during the opening balance..', description:'This account will hold the difference in the debits and credits entered during the opening balance..',
@@ -193,9 +193,9 @@ export default [
// Expenses // Expenses
{ {
name:'Uncategorized Expenses', name:'Other Expenses',
slug: 'uncategorized-expense', slug: 'other-expenses',
account_type: 'expense', account_type: 'other-expense',
parent_account_id: null, parent_account_id: null,
code: '40001', code: '40001',
description: '', description: '',

View File

@@ -24,6 +24,8 @@ export interface IAccount {
currencyCode: string, currencyCode: string,
transactions?: any[], transactions?: any[],
type?: any[], type?: any[],
accountNormal: string,
accountParentType: string,
}; };
export interface IAccountsFilter extends IDynamicListFilterDTO { export interface IAccountsFilter extends IDynamicListFilterDTO {

View File

@@ -179,14 +179,6 @@ export default class Account extends TenantModel {
return this.isProfitLossSheet(); return this.isProfitLossSheet();
} }
static collectJournalEntries(accounts) {
return flatten(accounts.map((account) => account.transactions.map((transaction) => ({
accountId: account.id,
...transaction,
accountNormal: account.type.normal,
}))));
}
/** /**
* Converts flatten accounts list to nested array. * Converts flatten accounts list to nested array.
* @param {Array} accounts * @param {Array} accounts
@@ -196,6 +188,10 @@ export default class Account extends TenantModel {
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
*/
static toDependencyGraph(accounts) { static toDependencyGraph(accounts) {
return DependencyGraph.fromArray( return DependencyGraph.fromArray(
accounts, { itemId: 'id', parentItemId: 'parentAccountId' } accounts, { itemId: 'id', parentItemId: 'parentAccountId' }

View File

@@ -24,6 +24,15 @@ export default class AccountRepository extends TenantRepository {
}); });
} }
/**
* Retrieve.
* @param {string} slug
* @return {Promise<IAccount>}
*/
findBySlug(slug: string) {
return this.findOne({ slug });
}
/** /**
* Changes account balance. * Changes account balance.
* @param {number} accountId * @param {number} accountId

View File

@@ -31,7 +31,7 @@ export default class AccountTransactionsRepository extends TenantRepository {
return this.model.query() return this.model.query()
.modify('filterAccounts', filter.accountsIds) .modify('filterAccounts', filter.accountsIds)
.modify('filterDateRange', filter.fromDate, filter.toDate) .modify('filterDateRange', filter.fromDate, filter.toDate)
.withGraphFetched('account.type') .withGraphFetched('account')
.onBuild((query) => { .onBuild((query) => {
if (filter.sumationCreditDebit) { if (filter.sumationCreditDebit) {
query.modify('sumationCreditDebit'); query.modify('sumationCreditDebit');

View File

@@ -269,7 +269,7 @@ export default class JournalCommands {
'reference_id', 'reference_id',
Array.isArray(referenceId) ? referenceId : [referenceId] Array.isArray(referenceId) ? referenceId : [referenceId]
) )
.withGraphFetched('account.type'); .withGraphFetched('account');
this.journal.fromTransactions(transactions); this.journal.fromTransactions(transactions);
this.journal.removeEntries(); this.journal.removeEntries();

View File

@@ -165,7 +165,6 @@ export default class JournalPoster implements IJournalPoster {
private async convertBalanceChangesToArr( private async convertBalanceChangesToArr(
accountsChange: IAccountsChange accountsChange: IAccountsChange
) : Promise<{ account: number, change: number }[]>{ ) : Promise<{ account: number, change: number }[]>{
const { accountTypeRepository } = this.repositories;
const mappedList: { account: number, change: number }[] = []; const mappedList: { account: number, change: number }[] = [];
const accountsIds: number[] = Object.keys(accountsChange).map(id => parseInt(id, 10)); const accountsIds: number[] = Object.keys(accountsChange).map(id => parseInt(id, 10));
@@ -173,8 +172,8 @@ export default class JournalPoster implements IJournalPoster {
accountsIds.map(async (account: number) => { accountsIds.map(async (account: number) => {
const accountChange = accountsChange[account]; const accountChange = accountsChange[account];
const accountNode = this.accountsDepGraph.getNodeData(account); const accountNode = this.accountsDepGraph.getNodeData(account);
const accountTypeMeta = await accountTypeRepository.findOneById(accountNode.accountTypeId);
const { normal }: { normal: TEntryType } = accountTypeMeta; const { normal }: { normal: TEntryType } = accountNode.accountNormal;
let change = 0; let change = 0;
if (accountChange.credit) { if (accountChange.credit) {
@@ -333,7 +332,7 @@ export default class JournalPoster implements IJournalPoster {
...transaction, ...transaction,
referenceTypeFormatted: transaction.referenceTypeFormatted, referenceTypeFormatted: transaction.referenceTypeFormatted,
account: transaction.accountId, account: transaction.accountId,
accountNormal: get(transaction, 'account.type.normal'), accountNormal: get(transaction, 'account.accountNormal'),
}); });
}); });
} }

View File

@@ -184,7 +184,7 @@ export default class BalanceSheetStatement extends FinancialSheet {
const filteredAccounts = accounts const filteredAccounts = accounts
// Filter accounts that associated to the section accounts types. // Filter accounts that associated to the section accounts types.
.filter( .filter(
(account) => sectionAccountsTypes.indexOf(account.type.key) !== -1 (account) => sectionAccountsTypes.indexOf(account.accountType) !== -1
) )
.map((account) => this.balanceSheetAccountMapper(account)) .map((account) => this.balanceSheetAccountMapper(account))
// Filter accounts that have no transaction when `noneTransactions` is on. // Filter accounts that have no transaction when `noneTransactions` is on.

View File

@@ -70,7 +70,7 @@ export default class BalanceSheetStatementService
this.logger.info('[balance_sheet] trying to calculate the report.', { filter, tenantId }); this.logger.info('[balance_sheet] trying to calculate the report.', { filter, tenantId });
// Retrieve all accounts on the storage. // Retrieve all accounts on the storage.
const accounts = await accountRepository.all('type'); const accounts = await accountRepository.all();
const accountsGraph = await accountRepository.getDependencyGraph(); const accountsGraph = await accountRepository.getDependencyGraph();
// Retrieve all journal transactions based on the given query. // Retrieve all journal transactions based on the given query.

View File

@@ -6,7 +6,6 @@ import {
IGeneralLedgerSheetAccountTransaction, IGeneralLedgerSheetAccountTransaction,
IAccount, IAccount,
IJournalPoster, IJournalPoster,
IAccountType,
IJournalEntry, IJournalEntry,
IContact, IContact,
} from 'interfaces'; } from 'interfaces';
@@ -130,7 +129,7 @@ export default class GeneralLedgerSheet extends FinancialSheet {
* @return {IGeneralLedgerSheetAccountTransaction[]} * @return {IGeneralLedgerSheetAccountTransaction[]}
*/ */
private accountTransactionsMapper( private accountTransactionsMapper(
account: IAccount & { type: IAccountType }, account: IAccount,
openingBalance: number openingBalance: number
): IGeneralLedgerSheetAccountTransaction[] { ): IGeneralLedgerSheetAccountTransaction[] {
const entries = this.transactions.getAccountEntries(account.id); const entries = this.transactions.getAccountEntries(account.id);
@@ -184,7 +183,7 @@ export default class GeneralLedgerSheet extends FinancialSheet {
* @return {IGeneralLedgerSheetAccount} * @return {IGeneralLedgerSheetAccount}
*/ */
private accountMapper( private accountMapper(
account: IAccount & { type: IAccountType } account: IAccount
): IGeneralLedgerSheetAccount { ): IGeneralLedgerSheetAccount {
const openingBalance = this.accountOpeningBalance(account); const openingBalance = this.accountOpeningBalance(account);
const closingBalance = this.accountClosingBalance(account); const closingBalance = this.accountClosingBalance(account);
@@ -210,11 +209,11 @@ export default class GeneralLedgerSheet extends FinancialSheet {
* @return {IGeneralLedgerSheetAccount[]} * @return {IGeneralLedgerSheetAccount[]}
*/ */
private accountsWalker( private accountsWalker(
accounts: IAccount & { type: IAccountType }[] accounts: IAccount[]
): IGeneralLedgerSheetAccount[] { ): IGeneralLedgerSheetAccount[] {
return ( return (
accounts accounts
.map((account: IAccount & { type: IAccountType }) => .map((account: IAccount) =>
this.accountMapper(account) this.accountMapper(account)
) )
// Filter general ledger accounts that have no transactions // Filter general ledger accounts that have no transactions

View File

@@ -89,7 +89,7 @@ export default class GeneralLedgerService {
key: 'base_currency', key: 'base_currency',
}); });
// Retrieve all accounts with associated type from the storage. // Retrieve all accounts with associated type from the storage.
const accounts = await accountRepository.all('type'); const accounts = await accountRepository.all();
const accountsGraph = await accountRepository.getDependencyGraph(); const accountsGraph = await accountRepository.getDependencyGraph();
// Retrieve all contacts on the storage. // Retrieve all contacts on the storage.

View File

@@ -12,6 +12,7 @@ import {
IProfitLossSheetTotalSection, IProfitLossSheetTotalSection,
} from 'interfaces'; } from 'interfaces';
import { flatToNestedArray, dateRangeCollection } from 'utils'; import { flatToNestedArray, dateRangeCollection } from 'utils';
import { ACCOUNT_TYPE } from 'data/AccountTypes';
export default class ProfitLossSheet extends FinancialSheet { export default class ProfitLossSheet extends FinancialSheet {
tenantId: number; tenantId: number;
@@ -51,7 +52,7 @@ export default class ProfitLossSheet extends FinancialSheet {
} }
get otherIncomeAccounts() { get otherIncomeAccounts() {
return this.accounts.filter((a) => a.type.key === 'other_income'); return this.accounts.filter((a) => a.accountType === ACCOUNT_TYPE.OTHER_INCOME);
} }
/** /**
@@ -59,7 +60,7 @@ export default class ProfitLossSheet extends FinancialSheet {
* @return {IAccount & { type: IAccountType }[]} * @return {IAccount & { type: IAccountType }[]}
*/ */
get incomeAccounts() { get incomeAccounts() {
return this.accounts.filter((a) => a.type.key === 'income'); return this.accounts.filter((a) => a.accountType === ACCOUNT_TYPE.INCOME);
} }
/** /**
@@ -67,7 +68,7 @@ export default class ProfitLossSheet extends FinancialSheet {
* @return {IAccount & { type: IAccountType }[]} * @return {IAccount & { type: IAccountType }[]}
*/ */
get expensesAccounts() { get expensesAccounts() {
return this.accounts.filter((a) => a.type.key === 'expense'); return this.accounts.filter((a) => a.accountType === ACCOUNT_TYPE.EXPENSE);
} }
/** /**
@@ -75,7 +76,7 @@ export default class ProfitLossSheet extends FinancialSheet {
* @return {IAccount & { type: IAccountType }[]}} * @return {IAccount & { type: IAccountType }[]}}
*/ */
get otherExpensesAccounts() { get otherExpensesAccounts() {
return this.accounts.filter((a) => a.type.key === 'other_expense'); return this.accounts.filter((a) => a.accountType === ACCOUNT_TYPE.OTHER_EXPENSE);
} }
/** /**
@@ -83,7 +84,7 @@ export default class ProfitLossSheet extends FinancialSheet {
* @return {IAccount & { type: IAccountType }[]} * @return {IAccount & { type: IAccountType }[]}
*/ */
get costOfSalesAccounts() { get costOfSalesAccounts() {
return this.accounts.filter((a) => a.type.key === 'cost_of_goods_sold'); return this.accounts.filter((a) => a.accountType === ACCOUNT_TYPE.COST_OF_GOODS_SOLD);
} }
/** /**

View File

@@ -77,7 +77,7 @@ export default class ProfitLossSheetService {
key: 'base_currency', key: 'base_currency',
}); });
// Retrieve all accounts on the storage. // Retrieve all accounts on the storage.
const accounts = await accountRepository.all('type'); const accounts = await accountRepository.all();
const accountsGraph = await accountRepository.getDependencyGraph(); const accountsGraph = await accountRepository.getDependencyGraph();
// Retrieve all journal transactions based on the given query. // Retrieve all journal transactions based on the given query.

View File

@@ -65,7 +65,7 @@ export default class TrialBalanceSheet extends FinancialSheet {
parentAccountId: account.parentAccountId, parentAccountId: account.parentAccountId,
name: account.name, name: account.name,
code: account.code, code: account.code,
accountNormal: account.type.normal, accountNormal: account.accountNormal,
hasTransactions: entries.length > 0, hasTransactions: entries.length > 0,
credit: trial.credit, credit: trial.credit,

View File

@@ -69,7 +69,7 @@ export default class TrialBalanceSheetService extends FinancialSheet {
filter, filter,
}); });
// Retrieve all accounts on the storage. // Retrieve all accounts on the storage.
const accounts = await accountRepository.all('type'); const accounts = await accountRepository.all();
const accountsGraph = await accountRepository.getDependencyGraph(); const accountsGraph = await accountRepository.getDependencyGraph();
// Retrieve all journal transactions based on the given query. // Retrieve all journal transactions based on the given query.

View File

@@ -513,7 +513,7 @@ export default class BillPaymentsService {
const transactions = await AccountTransaction.query() const transactions = await AccountTransaction.query()
.whereIn('reference_type', ['BillPayment']) .whereIn('reference_type', ['BillPayment'])
.where('reference_id', billPayment.id) .where('reference_id', billPayment.id)
.withGraphFetched('account.type'); .withGraphFetched('account');
journal.loadEntries(transactions); journal.loadEntries(transactions);
journal.removeEntries(); journal.removeEntries();

View File

@@ -10,23 +10,4 @@ export default class ItemsSubscriber{
constructor() { constructor() {
this.itemsService = Container.get(ItemsService); this.itemsService = Container.get(ItemsService);
}; };
/**
* Handle writing opening item inventory transaction.
*/
@On(events.item.onCreated)
handleWriteOpeningInventoryTransaction({ tenantId, item }) {
// Can't continue if the opeing cost, quantity or opening date was empty.
if (!item.openingCost || !item.openingQuantity || !item.openingDate) {
return;
}
// Records the opeing items inventory transaction once the item created.
this.itemsService.recordOpeningItemsInventoryTransaction(
tenantId,
item.id,
item.openingQuantity,
item.openingCost,
item.openingDate,
)
}
} }