feat: Receivable aging summary front-end.

This commit is contained in:
Ahmed Bouhuolia
2020-06-14 14:19:18 +02:00
parent ac9c360629
commit f0c1985e43
45 changed files with 4150 additions and 538 deletions

View File

@@ -2,7 +2,6 @@ import { createReducer } from '@reduxjs/toolkit';
import { createTableQueryReducers } from 'store/queryReducers';
import t from 'store/types';
import { omit } from 'lodash';
const initialState = {
items: {},
@@ -90,7 +89,5 @@ const reducer = createReducer(initialState, {
export default createTableQueryReducers('expenses', reducer);
export const getExpenseById = (state, id) => {
// debugger;
// state.items = omit(state.items, [id]);
return state.expenses.items[id];
return state.expenses.items[id] || {};
};

View File

@@ -23,9 +23,6 @@ export const fetchGeneralLedger = ({ query }) => {
export const fetchBalanceSheet = ({ query }) => {
return (dispatch) => new Promise((resolve, reject) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_LOADING,
});
dispatch({
type: t.BALANCE_SHEET_LOADING,
loading: true,
@@ -109,4 +106,37 @@ export const fetchJournalSheet = ({ query }) => {
resolve(response.data);
}).catch(error => { reject(error); });
});
};
};
export const fetchReceivableAgingSummary = ({ query }) => {
return (dispatch) => new Promise((resolve, reject) => {
dispatch({
type: t.RECEIVABLE_AGING_SUMMARY_LOADING,
payload: {
loading: true,
},
});
ApiService
.get('/financial_statements/receivable_aging_summary', { params: query })
.then((response) => {
dispatch({
type: t.RECEIVABLE_AGING_SUMMARY_SET,
payload: {
aging: response.data.aging,
columns: response.data.columns,
query,
},
});
dispatch({
type: t.RECEIVABLE_AGING_SUMMARY_LOADING,
payload: {
loading: false,
},
});
resolve(response);
})
.catch((error) => {
reject(error);
})
});
}

View File

@@ -1,11 +1,9 @@
import { createReducer } from '@reduxjs/toolkit';
import t from 'store/types';
import {
// getBalanceSheetIndexByQuery,
getFinancialSheetIndexByQuery,
// getFinancialSheetIndexByQuery,
} from './financialStatements.selectors';
import {omit} from 'lodash';
import { omit } from 'lodash';
const initialState = {
balanceSheet: {
@@ -34,38 +32,48 @@ const initialState = {
loading: false,
tableRows: [],
filter: true,
}
},
receivableAgingSummary: {
sheets: [],
loading: false,
tableRows: [],
filter: true,
},
};
const mapGeneralLedgerAccountsToRows = (accounts) => {
return accounts.reduce((tableRows, account) => {
const children = [];
children.push({
...account.opening, rowType: 'opening_balance',
...account.opening,
rowType: 'opening_balance',
});
account.transactions.map((transaction) => {
children.push({
...transaction, ...omit(account, ['transactions']),
rowType: 'transaction'
...transaction,
...omit(account, ['transactions']),
rowType: 'transaction',
});
});
children.push({
...account.closing, rowType: 'closing_balance',
...account.closing,
rowType: 'closing_balance',
});
tableRows.push({
...omit(account, ['transactions']), children,
...omit(account, ['transactions']),
children,
rowType: 'account_name',
});
return tableRows;
}, []);
}
};
const mapJournalTableRows = (journal) => {
return journal.reduce((rows, journal) => {
journal.entries.forEach((entry, index) => {
rows.push({
...entry,
rowType: (index === 0) ? 'first_entry' : 'entry'
rowType: index === 0 ? 'first_entry' : 'entry',
});
});
rows.push({
@@ -78,8 +86,7 @@ const mapJournalTableRows = (journal) => {
});
return rows;
}, []);
}
};
const mapProfitLossToTableRows = (profitLoss) => {
return [
@@ -92,7 +99,7 @@ const mapProfitLossToTableRows = (profitLoss) => {
name: 'Total Income',
total: profitLoss.income.total,
rowType: 'income_total',
}
},
],
},
{
@@ -104,15 +111,15 @@ const mapProfitLossToTableRows = (profitLoss) => {
name: 'Total Expenses',
total: profitLoss.expenses.total,
rowType: 'expense_total',
}
},
],
},
{
name: 'Net Income',
total: profitLoss.net_income.total,
total: profitLoss.net_income.total,
rowType: 'net_income',
}
]
},
];
};
const financialStatementFilterToggle = (financialName, statePath) => {
@@ -120,13 +127,16 @@ const financialStatementFilterToggle = (financialName, statePath) => {
[`${financialName}_FILTER_TOGGLE`]: (state, action) => {
state[statePath].filter = !state[statePath].filter;
},
}
};
};
export default createReducer(initialState, {
[t.BALANCE_SHEET_STATEMENT_SET]: (state, action) => {
const index = getFinancialSheetIndexByQuery(state.balanceSheet.sheets, action.query);
const index = getFinancialSheetIndexByQuery(
state.balanceSheet.sheets,
action.query,
);
const balanceSheet = {
accounts: action.data.accounts,
columns: Object.values(action.data.columns),
@@ -145,7 +155,10 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('BALANCE_SHEET', 'balanceSheet'),
[t.TRAIL_BALANCE_STATEMENT_SET]: (state, action) => {
const index = getFinancialSheetIndexByQuery(state.trialBalance.sheets, action.query);
const index = getFinancialSheetIndexByQuery(
state.trialBalance.sheets,
action.query,
);
const trailBalanceSheet = {
accounts: action.data.accounts,
query: action.data.query,
@@ -163,7 +176,10 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('TRIAL_BALANCE', 'trialBalance'),
[t.JOURNAL_SHEET_SET]: (state, action) => {
const index = getFinancialSheetIndexByQuery(state.journal.sheets, action.query);
const index = getFinancialSheetIndexByQuery(
state.journal.sheets,
action.query,
);
const journal = {
query: action.data.query,
@@ -183,8 +199,11 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('JOURNAL', 'journal'),
[t.GENERAL_LEDGER_STATEMENT_SET]: (state, action) => {
const index = getFinancialSheetIndexByQuery(state.generalLedger.sheets, action.query);
const index = getFinancialSheetIndexByQuery(
state.generalLedger.sheets,
action.query,
);
const generalLedger = {
query: action.data.query,
accounts: action.data.accounts,
@@ -203,7 +222,10 @@ export default createReducer(initialState, {
...financialStatementFilterToggle('GENERAL_LEDGER', 'generalLedger'),
[t.PROFIT_LOSS_SHEET_SET]: (state, action) => {
const index = getFinancialSheetIndexByQuery(state.profitLoss.sheets, action.query);
const index = getFinancialSheetIndexByQuery(
state.profitLoss.sheets,
action.query,
);
const profitLossSheet = {
query: action.query,
@@ -212,7 +234,7 @@ export default createReducer(initialState, {
tableRows: mapProfitLossToTableRows(action.profitLoss),
};
if (index !== -1) {
state.profitLoss.sheets[index] = profitLossSheet;
state.profitLoss.sheets[index] = profitLossSheet;
} else {
state.profitLoss.sheets.push(profitLossSheet);
}
@@ -222,4 +244,27 @@ export default createReducer(initialState, {
state.profitLoss.loading = !!action.loading;
},
...financialStatementFilterToggle('PROFIT_LOSS', 'profitLoss'),
});
[t.RECEIVABLE_AGING_SUMMARY_LOADING]: (state, action) => {
const { loading } = action.payload;
state.receivableAgingSummary.loading = loading;
},
[t.RECEIVABLE_AGING_SUMMARY_SET]: (state, action) => {
const { aging, columns, query } = action.payload;
const index = getFinancialSheetIndexByQuery(state.receivableAgingSummary.sheets, query);
const receivableSheet = {
query,
columns,
aging,
tableRows: aging
};
if (index !== -1) {
state.receivableAgingSummary[index] = receivableSheet;
} else {
state.receivableAgingSummary.sheets.push(receivableSheet);
}
},
...financialStatementFilterToggle('RECEIVABLE_AGING_SUMMARY', 'receivableAgingSummary'),
});

View File

@@ -15,4 +15,7 @@ export default {
PROFIT_LOSS_SHEET_SET: 'PROFIT_LOSS_SHEET_SET',
PROFIT_LOSS_SHEET_LOADING: 'PROFIT_LOSS_SHEET_LOADING',
RECEIVABLE_AGING_SUMMARY_LOADING: 'RECEIVABLE_AGING_SUMMARY_LOADING',
RECEIVABLE_AGING_SUMMARY_SET: 'RECEIVABLE_AGING_SUMMARY_SET',
}

View File

@@ -3,4 +3,5 @@
export default {
RESOURCE_COLUMNS_SET: 'RESOURCE_COLUMNS_SET',
RESOURCE_FIELDS_SET: 'RESOURCE_FIELDS_SET',
RESOURCE_DATA_SET: 'RESOURCE_DATA_SET',
};

View File

@@ -3,9 +3,6 @@ import t from 'store/types';
export const fetchResourceColumns = ({ resourceSlug }) => {
return (dispatch) => new Promise((resolve, reject) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_LOADING,
});
ApiService.get(`resources/${resourceSlug}/columns`).then((response) => {
dispatch({
type: t.RESOURCE_COLUMNS_SET,
@@ -22,9 +19,6 @@ export const fetchResourceColumns = ({ resourceSlug }) => {
export const fetchResourceFields = ({ resourceSlug }) => {
return (dispatch) => new Promise((resolve, reject) => {
dispatch({
type: t.SET_DASHBOARD_REQUEST_LOADING,
});
ApiService.get(`resources/${resourceSlug}/fields`).then((response) => {
dispatch({
type: t.RESOURCE_FIELDS_SET,
@@ -37,4 +31,19 @@ export const fetchResourceFields = ({ resourceSlug }) => {
resolve(response);
}).catch((error) => { reject(error); });
});
};
export const fetchResourceData = ({ resourceSlug }) => {
return (dispatch) => new Promise((resolve, reject) => {
ApiService.get(`/resources/${resourceSlug}/data`).then((response) => {
dispatch({
type: t.RESOURCE_DATA_SET,
payload: {
data: response.data.data,
resource_key: resourceSlug,
},
});
resolve(response);
}).catch(error => { reject(error); });
});
};

View File

@@ -3,6 +3,7 @@ import t from 'store/types';
import { pickItemsFromIds } from 'store/selectors'
const initialState = {
data: {},
fields: {},
columns: {},
resourceFields: {},
@@ -50,6 +51,14 @@ export default createReducer(initialState, {
};
state.resourceFields[action.resource_slug] = action.fields.map(f => f.id);
},
[t.RESOURCE_DATA_SET]: (state, action) => {
const { data, resource_key: resourceKey } = action.payload;
const dataMapped = {};
data.forEach((item) => { dataMapped[item.id] = item; })
state.data[resourceKey] = dataMapped;
},
});
/**
@@ -96,4 +105,9 @@ export const getResourceColumn = (state, columnId) => {
export const getResourceMetadata = (state, resourceSlug) => {
return state.resources.metadata[resourceSlug];
};
export const getResourceData = (state, resourceSlug) => {
return state.resources.data[resourceSlug] || {};
};