mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
Merge branch 'master' of https://github.com/abouolia/Bigcapital
This commit is contained in:
@@ -1,27 +1,32 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { get } from 'lodash';
|
||||||
import { Classes, Checkbox, FormGroup, Intent } from '@blueprintjs/core';
|
import { Classes, Checkbox, FormGroup, Intent } from '@blueprintjs/core';
|
||||||
|
|
||||||
const CheckboxEditableCell = ({
|
const CheckboxEditableCell = ({
|
||||||
row: { index },
|
row: { index, original },
|
||||||
column: { id },
|
column: { id, disabledAccessor, checkboxProps },
|
||||||
cell: { value: initialValue },
|
cell: { value: initialValue },
|
||||||
payload,
|
payload,
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = React.useState(initialValue);
|
const [value, setValue] = React.useState(initialValue);
|
||||||
|
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
setValue(e.target.checked);
|
const newValue = e.target.checked;
|
||||||
};
|
|
||||||
const onBlur = () => {
|
setValue(newValue);
|
||||||
payload.updateData(index, id, value);
|
payload.updateData(index, id, newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setValue(initialValue);
|
setValue(initialValue);
|
||||||
}, [initialValue]);
|
}, [initialValue]);
|
||||||
|
|
||||||
const error = payload.errors?.[index]?.[id];
|
const error = payload.errors?.[index]?.[id];
|
||||||
|
|
||||||
|
// Detarmines whether the checkbox is disabled.
|
||||||
|
const disabled = disabledAccessor ? get(original, disabledAccessor) : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
intent={error ? Intent.DANGER : null}
|
intent={error ? Intent.DANGER : null}
|
||||||
@@ -31,9 +36,10 @@ const CheckboxEditableCell = ({
|
|||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
checked={initialValue}
|
checked={initialValue}
|
||||||
onBlur={onBlur}
|
disabled={disabled}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
className="ml2"
|
className="ml2"
|
||||||
|
{...checkboxProps}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
updateMinEntriesLines,
|
updateMinEntriesLines,
|
||||||
updateRemoveLineByIndex,
|
updateRemoveLineByIndex,
|
||||||
updateAutoAddNewLine,
|
updateAutoAddNewLine,
|
||||||
updateTableRow,
|
updateTableCell,
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
import { useMakeJournalFormContext } from './MakeJournalProvider';
|
||||||
import { useJournalTableEntriesColumns } from './components';
|
import { useJournalTableEntriesColumns } from './components';
|
||||||
@@ -38,7 +38,7 @@ export default function MakeJournalEntriesTable({
|
|||||||
// Update items entries total.
|
// Update items entries total.
|
||||||
updateAdjustEntries(rowIndex, columnId, value),
|
updateAdjustEntries(rowIndex, columnId, value),
|
||||||
// Update entry of the given row index and column id.
|
// Update entry of the given row index and column id.
|
||||||
updateTableRow(rowIndex, columnId, value),
|
updateTableCell(rowIndex, columnId, value),
|
||||||
)(entries);
|
)(entries);
|
||||||
|
|
||||||
saveInvoke(onChange, newRows);
|
saveInvoke(onChange, newRows);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import moment from 'moment';
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import {
|
import {
|
||||||
transactionNumber,
|
transactionNumber,
|
||||||
updateTableRow,
|
updateTableCell,
|
||||||
repeatValue,
|
repeatValue,
|
||||||
transformToForm,
|
transformToForm,
|
||||||
defaultFastFieldShouldUpdate,
|
defaultFastFieldShouldUpdate,
|
||||||
@@ -100,10 +100,10 @@ export const updateAdjustEntries = (rowIndex, columnId, value) => (rows) => {
|
|||||||
const adjustment = adjustmentEntries(rows);
|
const adjustment = adjustmentEntries(rows);
|
||||||
|
|
||||||
if (adjustment.credit) {
|
if (adjustment.credit) {
|
||||||
newRows = updateTableRow(rowIndex, 'credit', adjustment.credit)(newRows);
|
newRows = updateTableCell(rowIndex, 'credit', adjustment.credit)(newRows);
|
||||||
}
|
}
|
||||||
if (adjustment.debit) {
|
if (adjustment.debit) {
|
||||||
newRows = updateTableRow(rowIndex, 'debit', adjustment.debit)(newRows);
|
newRows = updateTableCell(rowIndex, 'debit', adjustment.debit)(newRows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newRows;
|
return newRows;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { MoneyFieldCell, DataTableEditable } from 'components';
|
import { MoneyFieldCell, DataTableEditable } from 'components';
|
||||||
import { compose, updateTableRow } from 'utils';
|
import { compose, updateTableCell } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate landed cost entries table.
|
* Allocate landed cost entries table.
|
||||||
@@ -51,7 +51,7 @@ export default function AllocateLandedCostEntriesTable({
|
|||||||
// Handle update data.
|
// Handle update data.
|
||||||
const handleUpdateData = React.useCallback(
|
const handleUpdateData = React.useCallback(
|
||||||
(rowIndex, columnId, value) => {
|
(rowIndex, columnId, value) => {
|
||||||
const newRows = compose(updateTableRow(rowIndex, columnId, value))(
|
const newRows = compose(updateTableCell(rowIndex, columnId, value))(
|
||||||
entries,
|
entries,
|
||||||
);
|
);
|
||||||
onUpdateData(newRows);
|
onUpdateData(newRows);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React, { useEffect, useCallback } from 'react';
|
import React, { useEffect, useCallback } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useItem } from 'hooks/query';
|
|
||||||
|
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
import { DataTableEditable } from 'components';
|
import { DataTableEditable } from 'components';
|
||||||
@@ -9,12 +8,13 @@ import { useEditableItemsEntriesColumns } from './components';
|
|||||||
import {
|
import {
|
||||||
saveInvoke,
|
saveInvoke,
|
||||||
compose,
|
compose,
|
||||||
updateTableRow,
|
updateTableCell,
|
||||||
updateMinEntriesLines,
|
updateMinEntriesLines,
|
||||||
updateAutoAddNewLine,
|
updateAutoAddNewLine,
|
||||||
updateRemoveLineByIndex,
|
updateRemoveLineByIndex,
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
import { updateItemsEntriesTotal, ITEM_TYPE } from './utils';
|
import { updateItemsEntriesTotal, useFetchItemRow } from './utils';
|
||||||
|
import { updateTableRow } from '../../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Items entries table.
|
* Items entries table.
|
||||||
@@ -30,62 +30,9 @@ function ItemsEntriesTable({
|
|||||||
linesNumber,
|
linesNumber,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
itemType, // sellable or purchasable
|
itemType, // sellable or purchasable
|
||||||
landedCost = false
|
landedCost = false,
|
||||||
}) {
|
}) {
|
||||||
const [rows, setRows] = React.useState(initialEntries);
|
const [rows, setRows] = React.useState(initialEntries);
|
||||||
const [rowItem, setRowItem] = React.useState(null);
|
|
||||||
const [cellsLoading, setCellsLoading] = React.useState(null);
|
|
||||||
|
|
||||||
// Fetches the item details.
|
|
||||||
const {
|
|
||||||
data: item,
|
|
||||||
isFetching: isItemFetching,
|
|
||||||
isSuccess: isItemSuccess,
|
|
||||||
} = useItem(rowItem && rowItem.itemId, {
|
|
||||||
enabled: !!(rowItem && rowItem.itemId),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Once the item start loading give the table cells loading state.
|
|
||||||
useEffect(() => {
|
|
||||||
if (rowItem && isItemFetching) {
|
|
||||||
setCellsLoading([
|
|
||||||
[rowItem.rowIndex, 'rate'],
|
|
||||||
[rowItem.rowIndex, 'description'],
|
|
||||||
[rowItem.rowIndex, 'quantity'],
|
|
||||||
[rowItem.rowIndex, 'discount'],
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
setCellsLoading(null);
|
|
||||||
}
|
|
||||||
}, [isItemFetching, setCellsLoading, rowItem]);
|
|
||||||
|
|
||||||
// Once the item selected and fetched set the initial details to the table.
|
|
||||||
useEffect(() => {
|
|
||||||
if (isItemSuccess && item && rowItem) {
|
|
||||||
const { rowIndex } = rowItem;
|
|
||||||
const price =
|
|
||||||
itemType === ITEM_TYPE.PURCHASABLE
|
|
||||||
? item.cost_price
|
|
||||||
: item.sell_price;
|
|
||||||
|
|
||||||
const description =
|
|
||||||
itemType === ITEM_TYPE.PURCHASABLE
|
|
||||||
? item.cost_description
|
|
||||||
: item.sell_description;
|
|
||||||
|
|
||||||
// Update the rate, description and quantity data of the row.
|
|
||||||
const newRows = compose(
|
|
||||||
updateItemsEntriesTotal,
|
|
||||||
updateTableRow(rowIndex, 'rate', price),
|
|
||||||
updateTableRow(rowIndex, 'description', description),
|
|
||||||
updateTableRow(rowIndex, 'quantity', 1),
|
|
||||||
)(rows);
|
|
||||||
|
|
||||||
setRows(newRows);
|
|
||||||
setRowItem(null);
|
|
||||||
saveInvoke(onUpdateData, newRows);
|
|
||||||
}
|
|
||||||
}, [item, rowItem, rows, itemType, onUpdateData, isItemSuccess]);
|
|
||||||
|
|
||||||
// Allows to observes `entries` to make table rows outside controlled.
|
// Allows to observes `entries` to make table rows outside controlled.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -97,22 +44,38 @@ function ItemsEntriesTable({
|
|||||||
// Editiable items entries columns.
|
// Editiable items entries columns.
|
||||||
const columns = useEditableItemsEntriesColumns({ landedCost });
|
const columns = useEditableItemsEntriesColumns({ landedCost });
|
||||||
|
|
||||||
// Handles the editor data update.
|
// Handle the fetch item row details.
|
||||||
const handleUpdateData = useCallback(
|
const { setItemRow, cellsLoading, isItemFetching } = useFetchItemRow({
|
||||||
(rowIndex, columnId, value) => {
|
landedCost,
|
||||||
if (columnId === 'item_id') {
|
itemType,
|
||||||
setRowItem({ rowIndex, columnId, itemId: value });
|
notifyNewRow: (newRow, rowIndex) => {
|
||||||
}
|
// Update the rate, description and quantity data of the row.
|
||||||
const newRows = compose(
|
const newRows = compose(
|
||||||
updateAutoAddNewLine(defaultEntry, ['item_id']),
|
|
||||||
updateItemsEntriesTotal,
|
updateItemsEntriesTotal,
|
||||||
updateTableRow(rowIndex, columnId, value),
|
updateTableRow(rowIndex, newRow),
|
||||||
)(rows);
|
)(rows);
|
||||||
|
|
||||||
setRows(newRows);
|
setRows(newRows);
|
||||||
onUpdateData(newRows);
|
onUpdateData(newRows);
|
||||||
},
|
},
|
||||||
[rows, defaultEntry, onUpdateData],
|
});
|
||||||
|
|
||||||
|
// Handles the editor data update.
|
||||||
|
const handleUpdateData = useCallback(
|
||||||
|
(rowIndex, columnId, value) => {
|
||||||
|
if (columnId === 'item_id') {
|
||||||
|
setItemRow({ rowIndex, columnId, itemId: value });
|
||||||
|
}
|
||||||
|
const newRows = compose(
|
||||||
|
updateAutoAddNewLine(defaultEntry, ['item_id']),
|
||||||
|
updateItemsEntriesTotal,
|
||||||
|
updateTableCell(rowIndex, columnId, value),
|
||||||
|
)(rows);
|
||||||
|
|
||||||
|
setRows(newRows);
|
||||||
|
onUpdateData(newRows);
|
||||||
|
},
|
||||||
|
[rows, defaultEntry, onUpdateData, setItemRow],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle table rows removing by index.
|
// Handle table rows removing by index.
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ export function useEditableItemsEntriesColumns({ landedCost }) {
|
|||||||
accessor: 'landed_cost',
|
accessor: 'landed_cost',
|
||||||
Cell: CheckBoxFieldCell,
|
Cell: CheckBoxFieldCell,
|
||||||
width: 100,
|
width: 100,
|
||||||
|
disabledAccessor: 'landed_cost_disabled',
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
className: 'landed-cost',
|
className: 'landed-cost',
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import * as R from 'ramda';
|
||||||
import { sumBy, isEmpty, last } from 'lodash';
|
import { sumBy, isEmpty, last } from 'lodash';
|
||||||
import * as R from 'ramda';
|
|
||||||
import { toSafeNumber } from 'utils';
|
import { useItem } from 'hooks/query';
|
||||||
|
import { toSafeNumber, saveInvoke } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve item entry total from the given rate, quantity and discount.
|
* Retrieve item entry total from the given rate, quantity and discount.
|
||||||
@@ -53,3 +56,78 @@ export const ensureEntriesHaveEmptyLine = R.curry((defaultEntry, entries) => {
|
|||||||
}
|
}
|
||||||
return entries;
|
return entries;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const isLandedCostDisabled = (item) =>
|
||||||
|
['service', 'non-inventory'].indexOf(item.type) !== -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle fetch item row details and retrieves the new table row.
|
||||||
|
*/
|
||||||
|
export function useFetchItemRow({ landedCost, itemType, notifyNewRow }) {
|
||||||
|
const [itemRow, setItemRow] = React.useState(null);
|
||||||
|
const [cellsLoading, setCellsLoading] = React.useState(null);
|
||||||
|
|
||||||
|
// Fetches the item details.
|
||||||
|
const {
|
||||||
|
data: item,
|
||||||
|
isFetching: isItemFetching,
|
||||||
|
isSuccess: isItemSuccess,
|
||||||
|
} = useItem(itemRow && itemRow.itemId, {
|
||||||
|
enabled: !!(itemRow && itemRow.itemId),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Once the item start loading give the table cells loading state.
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (itemRow && isItemFetching) {
|
||||||
|
setCellsLoading([
|
||||||
|
[itemRow.rowIndex, 'rate'],
|
||||||
|
[itemRow.rowIndex, 'description'],
|
||||||
|
[itemRow.rowIndex, 'quantity'],
|
||||||
|
[itemRow.rowIndex, 'discount'],
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setCellsLoading(null);
|
||||||
|
}
|
||||||
|
}, [isItemFetching, setCellsLoading, itemRow]);
|
||||||
|
|
||||||
|
// Once the item selected and fetched set the initial details to the table.
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isItemSuccess && item && itemRow) {
|
||||||
|
const { rowIndex } = itemRow;
|
||||||
|
const price =
|
||||||
|
itemType === ITEM_TYPE.PURCHASABLE ? item.cost_price : item.sell_price;
|
||||||
|
|
||||||
|
const description =
|
||||||
|
itemType === ITEM_TYPE.PURCHASABLE
|
||||||
|
? item.cost_description
|
||||||
|
: item.sell_description;
|
||||||
|
|
||||||
|
// Detarmines whether the landed cost checkbox should be disabled.
|
||||||
|
const landedCostDisabled = isLandedCostDisabled(item);
|
||||||
|
|
||||||
|
// The new row.
|
||||||
|
const newRow = {
|
||||||
|
rate: price,
|
||||||
|
description,
|
||||||
|
quantity: 1,
|
||||||
|
...(landedCost
|
||||||
|
? {
|
||||||
|
landed_cost: false,
|
||||||
|
landed_cost_disabled: landedCostDisabled,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
setItemRow(null);
|
||||||
|
saveInvoke(notifyNewRow, newRow, rowIndex);
|
||||||
|
}
|
||||||
|
}, [item, itemRow, itemType, isItemSuccess, landedCost, notifyNewRow]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isItemFetching,
|
||||||
|
isItemSuccess,
|
||||||
|
item,
|
||||||
|
setItemRow,
|
||||||
|
itemRow,
|
||||||
|
cellsLoading,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useExpenseFormTableColumns } from './components';
|
|||||||
import {
|
import {
|
||||||
saveInvoke,
|
saveInvoke,
|
||||||
compose,
|
compose,
|
||||||
updateTableRow,
|
updateTableCell,
|
||||||
updateMinEntriesLines,
|
updateMinEntriesLines,
|
||||||
updateAutoAddNewLine,
|
updateAutoAddNewLine,
|
||||||
updateRemoveLineByIndex,
|
updateRemoveLineByIndex,
|
||||||
@@ -38,7 +38,7 @@ export default function ExpenseFormEntriesTable({
|
|||||||
// Update auto-adding new line.
|
// Update auto-adding new line.
|
||||||
updateAutoAddNewLine(defaultEntry, ['expense_account_id']),
|
updateAutoAddNewLine(defaultEntry, ['expense_account_id']),
|
||||||
// Update the row value of the given row index and column id.
|
// Update the row value of the given row index and column id.
|
||||||
updateTableRow(rowIndex, columnId, value),
|
updateTableCell(rowIndex, columnId, value),
|
||||||
)(entries);
|
)(entries);
|
||||||
|
|
||||||
saveInvoke(onChange, newRows);
|
saveInvoke(onChange, newRows);
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import { dateRangeOptions } from 'containers/FinancialStatements/common';
|
|||||||
* Financial statement - Date range select.
|
* Financial statement - Date range select.
|
||||||
*/
|
*/
|
||||||
export default function FinancialStatementDateRange() {
|
export default function FinancialStatementDateRange() {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row>
|
<Row>
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ export const useItemFormInitialValues = (item) => {
|
|||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
...defaultInitialValues,
|
...defaultInitialValues,
|
||||||
cost_account_id: defaultTo(itemsSettings.preferredCostAccount, ''),
|
cost_account_id: defaultTo(itemsSettings?.preferredCostAccount, ''),
|
||||||
sell_account_id: defaultTo(itemsSettings.preferredSellAccount, ''),
|
sell_account_id: defaultTo(itemsSettings?.preferredSellAccount, ''),
|
||||||
inventory_account_id: defaultTo(
|
inventory_account_id: defaultTo(
|
||||||
itemsSettings.preferredInventoryAccount,
|
itemsSettings?.preferredInventoryAccount,
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import classNames from 'classnames';
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { isEmpty, omit } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { CLASSES } from 'common/classes';
|
import { CLASSES } from 'common/classes';
|
||||||
|
|
||||||
import { EditBillFormSchema, CreateBillFormSchema } from './BillForm.schema';
|
import { EditBillFormSchema, CreateBillFormSchema } from './BillForm.schema';
|
||||||
@@ -18,8 +18,12 @@ import { AppToaster } from 'components';
|
|||||||
|
|
||||||
import { ERROR } from 'common/errors';
|
import { ERROR } from 'common/errors';
|
||||||
import { useBillFormContext } from './BillFormProvider';
|
import { useBillFormContext } from './BillFormProvider';
|
||||||
import { compose, orderingLinesIndexes, safeSumBy } from 'utils';
|
import { compose, safeSumBy } from 'utils';
|
||||||
import { defaultBill, transformToEditForm } from './utils';
|
import {
|
||||||
|
defaultBill,
|
||||||
|
transformToEditForm,
|
||||||
|
transformEntriesToSubmit,
|
||||||
|
} from './utils';
|
||||||
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
import withCurrentOrganization from 'containers/Organization/withCurrentOrganization';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +85,7 @@ function BillForm({
|
|||||||
const form = {
|
const form = {
|
||||||
...values,
|
...values,
|
||||||
open: submitPayload.status,
|
open: submitPayload.status,
|
||||||
entries: R.compose(orderingLinesIndexes)(entries),
|
entries: transformEntriesToSubmit(entries),
|
||||||
};
|
};
|
||||||
// Handle the request success.
|
// Handle the request success.
|
||||||
const onSuccess = (response) => {
|
const onSuccess = (response) => {
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ import {
|
|||||||
|
|
||||||
const BillFormContext = createContext();
|
const BillFormContext = createContext();
|
||||||
|
|
||||||
|
// Filter all purchasable items only.
|
||||||
|
const stringifiedFilterRoles = JSON.stringify([
|
||||||
|
{ index: 1, fieldKey: 'purchasable', value: true, condition: '&&', comparator: 'equals' },
|
||||||
|
{ index: 2, fieldKey: 'active', value: true, condition: '&&', comparator: 'equals' },
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bill form provider.
|
* Bill form provider.
|
||||||
*/
|
*/
|
||||||
@@ -25,16 +31,6 @@ function BillFormProvider({ billId, ...props }) {
|
|||||||
isLoading: isVendorsLoading,
|
isLoading: isVendorsLoading,
|
||||||
} = useVendors({ page_size: 10000 });
|
} = useVendors({ page_size: 10000 });
|
||||||
|
|
||||||
// Filter all purchasable items only.
|
|
||||||
const stringifiedFilterRoles = React.useMemo(
|
|
||||||
() =>
|
|
||||||
JSON.stringify([
|
|
||||||
{ index: 1, fieldKey: 'purchasable', value: true, condition: '&&', comparator: 'equals' },
|
|
||||||
{ index: 2, fieldKey: 'active', value: true, condition: '&&', comparator: 'equals' },
|
|
||||||
]),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle fetch Items data table or list
|
// Handle fetch Items data table or list
|
||||||
const {
|
const {
|
||||||
data: { items },
|
data: { items },
|
||||||
|
|||||||
@@ -7,14 +7,17 @@ import {
|
|||||||
defaultFastFieldShouldUpdate,
|
defaultFastFieldShouldUpdate,
|
||||||
transformToForm,
|
transformToForm,
|
||||||
repeatValue,
|
repeatValue,
|
||||||
|
orderingLinesIndexes,
|
||||||
} from 'utils';
|
} from 'utils';
|
||||||
import {
|
import {
|
||||||
updateItemsEntriesTotal,
|
updateItemsEntriesTotal,
|
||||||
ensureEntriesHaveEmptyLine,
|
ensureEntriesHaveEmptyLine,
|
||||||
} from 'containers/Entries/utils';
|
} from 'containers/Entries/utils';
|
||||||
|
import { isLandedCostDisabled } from '../../../Entries/utils';
|
||||||
|
|
||||||
export const MIN_LINES_NUMBER = 4;
|
export const MIN_LINES_NUMBER = 4;
|
||||||
|
|
||||||
|
// Default bill entry.
|
||||||
export const defaultBillEntry = {
|
export const defaultBillEntry = {
|
||||||
index: 0,
|
index: 0,
|
||||||
item_id: '',
|
item_id: '',
|
||||||
@@ -26,6 +29,7 @@ export const defaultBillEntry = {
|
|||||||
landed_cost: false,
|
landed_cost: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Default bill.
|
||||||
export const defaultBill = {
|
export const defaultBill = {
|
||||||
vendor_id: '',
|
vendor_id: '',
|
||||||
bill_number: '',
|
bill_number: '',
|
||||||
@@ -37,10 +41,14 @@ export const defaultBill = {
|
|||||||
entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)],
|
entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes the bill to initial values of edit form.
|
||||||
|
*/
|
||||||
export const transformToEditForm = (bill) => {
|
export const transformToEditForm = (bill) => {
|
||||||
const initialEntries = [
|
const initialEntries = [
|
||||||
...bill.entries.map((entry) => ({
|
...bill.entries.map((entry) => ({
|
||||||
...transformToForm(entry, defaultBillEntry),
|
...transformToForm(entry, defaultBillEntry),
|
||||||
|
landed_cost_disabled: isLandedCostDisabled(entry.item),
|
||||||
})),
|
})),
|
||||||
...repeatValue(
|
...repeatValue(
|
||||||
defaultBillEntry,
|
defaultBillEntry,
|
||||||
@@ -58,7 +66,18 @@ export const transformToEditForm = (bill) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// handle delete errors.
|
/**
|
||||||
|
* Transformes bill entries to submit request.
|
||||||
|
*/
|
||||||
|
export const transformEntriesToSubmit = (entries) => {
|
||||||
|
const transformBillEntry = R.curry(transformToForm)(R.__, defaultBillEntry);
|
||||||
|
|
||||||
|
return R.compose(orderingLinesIndexes, R.map(transformBillEntry))(entries);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle delete errors.
|
||||||
|
*/
|
||||||
export const handleDeleteErrors = (errors) => {
|
export const handleDeleteErrors = (errors) => {
|
||||||
if (
|
if (
|
||||||
errors.find((error) => error.type === 'BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES')
|
errors.find((error) => error.type === 'BILL_HAS_ASSOCIATED_PAYMENT_ENTRIES')
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { DataTableEditable } from 'components';
|
|||||||
import { usePaymentMadeEntriesTableColumns } from './components';
|
import { usePaymentMadeEntriesTableColumns } from './components';
|
||||||
|
|
||||||
import { usePaymentMadeInnerContext } from './PaymentMadeInnerProvider';
|
import { usePaymentMadeInnerContext } from './PaymentMadeInnerProvider';
|
||||||
import { compose, updateTableRow } from 'utils';
|
import { compose, updateTableCell } from 'utils';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +33,7 @@ export default function PaymentMadeEntriesTable({
|
|||||||
// Handle update data.
|
// Handle update data.
|
||||||
const handleUpdateData = useCallback(
|
const handleUpdateData = useCallback(
|
||||||
(rowIndex, columnId, value) => {
|
(rowIndex, columnId, value) => {
|
||||||
const newRows = compose(updateTableRow(rowIndex, columnId, value))(
|
const newRows = compose(updateTableCell(rowIndex, columnId, value))(
|
||||||
entries,
|
entries,
|
||||||
);
|
);
|
||||||
onUpdateData(newRows);
|
onUpdateData(newRows);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CLASSES } from 'common/classes';
|
|||||||
import { usePaymentReceiveInnerContext } from './PaymentReceiveInnerProvider';
|
import { usePaymentReceiveInnerContext } from './PaymentReceiveInnerProvider';
|
||||||
import { DataTableEditable } from 'components';
|
import { DataTableEditable } from 'components';
|
||||||
import { usePaymentReceiveEntriesColumns } from './components';
|
import { usePaymentReceiveEntriesColumns } from './components';
|
||||||
import { compose, updateTableRow } from 'utils';
|
import { compose, updateTableCell } from 'utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment receive items table.
|
* Payment receive items table.
|
||||||
@@ -39,7 +39,7 @@ export default function PaymentReceiveItemsTable({
|
|||||||
// Handle update data.
|
// Handle update data.
|
||||||
const handleUpdateData = useCallback(
|
const handleUpdateData = useCallback(
|
||||||
(rowIndex, columnId, value) => {
|
(rowIndex, columnId, value) => {
|
||||||
const newRows = compose(updateTableRow(rowIndex, columnId, value))(
|
const newRows = compose(updateTableCell(rowIndex, columnId, value))(
|
||||||
entries,
|
entries,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
.bp3-control-indicator{
|
.bp3-control-indicator{
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
border-color: #e0e0e0;
|
border-color: #dbdbdb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -643,7 +643,7 @@ export const updateRemoveLineByIndex = (rowIndex) => (entries) => {
|
|||||||
return entries.filter((row, index) => index !== removeIndex);
|
return entries.filter((row, index) => index !== removeIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateTableRow = (rowIndex, columnId, value) => (old) => {
|
export const updateTableCell = (rowIndex, columnId, value) => (old) => {
|
||||||
return old.map((row, index) => {
|
return old.map((row, index) => {
|
||||||
if (index === rowIndex) {
|
if (index === rowIndex) {
|
||||||
return {
|
return {
|
||||||
@@ -654,6 +654,18 @@ export const updateTableRow = (rowIndex, columnId, value) => (old) => {
|
|||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateTableRow = (rowIndex, value) => (old) => {
|
||||||
|
return old.map((row, index) => {
|
||||||
|
if (index === rowIndex) {
|
||||||
|
return {
|
||||||
|
...old[rowIndex],
|
||||||
|
...value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
};
|
||||||
export const transformGeneralSettings = (data) => {
|
export const transformGeneralSettings = (data) => {
|
||||||
return _.mapKeys(data, (value, key) => _.snakeCase(key));
|
return _.mapKeys(data, (value, key) => _.snakeCase(key));
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user