+
+
+
+
+
+ {({
+ form: { setFieldValue },
+ field: { value },
+ meta: { error, touched },
+ }) => (
+ }
+ className={classNames('form-group--select-list', Classes.FILL)}
+ >
+ {
+ setFieldValue('itemsIds', itemsIds);
+ }}
+ />
+
+ )}
+
+
+
);
}
diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.js
index 9c8a28f93..6b15ac729 100644
--- a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.js
+++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.js
@@ -12,7 +12,7 @@ import PurchasesByItemsGeneralPanel from './PurchasesByItemsGeneralPanel';
import withPurchasesByItems from './withPurchasesByItems';
import withPurchasesByItemsActions from './withPurchasesByItemsActions';
-import { compose } from 'utils';
+import { compose, transformToForm } from 'utils';
/**
* Purchases by items header.
@@ -28,25 +28,31 @@ function PurchasesByItemsHeader({
// #withPurchasesByItems
togglePurchasesByItemsFilterDrawer,
}) {
-
-
// Form validation schema.
const validationSchema = Yup.object().shape({
- fromDate: Yup.date()
- .required()
- .label(intl.get('from_date')),
+ fromDate: Yup.date().required().label(intl.get('from_date')),
toDate: Yup.date()
.min(Yup.ref('fromDate'))
.required()
.label(intl.get('to_date')),
});
- // Initial values.
- const initialValues = {
+ // Default form values.
+ const defaultValues = {
...pageFilter,
- fromDate: moment(pageFilter.fromDate).toDate(),
- toDate: moment(pageFilter.toDate).toDate(),
+ fromDate: moment().toDate(),
+ toDate: moment().toDate(),
+ itemsIds: [],
};
+ // Initial form values.
+ const initialValues = transformToForm(
+ {
+ ...pageFilter,
+ fromDate: moment(pageFilter.fromDate).toDate(),
+ toDate: moment(pageFilter.toDate).toDate(),
+ },
+ defaultValues,
+ );
// Handle form submit.
const handleSubmit = (values, { setSubmitting }) => {
diff --git a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js
index 9de8c6c47..b49757a96 100644
--- a/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js
+++ b/client/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsProvider.js
@@ -1,12 +1,13 @@
import React, { createContext, useContext } from 'react';
import FinancialReportPage from '../FinancialReportPage';
-import { usePurchasesByItems } from 'hooks/query';
+import { usePurchasesByItems, useItems } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const PurchasesByItemsContext = createContext();
function PurchasesByItemsProvider({ query, ...props }) {
+ // Handle fetching the purchases by items report based on the given query.
const {
data: purchaseByItems,
isFetching,
@@ -21,11 +22,23 @@ function PurchasesByItemsProvider({ query, ...props }) {
},
);
+ // Handle fetching the items based on the given query.
+ const {
+ data: { items },
+ isLoading: isItemsLoading,
+ isFetching: isItemsFetching,
+ } = useItems({ page_size: 10000 });
+
const provider = {
purchaseByItems,
isFetching,
isLoading,
- refetchSheet: refetch,
+
+ items,
+ isItemsLoading,
+ isItemsFetching,
+
+ refetchSheet: refetch,
};
return (
diff --git a/client/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.js b/client/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.js
index 86ce8b8a1..54bd0b174 100644
--- a/client/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.js
+++ b/client/src/containers/FinancialStatements/SalesByItems/SalesByItemProvider.js
@@ -1,6 +1,6 @@
import React, { createContext, useContext } from 'react';
import FinancialReportPage from '../FinancialReportPage';
-import { useSalesByItems } from 'hooks/query';
+import { useSalesByItems, useItems } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const SalesByItemsContext = createContext();
@@ -20,10 +20,22 @@ function SalesByItemProvider({ query, ...props }) {
},
);
+ // Handle fetching the items based on the given query.
+ const {
+ data: { items },
+ isLoading: isItemsLoading,
+ isFetching: isItemsFetching,
+ } = useItems({ page_size: 10000 });
+
const provider = {
salesByItems,
isFetching,
isLoading,
+
+ items,
+ isItemsLoading,
+ isItemsFetching,
+
refetchSheet: refetch,
};
return (
diff --git a/client/src/containers/FinancialStatements/SalesByItems/SalesByItems.js b/client/src/containers/FinancialStatements/SalesByItems/SalesByItems.js
index 7fb334fc1..73c159396 100644
--- a/client/src/containers/FinancialStatements/SalesByItems/SalesByItems.js
+++ b/client/src/containers/FinancialStatements/SalesByItems/SalesByItems.js
@@ -68,7 +68,7 @@ function SalesByItems({
/>
-
+
+
+
+
+
+ {({
+ form: { setFieldValue },
+ field: { value },
+ meta: { error, touched },
+ }) => (
+ }
+ className={classNames('form-group--select-list', Classes.FILL)}
+ >
+ {
+ setFieldValue('itemsIds', itemsIds);
+ }}
+ />
+
+ )}
+
+
+
);
}
diff --git a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetHeader.js b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetHeader.js
index de60c8718..77e993c85 100644
--- a/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetHeader.js
+++ b/client/src/containers/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetHeader.js
@@ -12,7 +12,7 @@ import TrialBalanceSheetHeaderGeneralPanel from './TrialBalanceSheetHeaderGenera
import withTrialBalance from './withTrialBalance';
import withTrialBalanceActions from './withTrialBalanceActions';
-import { compose } from 'utils';
+import { compose, transformToForm } from 'utils';
/**
* Trial balance sheet header.
@@ -28,42 +28,41 @@ function TrialBalanceSheetHeader({
// #withTrialBalanceActions
toggleTrialBalanceFilterDrawer: toggleFilterDrawer,
}) {
-
-
// Form validation schema.
const validationSchema = Yup.object().shape({
- fromDate: Yup.date()
- .required()
- .label(intl.get('from_date')),
+ fromDate: Yup.date().required().label(intl.get('from_date')),
toDate: Yup.date()
.min(Yup.ref('fromDate'))
.required()
.label(intl.get('to_date')),
});
- // Initial values.
- const initialValues = {
- ...pageFilter,
- fromDate: moment(pageFilter.fromDate).toDate(),
- toDate: moment(pageFilter.toDate).toDate(),
+ // Default values.
+ const defaultValues = {
+ fromDate: moment().toDate(),
+ toDate: moment().toDate(),
};
+ // Initial values.
+ const initialValues = transformToForm(
+ {
+ ...pageFilter,
+ fromDate: moment(pageFilter.fromDate).toDate(),
+ toDate: moment(pageFilter.toDate).toDate(),
+ },
+ defaultValues,
+ );
// Handle form submit.
const handleSubmit = (values, { setSubmitting }) => {
onSubmitFilter(values);
setSubmitting(false);
toggleFilterDrawer(false);
};
-
// Handle drawer close action.
- const handleDrawerClose = () => {
- toggleFilterDrawer(false);
- };
+ const handleDrawerClose = () => { toggleFilterDrawer(false); };
// Handle cancel button click.
- const handleCancelClick = () => {
- toggleFilterDrawer(false);
- };
+ const handleCancelClick = () => { toggleFilterDrawer(false); };
return (
{
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js
index 7ac062a36..e599fc02d 100644
--- a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeaderGeneral.js
@@ -1,8 +1,9 @@
import React from 'react';
-import { FastField } from 'formik';
+import { Field, FastField } from 'formik';
import { DateInput } from '@blueprintjs/datetime';
+import classNames from 'classnames';
import { FormGroup, Position, Classes, Checkbox } from '@blueprintjs/core';
-import { FormattedMessage as T } from 'components';
+import { ContactsMultiSelect, FormattedMessage as T } from 'components';
import { Row, Col, FieldHint } from 'components';
import {
momentFormatter,
@@ -10,11 +11,14 @@ import {
inputIntent,
handleDateChange,
} from 'utils';
+import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
/**
* Vendors balance header -general panel.
*/
export default function VendorsBalanceSummaryHeaderGeneral() {
+ const { vendors } = useVendorsBalanceSummaryContext();
+
return (
@@ -42,6 +46,7 @@ export default function VendorsBalanceSummaryHeaderGeneral() {
+
@@ -59,6 +64,31 @@ export default function VendorsBalanceSummaryHeaderGeneral() {
+
+
+
+
+ {({
+ form: { setFieldValue },
+ field: { value },
+ meta: { error, touched },
+ }) => (
+ }
+ className={classNames('form-group--select-list', Classes.FILL)}
+ >
+ {
+ setFieldValue('vendorsIds', contactsIds);
+ }}
+ contacts={vendors}
+ contactsSelected={value}
+ />
+
+ )}
+
+
+
);
}
diff --git a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js
index 840b45268..db2847d64 100644
--- a/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js
+++ b/client/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryProvider.js
@@ -1,6 +1,6 @@
import React from 'react';
import FinancialReportPage from '../FinancialReportPage';
-import { useVendorsBalanceSummaryReport } from 'hooks/query';
+import { useVendorsBalanceSummaryReport, useVendors } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const VendorsBalanceSummaryContext = React.createContext();
@@ -13,6 +13,7 @@ function VendorsBalanceSummaryProvider({ filter, ...props }) {
filter,
]);
+ // Fetching vendors balance summary report based on the given query.
const {
data: VendorBalanceSummary,
isLoading: isVendorsBalanceLoading,
@@ -22,10 +23,23 @@ function VendorsBalanceSummaryProvider({ filter, ...props }) {
keepPreviousData: true,
});
+ // Fetch vendors list with pagination meta.
+ const {
+ data: { vendors },
+ isLoading: isVendorsLoading,
+ isFetching: isVendorsFetching,
+ } = useVendors({ page_size: 1000000 });
+
+ // Provider.
const provider = {
VendorBalanceSummary,
isVendorsBalanceLoading,
isVendorsBalanceFetching,
+
+ vendors,
+ isVendorsFetching,
+ isVendorsLoading,
+
refetch,
};
diff --git a/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.js b/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.js
index babf5f7c8..d3e29f513 100644
--- a/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.js
+++ b/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.js
@@ -12,7 +12,7 @@ import VendorsTransactionsHeaderGeneralPanel from './VendorsTransactionsHeaderGe
import withVendorsTransaction from './withVendorsTransaction';
import withVendorsTransactionsActions from './withVendorsTransactionsActions';
-import { compose } from 'utils';
+import { compose, transformToForm } from 'utils';
/**
* Vendors transactions header.
@@ -29,14 +29,19 @@ function VendorsTransactionsHeader({
//#withVendorsTransactionsActions
toggleVendorsTransactionsFilterDrawer: toggleFilterDrawer,
}) {
-
+ // Default form values.
+ const defaultValues = {
+ fromDate: moment().toDate(),
+ toDate: moment().toDate(),
+ vendorsIds: [],
+ };
- // Filter form initial values.
- const initialValues = {
+ // Initial form values.
+ const initialValues = transformToForm({
...pageFilter,
fromDate: moment(pageFilter.fromDate).toDate(),
toDate: moment(pageFilter.toDate).toDate(),
- };
+ }, defaultValues);
// Validation schema.
const validationSchema = Yup.object().shape({
@@ -57,9 +62,7 @@ function VendorsTransactionsHeader({
};
// Handle drawer close action.
- const handleDrawerClose = () => {
- toggleFilterDrawer(false);
- };
+ const handleDrawerClose = () => { toggleFilterDrawer(false); };
return (
+
+
+
+
+ {({ form: { setFieldValue }, field: { value } }) => (
+ }
+ className={classNames('form-group--select-list', Classes.FILL)}
+ >
+ {
+ setFieldValue('vendorsIds', contactsIds);
+ }}
+ contacts={vendors}
+ contactsSelected={value}
+ />
+
+ )}
+
+
+
);
}
diff --git a/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsProvider.js b/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsProvider.js
index afbf44242..a15a40f23 100644
--- a/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsProvider.js
+++ b/client/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsProvider.js
@@ -1,6 +1,6 @@
import React, { createContext, useContext, useMemo } from 'react';
import FinancialReportPage from '../FinancialReportPage';
-import { useVendorsTransactionsReport } from 'hooks/query';
+import { useVendorsTransactionsReport, useVendors } from 'hooks/query';
import { transformFilterFormToQuery } from '../common';
const VendorsTransactionsContext = createContext();
@@ -11,6 +11,7 @@ const VendorsTransactionsContext = createContext();
function VendorsTransactionsProvider({ filter, ...props }) {
const query = useMemo(() => transformFilterFormToQuery(filter), [filter]);
+ // Fetch vendors transactions based on the given query.
const {
data: vendorsTransactions,
isFetching: isVendorsTransactionFetching,
@@ -18,10 +19,22 @@ function VendorsTransactionsProvider({ filter, ...props }) {
refetch,
} = useVendorsTransactionsReport(query, { keepPreviousData: true });
+ // Fetch vendors list based on the given query.
+ const {
+ data: { vendors },
+ isLoading: isVendorsLoading,
+ isFetching: isVendorsFetching,
+ } = useVendors({ page_size: 100000 });
+
const provider = {
vendorsTransactions,
isVendorsTransactionsLoading,
isVendorsTransactionFetching,
+
+ vendors,
+ isVendorsLoading,
+
+ isVendorsFetching,
refetch,
filter,
query,
diff --git a/client/src/containers/FinancialStatements/common.js b/client/src/containers/FinancialStatements/common.js
index d9234a63d..fa5e760e9 100644
--- a/client/src/containers/FinancialStatements/common.js
+++ b/client/src/containers/FinancialStatements/common.js
@@ -82,5 +82,5 @@ export const transformFilterFormToQuery = (form) => {
noneZero: form.accountsFilter === 'without-zero-balance',
noneTransactions: form.accountsFilter === 'with-transactions',
});
- return flatObject(transformed);
+ return transformed;
};
diff --git a/client/src/lang/en/index.json b/client/src/lang/en/index.json
index 1643a7891..a1e7da419 100644
--- a/client/src/lang/en/index.json
+++ b/client/src/lang/en/index.json
@@ -1136,5 +1136,12 @@
"select_transaction":"Select transaction account",
"details":"Details",
"located_landed_cost":"Located Landed Cost",
- "delete_transaction":"Delete transaction"
+ "delete_transaction":"Delete transaction",
+ "all_items": "All items",
+ "Specific items": "Specific items",
+ "Selected contacts": "Selected contacts",
+ "All contacts": "All contacts",
+ "Selected items ({count})": "Selected items ({count})",
+ "All items": "All items",
+ "No items": "No items"
}
\ No newline at end of file
diff --git a/client/src/style/pages/FinancialStatements/ARAgingSummary.scss b/client/src/style/pages/FinancialStatements/ARAgingSummary.scss
index d663e5f8a..2bb2d6f5f 100644
--- a/client/src/style/pages/FinancialStatements/ARAgingSummary.scss
+++ b/client/src/style/pages/FinancialStatements/ARAgingSummary.scss
@@ -36,4 +36,13 @@
}
}
}
+}
+
+.financial-statement--AR-aging-summary{
+
+ .financial-header-drawer{
+ .bp3-drawer{
+ max-height: 450px;
+ }
+ }
}
\ No newline at end of file
diff --git a/client/src/style/pages/FinancialStatements/SalesAndPurchasesSheet.scss b/client/src/style/pages/FinancialStatements/SalesAndPurchasesSheet.scss
index 48f9656b6..f3a0976a1 100644
--- a/client/src/style/pages/FinancialStatements/SalesAndPurchasesSheet.scss
+++ b/client/src/style/pages/FinancialStatements/SalesAndPurchasesSheet.scss
@@ -27,3 +27,23 @@
}
}
}
+
+.financial-statement--sales-by-items,
+.financial-statement--purchases-by-items{
+
+ .financial-header-drawer{
+ .bp3-drawer{
+ max-height: 400px;
+ }
+ }
+}
+
+
+.financial-statement--inventory-valuation{
+
+ .financial-header-drawer{
+ .bp3-drawer{
+ max-height: 350px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/utils.js b/client/src/utils.js
index e08b226e9..a6e3d07e0 100644
--- a/client/src/utils.js
+++ b/client/src/utils.js
@@ -297,6 +297,10 @@ export const saveInvoke = (func, ...rest) => {
return func && func(...rest);
};
+export const safeInvoke = (func, ...rest) => {
+ return func && func(...rest);
+};
+
export const transformToForm = (obj, emptyInitialValues) => {
return _.pickBy(
obj,
@@ -432,11 +436,10 @@ export function flatObject(obj) {
const path = []; // current path
function dig(obj) {
- if (obj !== Object(obj))
- /*is primitive, end of path*/
- return (flatObject[path.join('.')] = obj); /*<- value*/
+ if (obj !== Object(obj)) {
+ return (flatObject[path.join('.')] = obj);
+ }
- //no? so this is an object with keys. go deeper on each key down
for (let key in obj) {
path.push(key);
dig(obj[key]);
diff --git a/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts b/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
index a0e2e4c2c..99140c25a 100644
--- a/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
+++ b/server/src/api/controllers/FinancialStatements/CustomerBalanceSummary/index.ts
@@ -23,6 +23,7 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia
router.get(
'/',
this.validationSchema,
+ this.validationResult,
asyncMiddleware(this.customerBalanceSummary.bind(this))
);
return router;
@@ -34,7 +35,13 @@ export default class CustomerBalanceSummaryReportController extends BaseFinancia
get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
+
+ // As date.
query('as_date').optional().isISO8601(),
+
+ // Customers ids.
+ query('customers_ids').optional().isArray({ min: 1 }),
+ query('customers_ids.*').exists().isInt().toInt(),
];
}
diff --git a/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts b/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
index d40d9e585..78138c317 100644
--- a/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
+++ b/server/src/api/controllers/FinancialStatements/InventoryDetails/index.ts
@@ -53,8 +53,12 @@ export default class InventoryDetailsController extends BaseController {
.escape(),
query('from_date').optional(),
query('to_date').optional(),
+
query('none_zero').optional().isBoolean().toBoolean(),
query('none_transactions').optional().isBoolean().toBoolean(),
+
+ query('items_ids').optional().isArray(),
+ query('items_ids.*').optional().isInt().toInt(),
];
}
diff --git a/server/src/api/controllers/FinancialStatements/InventoryValuationSheet.ts b/server/src/api/controllers/FinancialStatements/InventoryValuationSheet.ts
index 0353870b3..266cc4e82 100644
--- a/server/src/api/controllers/FinancialStatements/InventoryValuationSheet.ts
+++ b/server/src/api/controllers/FinancialStatements/InventoryValuationSheet.ts
@@ -32,6 +32,10 @@ export default class InventoryValuationReportController extends BaseFinancialRep
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
+
+ query('items_ids').optional().isArray(),
+ query('items_ids.*').optional().isInt().toInt(),
+
query('number_format.no_cents').optional().isBoolean().toBoolean(),
query('number_format.divide_1000').optional().isBoolean().toBoolean(),
query('none_transactions').default(true).isBoolean().toBoolean(),
diff --git a/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts b/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts
index 835e6412f..7a5063dcf 100644
--- a/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts
+++ b/server/src/api/controllers/FinancialStatements/PurchasesByItem.ts
@@ -28,14 +28,20 @@ export default class PurchasesByItemReportController extends BaseFinancialReport
/**
* Validation schema.
+ * @return {ValidationChain[]}
*/
get validationSchema(): ValidationChain[] {
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
+
query('number_format.no_cents').optional().isBoolean().toBoolean(),
query('number_format.divide_1000').optional().isBoolean().toBoolean(),
query('none_transactions').default(true).isBoolean().toBoolean(),
+
+ query('items_ids').optional().isArray(),
+ query('items_ids.*').optional().isInt().toInt(),
+
query('orderBy').optional().isIn(['created_at', 'name', 'code']),
query('order').optional().isIn(['desc', 'asc']),
];
diff --git a/server/src/api/controllers/FinancialStatements/SalesByItems.ts b/server/src/api/controllers/FinancialStatements/SalesByItems.ts
index 7b9fb4602..5987d9418 100644
--- a/server/src/api/controllers/FinancialStatements/SalesByItems.ts
+++ b/server/src/api/controllers/FinancialStatements/SalesByItems.ts
@@ -33,6 +33,10 @@ export default class SalesByItemsReportController extends BaseFinancialReportCon
return [
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
+
+ query('items_ids').optional().isArray(),
+ query('items_ids.*').optional().isInt().toInt(),
+
query('number_format.no_cents').optional().isBoolean().toBoolean(),
query('number_format.divide_1000').optional().isBoolean().toBoolean(),
query('none_transactions').default(true).isBoolean().toBoolean(),
diff --git a/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts b/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
index 30ed4d41e..a484963f3 100644
--- a/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
+++ b/server/src/api/controllers/FinancialStatements/TransactionsByCustomers/index.ts
@@ -23,6 +23,7 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
router.get(
'/',
this.validationSchema,
+ this.validationResult,
asyncMiddleware(this.transactionsByCustomers.bind(this))
);
return router;
@@ -31,13 +32,18 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
/**
* Validation schema.
*/
- get validationSchema() {
+ private get validationSchema() {
return [
...this.sheetNumberFormatValidationSchema,
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
+
query('none_zero').optional().isBoolean().toBoolean(),
query('none_transactions').optional().isBoolean().toBoolean(),
+
+ // Customers ids.
+ query('customers_ids').optional().isArray({ min: 1 }),
+ query('customers_ids.*').exists().isInt().toInt(),
];
}
@@ -45,7 +51,9 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
* Transformes the statement to table rows response.
* @param {ITransactionsByCustomersStatement} statement -
*/
- transformToTableResponse({ data }: ITransactionsByCustomersStatement) {
+ private transformToTableResponse({
+ data,
+ }: ITransactionsByCustomersStatement) {
return {
table: {
rows: this.transactionsByCustomersTableRows.tableRows(data),
@@ -57,7 +65,7 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
* Transformes the statement to json response.
* @param {ITransactionsByCustomersStatement} statement -
*/
- transfromToJsonResponse({
+ private transfromToJsonResponse({
data,
columns,
}: ITransactionsByCustomersStatement) {
@@ -83,10 +91,11 @@ export default class TransactionsByCustomersReportController extends BaseFinanci
const filter = this.matchedQueryData(req);
try {
- const transactionsByCustomers = await this.transactionsByCustomersService.transactionsByCustomers(
- tenantId,
- filter
- );
+ const transactionsByCustomers =
+ await this.transactionsByCustomersService.transactionsByCustomers(
+ tenantId,
+ filter
+ );
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
diff --git a/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts b/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
index 2f24c2259..cf2240543 100644
--- a/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
+++ b/server/src/api/controllers/FinancialStatements/TransactionsByVendors/index.ts
@@ -23,6 +23,7 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
router.get(
'/',
this.validationSchema,
+ this.validationResult,
asyncMiddleware(this.transactionsByVendors.bind(this))
);
return router;
@@ -34,10 +35,16 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
get validationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
+
query('from_date').optional().isISO8601(),
query('to_date').optional().isISO8601(),
+
query('none_zero').optional().isBoolean().toBoolean(),
query('none_transactions').optional().isBoolean().toBoolean(),
+
+ // Vendors ids.
+ query('vendors_ids').optional().isArray({ min: 1 }),
+ query('vendors_ids.*').exists().isInt().toInt(),
];
}
@@ -80,10 +87,11 @@ export default class TransactionsByVendorsReportController extends BaseFinancial
const filter = this.matchedQueryData(req);
try {
- const transactionsByVendors = await this.transactionsByVendorsService.transactionsByVendors(
- tenantId,
- filter
- );
+ const transactionsByVendors =
+ await this.transactionsByVendorsService.transactionsByVendors(
+ tenantId,
+ filter
+ );
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);
diff --git a/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts b/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
index c94f77319..849a64eca 100644
--- a/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
+++ b/server/src/api/controllers/FinancialStatements/VendorBalanceSummary/index.ts
@@ -34,6 +34,10 @@ export default class VendorBalanceSummaryReportController extends BaseFinancialR
return [
...this.sheetNumberFormatValidationSchema,
query('as_date').optional().isISO8601(),
+
+ // Vendors ids.
+ query('vendors_ids').optional().isArray({ min: 1 }),
+ query('vendors_ids.*').exists().isInt().toInt(),
];
}
diff --git a/server/src/interfaces/IInventoryValuationSheet.ts b/server/src/interfaces/IInventoryValuationSheet.ts
index 8a6cf5f40..a295020ed 100644
--- a/server/src/interfaces/IInventoryValuationSheet.ts
+++ b/server/src/interfaces/IInventoryValuationSheet.ts
@@ -7,6 +7,7 @@ export interface IInventoryValuationReportQuery {
asDate: Date | string;
numberFormat: INumberFormatQuery;
noneTransactions: boolean;
+ itemsIds: number[],
};
export interface IInventoryValuationSheetMeta {
diff --git a/server/src/interfaces/InventoryDetails.ts b/server/src/interfaces/InventoryDetails.ts
index 69680f04f..270a4c254 100644
--- a/server/src/interfaces/InventoryDetails.ts
+++ b/server/src/interfaces/InventoryDetails.ts
@@ -7,6 +7,7 @@ export interface IInventoryDetailsQuery {
toDate: Date | string;
numberFormat: INumberFormatQuery;
noneTransactions: boolean;
+ itemsIds: number[]
}
export interface IInventoryDetailsNumber {
diff --git a/server/src/interfaces/SalesByItemsSheet.ts b/server/src/interfaces/SalesByItemsSheet.ts
index d90fff55e..362f4ceea 100644
--- a/server/src/interfaces/SalesByItemsSheet.ts
+++ b/server/src/interfaces/SalesByItemsSheet.ts
@@ -5,6 +5,7 @@ import {
export interface ISalesByItemsReportQuery {
fromDate: Date | string;
toDate: Date | string;
+ itemsIds: number[],
numberFormat: INumberFormatQuery;
noneTransactions: boolean;
};
diff --git a/server/src/interfaces/TransactionsByCustomers.ts b/server/src/interfaces/TransactionsByCustomers.ts
index 9ccd8de9c..fe2fbf5e2 100644
--- a/server/src/interfaces/TransactionsByCustomers.ts
+++ b/server/src/interfaces/TransactionsByCustomers.ts
@@ -18,7 +18,9 @@ export interface ITransactionsByCustomersCustomer {
}
export interface ITransactionsByCustomersFilter
- extends ITransactionsByContactsFilter {}
+ extends ITransactionsByContactsFilter {
+ customersIds: number[];
+}
export type ITransactionsByCustomersData = ITransactionsByCustomersCustomer[];
diff --git a/server/src/interfaces/TransactionsByVendors.ts b/server/src/interfaces/TransactionsByVendors.ts
index c2a4bc77a..107c7662e 100644
--- a/server/src/interfaces/TransactionsByVendors.ts
+++ b/server/src/interfaces/TransactionsByVendors.ts
@@ -18,7 +18,9 @@ export interface ITransactionsByVendorsVendor {
}
export interface ITransactionsByVendorsFilter
- extends ITransactionsByContactsFilter {}
+ extends ITransactionsByContactsFilter {
+ vendorsIds: number[];
+}
export type ITransactionsByVendorsData = ITransactionsByVendorsVendor[];
diff --git a/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts b/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
index de623f854..21b60064b 100644
--- a/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
+++ b/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts
@@ -83,7 +83,7 @@ export default class ARAgingSummaryService {
});
// Retrieve all customers from the storage.
const customers =
- filter.customersIds.length > 0
+ (filter.customersIds.length > 0)
? await customerRepository.findWhereIn('id', filter.customersIds)
: await customerRepository.all();
diff --git a/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsRepository.ts b/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsRepository.ts
index 8cc98ca0a..538febe9b 100644
--- a/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsRepository.ts
+++ b/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsRepository.ts
@@ -1,5 +1,6 @@
import { Inject } from 'typedi';
import { raw } from 'objection';
+import { isEmpty } from 'lodash';
import moment from 'moment';
import {
IItem,
@@ -17,10 +18,16 @@ export default class InventoryDetailsRepository {
* @param {number} tenantId -
* @returns {Promise}
*/
- public getInventoryItems(tenantId: number): Promise {
+ public getInventoryItems(tenantId: number, itemsIds?: number[]): Promise {
const { Item } = this.tenancy.models(tenantId);
- return Item.query().where('type', 'inventory');
+ return Item.query().onBuild((q) => {
+ q.where('type', 'inventory');
+
+ if (!isEmpty(itemsIds)) {
+ q.whereIn('id', itemsIds);
+ }
+ })
}
/**
diff --git a/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts b/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
index c1628042e..93e8045a0 100644
--- a/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
+++ b/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts
@@ -31,6 +31,7 @@ export default class InventoryDetailsService extends FinancialSheet {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
+ itemsIds: [],
numberFormat: {
precision: 2,
divideOn1000: false,
@@ -91,8 +92,10 @@ export default class InventoryDetailsService extends FinancialSheet {
...query,
};
// Retrieves the items.
- const items = await this.reportRepo.getInventoryItems(tenantId);
-
+ const items = await this.reportRepo.getInventoryItems(
+ tenantId,
+ filter.itemsIds
+ );
// Opening balance transactions.
const openingBalanceTransactions =
await this.reportRepo.openingBalanceTransactions(tenantId, filter);
diff --git a/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts b/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts
index fe818b419..f34d12eb6 100644
--- a/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts
+++ b/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts
@@ -26,6 +26,7 @@ export default class InventoryValuationSheetService {
get defaultQuery(): IInventoryValuationReportQuery {
return {
asDate: moment().endOf('year').format('YYYY-MM-DD'),
+ itemsIds: [],
numberFormat: {
precision: 2,
divideOn1000: false,
@@ -75,9 +76,6 @@ export default class InventoryValuationSheetService {
) {
const { Item, InventoryCostLotTracker } = this.tenancy.models(tenantId);
- const inventoryItems = await Item.query().where('type', 'inventory');
- const inventoryItemsIds = inventoryItems.map((item) => item.id);
-
// Settings tenant service.
const settings = this.tenancy.settings(tenantId);
const baseCurrency = settings.get({
@@ -89,6 +87,15 @@ export default class InventoryValuationSheetService {
...this.defaultQuery,
...query,
};
+ const inventoryItems = await Item.query().onBuild(q => {
+ q.where('type', 'inventory');
+
+ if (filter.itemsIds.length > 0) {
+ q.whereIn('id', filter.itemsIds);
+ }
+ });
+ const inventoryItemsIds = inventoryItems.map((item) => item.id);
+
const commonQuery = (builder) => {
builder.whereIn('item_id', inventoryItemsIds);
builder.sum('rate as rate');
diff --git a/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts b/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts
index aa52120c1..80455f585 100644
--- a/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts
+++ b/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts
@@ -24,6 +24,7 @@ export default class InventoryValuationReportService {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
+ itemsIds: [],
numberFormat: {
precision: 2,
divideOn1000: false,
@@ -91,7 +92,13 @@ export default class InventoryValuationReportService {
filter,
tenantId,
});
- const inventoryItems = await Item.query().where('type', 'inventory');
+ const inventoryItems = await Item.query().onBuild(q => {
+ q.where('type', 'inventory');
+
+ if (filter.itemsIds.length > 0) {
+ q.whereIn('id', filter.itemsIds);
+ }
+ });
const inventoryItemsIds = inventoryItems.map((item) => item.id);
// Calculates the total inventory total quantity and rate `IN` transactions.
diff --git a/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts b/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
index bbcc05100..093027fa2 100644
--- a/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
+++ b/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts
@@ -24,6 +24,7 @@ export default class SalesByItemsReportService {
return {
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
toDate: moment().endOf('year').format('YYYY-MM-DD'),
+ itemsIds: [],
numberFormat: {
precision: 2,
divideOn1000: false,
@@ -91,7 +92,14 @@ export default class SalesByItemsReportService {
filter,
tenantId,
});
- const inventoryItems = await Item.query().where('type', 'inventory');
+ // Inventory items for sales report.
+ const inventoryItems = await Item.query().onBuild((q) => {
+ q.where('type', 'inventory');
+
+ if (filter.itemsIds.length > 0) {
+ q.whereIn('id', filter.itemsIds);
+ }
+ });
const inventoryItemsIds = inventoryItems.map((item) => item.id);
// Calculates the total inventory total quantity and rate `IN` transactions.
diff --git a/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts b/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
index 603c339db..e3201660a 100644
--- a/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
+++ b/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersRepository.ts
@@ -1,4 +1,4 @@
-import { map } from 'lodash';
+import { isEmpty, map } from 'lodash';
import { IAccount, IAccountTransaction } from 'interfaces';
import { ACCOUNT_TYPE } from 'data/AccountTypes';
import HasTenancyService from 'services/Tenancy/TenancyService';
@@ -13,10 +13,16 @@ export default class TransactionsByCustomersRepository {
* @param {number} tenantId
* @returns {Promise}
*/
- public async getCustomers(tenantId: number) {
+ public async getCustomers(tenantId: number, customersIds?: number[]) {
const { Customer } = this.tenancy.models(tenantId);
- return Customer.query().orderBy('displayName');
+ return Customer.query().onBuild((q) => {
+ q.orderBy('displayName');
+
+ if (!isEmpty(customersIds)) {
+ q.whereIn('id', customersIds);
+ }
+ });
}
/**
diff --git a/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts b/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
index 0de5a070c..548ee7645 100644
--- a/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
+++ b/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts
@@ -44,6 +44,8 @@ export default class TransactionsByCustomersService
},
noneZero: false,
noneTransactions: false,
+
+ customersIds: [],
};
}
@@ -125,7 +127,7 @@ export default class TransactionsByCustomersService
const accountsGraph = await accountRepository.getDependencyGraph();
// Retrieve the report customers.
- const customers = await this.reportRepository.getCustomers(tenantId);
+ const customers = await this.reportRepository.getCustomers(tenantId, filter.customersIds);
const openingBalanceDate = moment(filter.fromDate)
.subtract(1, 'days')
diff --git a/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorRepository.ts b/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorRepository.ts
index c67b09741..daa9f3424 100644
--- a/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorRepository.ts
+++ b/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorRepository.ts
@@ -1,5 +1,5 @@
import { Inject, Service } from 'typedi';
-import { map } from 'lodash';
+import { isEmpty, map } from 'lodash';
import { IVendor, IAccount, IAccountTransaction } from 'interfaces';
import HasTenancyService from 'services/Tenancy/TenancyService';
import { ACCOUNT_TYPE } from 'data/AccountTypes';
@@ -14,10 +14,19 @@ export default class TransactionsByVendorRepository {
* @param {number} tenantId
* @returns {Promise}
*/
- public getVendors(tenantId: number): Promise {
+ public getVendors(
+ tenantId: number,
+ vendorsIds?: number[]
+ ): Promise {
const { Vendor } = this.tenancy.models(tenantId);
- return Vendor.query().orderBy('displayName');
+ return Vendor.query().onBuild((q) => {
+ q.orderBy('displayName');
+
+ if (!isEmpty(vendorsIds)) {
+ q.whereIn('id', vendorsIds);
+ }
+ });
}
/**
@@ -67,7 +76,7 @@ export default class TransactionsByVendorRepository {
* @param {Date|string} openingDate
* @param {number[]} customersIds
*/
- public async getVendorsPeriodTransactions(
+ public async getVendorsPeriodTransactions(
tenantId: number,
fromDate: Date,
toDate: Date
diff --git a/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts b/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts
index 354e5fa45..db934fbd3 100644
--- a/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts
+++ b/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts
@@ -45,6 +45,8 @@ export default class TransactionsByVendorsService
},
noneZero: false,
noneTransactions: false,
+
+ vendorsIds: [],
};
}
@@ -139,12 +141,13 @@ export default class TransactionsByVendorsService
group: 'organization',
key: 'base_currency',
});
-
const filter = { ...this.defaultQuery, ...query };
// Retrieve the report vendors.
- const vendors = await this.reportRepository.getVendors(tenantId);
-
+ const vendors = await this.reportRepository.getVendors(
+ tenantId,
+ filter.vendorsIds
+ );
// Retrieve the accounts graph.
const accountsGraph = await accountRepository.getDependencyGraph();