fix(WarehouseTransfer).

This commit is contained in:
a.bouhuolia
2022-03-20 16:43:49 +02:00
parent 89b28903fa
commit 29fbcf1f1c
17 changed files with 129 additions and 193 deletions

View File

@@ -1,7 +1,9 @@
import { useFormikContext } from 'formik';
import { useDeepCompareEffect } from 'hooks/utils';
export function FormikObserver({ onChange, values }) {
export function FormikObserver({ onChange }) {
const { values } = useFormikContext();
useDeepCompareEffect(() => {
onChange(values);
}, [values]);

View File

@@ -63,7 +63,6 @@ export default function MakeJournalEntriesTable({
data={entries}
sticky={true}
totalRow={true}
footer={true}
payload={{
accounts,
errors: error,

View File

@@ -1,8 +1,7 @@
import React from 'react';
import { Intent, Position, Button, Tooltip } from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { Icon, Money, Hint } from 'components';
import intl from 'react-intl-universal';
import { Icon, Hint, FormattedMessage as T } from 'components';
import {
AccountsListFieldCell,
MoneyFieldCell,
@@ -10,7 +9,6 @@ import {
ContactsListFieldCell,
BranchesListFieldCell,
} from 'components/DataTableCells';
import { safeSumBy } from 'utils';
import { useFeatureCan } from 'hooks/state';
import { Features } from 'common';
@@ -43,38 +41,6 @@ export function DebitHeaderCell({ payload: { currencyCode } }) {
return intl.get('debit_currency', { currency: currencyCode });
}
/**
* Account footer cell.
*/
function AccountFooterCell({ payload: { currencyCode } }) {
return <span>{intl.get('total_currency', { currency: currencyCode })}</span>;
}
/**
* Total credit table footer cell.
*/
function TotalCreditFooterCell({ payload: { currencyCode }, rows }) {
const credit = safeSumBy(rows, 'original.credit');
return (
<span>
<Money amount={credit} currency={currencyCode} />
</span>
);
}
/**
* Total debit table footer cell.
*/
function TotalDebitFooterCell({ payload: { currencyCode }, rows }) {
const debit = safeSumBy(rows, 'original.debit');
return (
<span>
<Money amount={debit} currency={currencyCode} />
</span>
);
}
/**
* Actions cell renderer.
*/
@@ -110,22 +76,11 @@ export const useJournalTableEntriesColumns = () => {
return React.useMemo(
() => [
{
Header: '#',
accessor: 'index',
Cell: ({ row: { index } }) => <span>{index + 1}</span>,
className: 'index',
width: 40,
disableResizing: true,
disableSortBy: true,
sticky: 'left',
},
{
Header: intl.get('account'),
id: 'account_id',
accessor: 'account_id',
Cell: AccountsListFieldCell,
Footer: AccountFooterCell,
className: 'account',
disableSortBy: true,
width: 160,
@@ -135,7 +90,6 @@ export const useJournalTableEntriesColumns = () => {
Header: CreditHeaderCell,
accessor: 'credit',
Cell: MoneyFieldCell,
Footer: TotalCreditFooterCell,
className: 'credit',
disableSortBy: true,
width: 100,
@@ -144,7 +98,6 @@ export const useJournalTableEntriesColumns = () => {
Header: DebitHeaderCell,
accessor: 'debit',
Cell: MoneyFieldCell,
Footer: TotalDebitFooterCell,
className: 'debit',
disableSortBy: true,
width: 100,

View File

@@ -27,7 +27,8 @@ const ERROR = {
ENTRIES_SHOULD_ASSIGN_WITH_CONTACT: 'ENTRIES_SHOULD_ASSIGN_WITH_CONTACT',
};
export const MIN_LINES_NUMBER = 4;
export const MIN_LINES_NUMBER = 1;
export const DEFAULT_LINES_NUMBER = 1;
export const defaultEntry = {
account_id: '',
@@ -49,7 +50,7 @@ export const defaultManualJournal = {
publish: '',
branch_id: '',
exchange_rate: 1,
entries: [...repeatValue(defaultEntry, 4)],
entries: [...repeatValue(defaultEntry, DEFAULT_LINES_NUMBER)],
};
// Transform to edit form.

View File

@@ -40,7 +40,6 @@ export default function PaymentMadeEntriesTable({
},
[onUpdateData, entries],
);
// Detarmines the right no results message before selecting vendor and aftering
// selecting vendor id.
const noResultsMessage = vendor_id ? (
@@ -67,7 +66,6 @@ export default function PaymentMadeEntriesTable({
currencyCode,
}}
noResults={noResultsMessage}
footer={true}
/>
</CloudLoadingIndicator>
);

View File

@@ -2,43 +2,15 @@ import React from 'react';
import intl from 'react-intl-universal';
import moment from 'moment';
import { Money } from 'components';
import { safeSumBy, formattedAmount } from 'utils';
import { MoneyFieldCell } from 'components/DataTableCells';
function BillNumberAccessor(row) {
return row?.bill_no ? row?.bill_no : '-';
}
function IndexTableCell({ row: { index } }) {
return <span>{index + 1}</span>;
}
function BillDateCell({ value }) {
return moment(value).format('YYYY MMM DD');
}
/**
* Balance footer cell.
*/
function AmountFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.amount');
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Due amount footer cell.
*/
function DueAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalDueAmount = safeSumBy(rows, 'original.due_amount');
return <span>{formattedAmount(totalDueAmount, currencyCode)}</span>;
}
/**
* Payment amount footer cell.
*/
function PaymentAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalPaymentAmount = safeSumBy(rows, 'original.payment_amount');
return <span>{formattedAmount(totalPaymentAmount, currencyCode)}</span>;
}
/**
* Mobey table cell.
@@ -51,19 +23,8 @@ function MoneyTableCell({ row: { original }, value }) {
* Payment made entries table columns
*/
export function usePaymentMadeEntriesTableColumns() {
return React.useMemo(
() => [
{
Header: '#',
accessor: 'index',
Cell: IndexTableCell,
width: 40,
disableResizing: true,
disableSortBy: true,
className: 'index',
},
{
Header: intl.get('Date'),
id: 'bill_date',
@@ -83,7 +44,6 @@ export function usePaymentMadeEntriesTableColumns() {
Header: intl.get('bill_amount'),
accessor: 'amount',
Cell: MoneyTableCell,
Footer: AmountFooterCell,
disableSortBy: true,
className: 'amount',
},
@@ -91,7 +51,6 @@ export function usePaymentMadeEntriesTableColumns() {
Header: intl.get('amount_due'),
accessor: 'due_amount',
Cell: MoneyTableCell,
Footer: DueAmountFooterCell,
disableSortBy: true,
className: 'due_amount',
},
@@ -99,7 +58,6 @@ export function usePaymentMadeEntriesTableColumns() {
Header: intl.get('payment_amount'),
accessor: 'payment_amount',
Cell: MoneyFieldCell,
Footer: PaymentAmountFooterCell,
disableSortBy: true,
className: 'payment_amount',
},

View File

@@ -62,7 +62,6 @@ export default function PaymentReceiveItemsTable({
currencyCode,
}}
noResults={noResultsMessage}
footer={true}
/>
</CloudLoadingIndicator>
);

View File

@@ -4,7 +4,6 @@ import intl from 'react-intl-universal';
import { Money } from 'components';
import { MoneyFieldCell } from 'components/DataTableCells';
import { safeSumBy, formattedAmount } from 'utils';
/**
* Invoice date cell.
@@ -13,13 +12,6 @@ function InvoiceDateCell({ value }) {
return <span>{moment(value).format('YYYY MMM DD')}</span>;
}
/**
* Index table cell.
*/
function IndexCell({ row: { index } }) {
return <span>{index + 1}</span>;
}
/**
* Invoice number table cell accessor.
*/
@@ -27,30 +19,6 @@ function InvNumberCellAccessor(row) {
return row?.invoice_no ? `#${row?.invoice_no || ''}` : '-';
}
/**
* Balance footer cell.
*/
function BalanceFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.amount');
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Due amount footer cell.
*/
function DueAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalDueAmount = safeSumBy(rows, 'original.due_amount');
return <span>{formattedAmount(totalDueAmount, currencyCode)}</span>;
}
/**
* Payment amount footer cell.
*/
function PaymentAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalPaymentAmount = safeSumBy(rows, 'original.payment_amount');
return <span>{formattedAmount(totalPaymentAmount, currencyCode)}</span>;
}
/**
* Mobey table cell.
*/
@@ -58,33 +26,17 @@ function MoneyTableCell({ row: { original }, value }) {
return <Money amount={value} currency={original.currency_code} />;
}
function DateFooterCell() {
return intl.get('total')
}
/**
* Retrieve payment receive form entries columns.
*/
export const usePaymentReceiveEntriesColumns = () => {
return React.useMemo(
() => [
{
Header: '#',
accessor: 'index',
Cell: IndexCell,
width: 40,
disableResizing: true,
disableSortBy: true,
className: 'index',
},
{
Header: intl.get('Date'),
Header: 'Invoice date',
id: 'invoice_date',
accessor: 'invoice_date',
Cell: InvoiceDateCell,
Footer: DateFooterCell,
disableSortBy: true,
disableResizing: true,
width: 250,
@@ -99,7 +51,6 @@ export const usePaymentReceiveEntriesColumns = () => {
{
Header: intl.get('invoice_amount'),
accessor: 'amount',
Footer: BalanceFooterCell,
Cell: MoneyTableCell,
disableSortBy: true,
width: 100,
@@ -108,7 +59,6 @@ export const usePaymentReceiveEntriesColumns = () => {
{
Header: intl.get('amount_due'),
accessor: 'due_amount',
Footer: DueAmountFooterCell,
Cell: MoneyTableCell,
disableSortBy: true,
width: 150,
@@ -118,7 +68,6 @@ export const usePaymentReceiveEntriesColumns = () => {
Header: intl.get('payment_amount'),
accessor: 'payment_amount',
Cell: MoneyFieldCell,
Footer: PaymentAmountFooterCell,
disableSortBy: true,
width: 150,
className: 'payment_amount',

View File

@@ -37,7 +37,7 @@ export default function WarehouseTransferEditorField() {
defaultEntry={defaultWarehouseTransferEntry}
errors={error}
sourceWarehouseId={values.from_warehouse_id}
distentionWarehouseId={value.to_warehouse_id}
destinationWarehouseId={values.to_warehouse_id}
/>
)}
</FastField>

View File

@@ -20,9 +20,10 @@ import WarehouseTransferFormDialog from './WarehouseTransferFormDialog';
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
import withSettings from 'containers/Settings/withSettings';
import { AppToaster } from 'components';
import { AppToaster, } from 'components';
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
import { compose, orderingLinesIndexes, transactionNumber } from 'utils';
import { WarehouseTransferObserveItemsCost } from './components';
import {
defaultWarehouseTransfer,
transformValueToRequest,
@@ -37,13 +38,14 @@ function WarehouseTransferForm({
warehouseTransferIncrementMode,
}) {
const history = useHistory();
const {
isNewMode,
warehouseTransfer,
createWarehouseTransferMutate,
editWarehouseTransferMutate,
submitPayload,
setItemCostQuery,
} = useWarehouseTransferFormContext();
// WarehouseTransfer number.
@@ -118,7 +120,7 @@ function WarehouseTransferForm({
.catch(onError);
}
};
return (
<div
className={classNames(
@@ -140,16 +142,18 @@ function WarehouseTransferForm({
<WarehouseTransferFormFooter />
<WarehouseTransferFormDialog />
<WarehouseTransferFloatingActions />
<WarehouseTransferObserveItemsCost />
</Form>
</Formik>
</div>
);
}
export default compose(withDashboardActions,
export default compose(
withDashboardActions,
withSettings(({ warehouseTransferSettings }) => ({
warehouseTransferNextNumber: warehouseTransferSettings?.nextNumber,
warehouseTransferNumberPrefix: warehouseTransferSettings?.numberPrefix,
warehouseTransferIncrementMode: warehouseTransferSettings?.autoIncrement,
})),
)(WarehouseTransferForm);
)(WarehouseTransferForm);

View File

@@ -6,10 +6,12 @@ import {
useWarehouseTransfer,
useCreateWarehouseTransfer,
useEditWarehouseTransfer,
useItemInventoryCost,
} from 'hooks/query';
import { Features } from 'common';
import { useFeatureCan } from 'hooks/state';
import { ITEMS_FILTER_ROLES_QUERY } from './utils.js';
import { isEmpty } from 'lodash';
const WarehouseFormContext = React.createContext();
@@ -44,6 +46,23 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
isLoading: isWarehouesLoading,
} = useWarehouses({}, { enabled: isWarehouseFeatureCan });
// Inventory items cost query.
const [itemCostQuery, setItemCostQuery] = React.useState(null);
// Detarmines whether the inventory items cost query is enabled.
const isItemsCostQueryEnabled =
!isEmpty(itemCostQuery?.date) && !isEmpty(itemCostQuery?.itemsIds);
// Retrieves the inventory item cost.
const { data: inventoryItemsCost } = useItemInventoryCost(
{
date: itemCostQuery?.date,
items_ids: itemCostQuery?.itemsIds,
},
{
enabled: isItemsCostQueryEnabled,
},
);
// Create and edit warehouse mutations.
const { mutateAsync: createWarehouseTransferMutate } =
useCreateWarehouseTransfer();
@@ -70,6 +89,10 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
setSubmitPayload,
createWarehouseTransferMutate,
editWarehouseTransferMutate,
inventoryItemsCost,
itemCostQuery,
setItemCostQuery,
};
return (

View File

@@ -0,0 +1,20 @@
import React from 'react';
import { FormikObserver } from 'components';
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
export function WarehouseTransferObserveItemsCost() {
const { setItemCostQuery } = useWarehouseTransferFormContext();
// Handle the form change.
const handleFormChange = (values) => {
const itemsIds = values.entries
.filter((e) => e.item_id)
.map((e) => e.item_id);
setItemCostQuery({
date: values.date,
itemsIds,
});
};
return <FormikObserver onChange={handleFormChange} />;
}

View File

@@ -65,10 +65,10 @@ export const useFetchItemWarehouseQuantity = () => {
return isItemSuccess
? {
...tableRow,
warehouses: [],
warehouses: transformWarehousesQuantity(item),
}
: null;
}, [isItemSuccess, tableRow]);
}, [isItemSuccess, item, tableRow]);
// Reset the table row.
const resetTableRow = React.useCallback(() => {
@@ -84,3 +84,11 @@ export const useFetchItemWarehouseQuantity = () => {
newRowMeta,
};
};
const transformWarehousesQuantity = (item) => {
return item.item_warehouses.map((warehouse) => ({
warehouseId: warehouse.warehouse_id,
quantityOnHand: warehouse.quantity_on_hand,
quantityOnHandFormatted: warehouse.quantity_on_hand_formatted,
}));
};

View File

@@ -22,14 +22,12 @@ import {
updateMinEntriesLines,
updateRemoveLineByIndex,
} from 'utils';
// import { defaultFastFieldShouldUpdate } from 'utils';
import {
updateItemsEntriesTotal,
ensureEntriesHaveEmptyLine,
} from 'containers/Entries/utils';
export const MIN_LINES_NUMBER = 4;
export const MIN_LINES_NUMBER = 1;
// Default warehouse transfer entry.
export const defaultWarehouseTransferEntry = {

View File

@@ -1,15 +1,10 @@
import React from 'react';
import intl from 'react-intl-universal';
import { find, get } from 'lodash';
import { Tooltip, Button, Intent, Position } from '@blueprintjs/core';
import { Button, Menu, MenuItem } from '@blueprintjs/core';
import { Popover2 } from '@blueprintjs/popover2';
import {
MoneyFieldCell,
FormatDateCell,
Icon,
AppToaster,
T,
} from 'components';
import { MoneyFieldCell, Icon, T } from 'components';
import { InputGroupCell, ItemsListCell } from 'components/DataTableCells';
// Index table cell.
@@ -31,37 +26,44 @@ export function ActionsCellRenderer({
removeRow(index);
};
const exampleMenu = (
<Menu>
<MenuItem onClick={onRemoveRole} text="Remove line" />
</Menu>
);
return (
<Tooltip content={<T id={'remove_the_line'} />} position={Position.LEFT}>
<Popover2 content={exampleMenu} placement="left-start">
<Button
icon={<Icon icon={'times-circle'} iconSize={14} />}
icon={<Icon icon={'more-13'} iconSize={13} />}
iconSize={14}
className="m12"
intent={Intent.DANGER}
onClick={onRemoveRole}
minimal={true}
/>
</Tooltip>
</Popover2>
);
}
function SourceWarehouseAccessorCell({ value, row: { original }, payload }) {
function SourceWarehouseAccessorCell({ row: { original }, payload }) {
// Ignore display zero if the item not selected yet.
if (!original.item_id) return '';
const warehouse = find(
original.warehouses,
(w) => w.warehouseId === payload.sourceWarehouseId,
);
return get(warehouse, 'warehouseQuantityFormatted', '0');
return get(warehouse, 'quantityOnHandFormatted', '0');
}
function DistentionWarehouseAccessorCell({
value,
row: { original },
payload,
}) {
function DistentionWarehouseAccessorCell({ row: { original }, payload }) {
// Ignore display zero if the item not selected yet.
if (!original.item_id) return '';
const warehouse = find(
original.warehouses,
(w) => w.warehouseId === payload.distentionWarehouseId,
(w) => w.warehouseId === payload.destinationWarehouseId,
);
return get(warehouse, 'warehouseQuantityFormatted', '0');
return get(warehouse, 'quantityOnHandFormatted', '0');
}
/**
@@ -71,15 +73,6 @@ function DistentionWarehouseAccessorCell({
export const useWarehouseTransferTableColumns = () => {
return React.useMemo(
() => [
{
Header: '#',
accessor: 'index',
Cell: IndexTableCell,
width: 40,
disableResizing: true,
disableSortBy: true,
className: 'index',
},
{
id: 'item_id',
Header: intl.get('warehouse_transfer.column.item_name'),
@@ -124,11 +117,18 @@ export const useWarehouseTransferTableColumns = () => {
align: 'right',
width: 100,
},
{
Header: intl.get('warehouse_transfer.column.cost_price'),
accessor: 'cost',
Cell: MoneyFieldCell,
disableSortBy: true,
align: 'right',
width: 100,
},
{
Header: '',
accessor: 'action',
Cell: ActionsCellRenderer,
className: 'actions',
disableSortBy: true,
disableResizing: true,
width: 45,

View File

@@ -246,3 +246,26 @@ export function useItemWarehouseLocation(id, props) {
},
);
}
/**
*
* @param {*} id
* @param {*} query
* @param {*} props
* @returns
*/
export function useItemInventoryCost(query, props) {
return useRequestQuery(
['ITEM_INVENTORY_COST', query],
{
method: 'get',
url: `inventory/items-cost`,
params: { ...query },
},
{
select: (res) => res.data.costs,
defaultData: [],
...props,
},
);
}

View File

@@ -1825,6 +1825,7 @@
"warehouse_transfer.column.transfer_quantity": "Transfer Quantity",
"warehouse_transfer.column.source_warehouse": "Source Warehouse",
"warehouse_transfer.column.destination_warehouse": "Destination Warehouse",
"warehouse_transfer.column.cost_price": "Cost price",
"warehouse_transfer.auto_increment.auto": "Your transfer numbers are set on auto-increment mode. Are you sure changing this setting?",
"warehouse_transfer.auto_increment.manually": "Your transfer numbers are set on manual mode. Are you sure chaning this settings?",
"warehouse_transfer.setting_your_auto_generated_transfer_no": "Setting your auto-generated transfer number",