mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
feat(warehouseTransfer): add create & delete transfer & details.
This commit is contained in:
@@ -80,7 +80,7 @@ export default [
|
||||
},
|
||||
{
|
||||
text: <T id={'sidebar_warehouse_transfer'} />,
|
||||
href: '/warehouse-transfers',
|
||||
href: '/warehouses-transfers',
|
||||
},
|
||||
{
|
||||
text: <T id={'category_list'} />,
|
||||
@@ -119,7 +119,7 @@ export default [
|
||||
},
|
||||
{
|
||||
text: <T id={'warehouse_transfer.label.new_warehouse_transfer'} />,
|
||||
href: '/warehouse-transfers/new',
|
||||
href: '/warehouses-transfers/new',
|
||||
},
|
||||
{
|
||||
text: <T id={'New service'} />,
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { FormattedMessage as T, FormattedHTMLMessage } from 'components';
|
||||
import { Intent, Alert } from '@blueprintjs/core';
|
||||
import { AppToaster } from 'components';
|
||||
import { useDeleteWarehouseTransfer } from 'hooks/query';
|
||||
|
||||
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Warehouse transfer delete alert
|
||||
* @returns
|
||||
*/
|
||||
function WarehouseTransferDeleteAlert({
|
||||
name,
|
||||
|
||||
// #withAlertStoreConnect
|
||||
isOpen,
|
||||
payload: { warehouseTransferId },
|
||||
|
||||
// #withAlertActions
|
||||
closeAlert,
|
||||
}) {
|
||||
const { mutateAsync: deleteWarehouseTransferMutate, isLoading } =
|
||||
useDeleteWarehouseTransfer();
|
||||
|
||||
// handle cancel delete warehouse alert.
|
||||
const handleCancelDeleteAlert = () => {
|
||||
closeAlert(name);
|
||||
};
|
||||
|
||||
// handleConfirm delete warehouse transfer.
|
||||
const handleConfirmWarehouseTransferDelete = () => {
|
||||
deleteWarehouseTransferMutate(warehouseTransferId)
|
||||
.then(() => {
|
||||
AppToaster.show({
|
||||
message: intl.get('warehouse_transfer.alert.delete_message'),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
})
|
||||
.catch(
|
||||
({
|
||||
response: {
|
||||
data: { errors },
|
||||
},
|
||||
}) => {},
|
||||
)
|
||||
.finally(() => {
|
||||
closeAlert(name);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete'} />}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={isOpen}
|
||||
onCancel={handleCancelDeleteAlert}
|
||||
onConfirm={handleConfirmWarehouseTransferDelete}
|
||||
loading={isLoading}
|
||||
>
|
||||
<p>
|
||||
<FormattedHTMLMessage
|
||||
id={'warehouse_transfer.once_delete_this_warehouse_transfer'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
)(WarehouseTransferDeleteAlert);
|
||||
@@ -21,6 +21,7 @@ import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts';
|
||||
import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts';
|
||||
import TransactionsLockingAlerts from '../TransactionsLocking/TransactionsLockingAlerts';
|
||||
import WarehousesAlerts from '../Preferences/Warehouses/WarehousesAlerts';
|
||||
import WarehousesTransfersAlerts from '../WarehouseTransfers/WarehousesTransfersAlerts'
|
||||
|
||||
export default [
|
||||
...AccountsAlerts,
|
||||
@@ -46,4 +47,5 @@ export default [
|
||||
...VendorCreditNotesAlerts,
|
||||
...TransactionsLockingAlerts,
|
||||
...WarehousesAlerts,
|
||||
...WarehousesTransfersAlerts
|
||||
];
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
useEditWarehouse,
|
||||
useWarehouse,
|
||||
} from 'hooks/query';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
const WarehouseFormContext = React.createContext();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
// import {} from 'hooks/query';
|
||||
import { useWarehouseTransfer } from 'hooks/query';
|
||||
import { DrawerHeaderContent, DrawerLoading } from 'components';
|
||||
|
||||
const WarehouseTransferDetailDrawerContext = React.createContext();
|
||||
@@ -9,17 +9,22 @@ const WarehouseTransferDetailDrawerContext = React.createContext();
|
||||
* Warehouse transfer detail drawer provider.
|
||||
*/
|
||||
function WarehouseTransferDetailDrawerProvider({
|
||||
warehouseTransferId,
|
||||
warehouseTransferId = 5,
|
||||
...props
|
||||
}) {
|
||||
// Handle fetch invoice detail.
|
||||
const { data: warehouseTransfer, isLoading: isWarehouseTransferLoading } =
|
||||
useWarehouseTransfer(warehouseTransferId, {
|
||||
enabled: !!warehouseTransferId,
|
||||
});
|
||||
|
||||
const provider = {
|
||||
warehouseTransfer,
|
||||
warehouseTransferId,
|
||||
};
|
||||
|
||||
return (
|
||||
<DrawerLoading
|
||||
// loading={}
|
||||
>
|
||||
<DrawerLoading loading={isWarehouseTransferLoading}>
|
||||
<DrawerHeaderContent
|
||||
name="warehouse-transfer-detail-drawer"
|
||||
title={intl.get('warehouse_transfer.drawer.title', {
|
||||
|
||||
@@ -16,44 +16,31 @@ import {
|
||||
import { useWarehouseDetailDrawerContext } from './WarehouseTransferDetailDrawerProvider';
|
||||
|
||||
/**
|
||||
* Warehouse transfer details drawer header
|
||||
* Warehouse transfer details drawer header.
|
||||
*/
|
||||
export default function WarehouseTransferDetailHeader() {
|
||||
const { warehouseTransfer } = useWarehouseDetailDrawerContext();
|
||||
|
||||
return (
|
||||
<CommercialDocHeader>
|
||||
<CommercialDocTopHeader>
|
||||
<DetailsMenu>
|
||||
<AmountItem label={intl.get('amount')}>
|
||||
<span class="big-number">'$10'</span>
|
||||
</AmountItem>
|
||||
</DetailsMenu>
|
||||
</CommercialDocTopHeader>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<DetailItem label={intl.get('date')}>
|
||||
{/* <FormatDate value={} /> */}
|
||||
<FormatDate value={warehouseTransfer.date} />
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem
|
||||
label={intl.get('warehouse_transfer.drawer.label.transfer_number')}
|
||||
// children={}
|
||||
children={defaultTo(warehouseTransfer.transaction_number, '-')}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('warehouse_transfer.drawer.label.from_warehouse')}
|
||||
// children={}
|
||||
children={warehouseTransfer.from_warehouse.name}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('warehouse_transfer.drawer.label.to_warehouse')}
|
||||
// children={}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('reason')}
|
||||
// children={defaultTo(, '-')}
|
||||
children={warehouseTransfer.to_warehouse.name}
|
||||
/>
|
||||
</DetailsMenu>
|
||||
</CommercialDocHeader>
|
||||
);
|
||||
}
|
||||
|
||||
const AmountItem = styled(DetailItem)`
|
||||
width: 50%;
|
||||
`;
|
||||
|
||||
@@ -3,6 +3,7 @@ import React from 'react';
|
||||
import { CommercialDocEntriesTable } from 'components';
|
||||
import { TableStyle } from '../../../common';
|
||||
import { useWarehouseTransferReadOnlyEntriesColumns } from './utils';
|
||||
import { useWarehouseDetailDrawerContext } from './WarehouseTransferDetailDrawerProvider';
|
||||
|
||||
/**
|
||||
* Warehouse transfer detail table.
|
||||
@@ -12,10 +13,14 @@ export default function WarehouseTransferDetailTable() {
|
||||
// Warehouse transfer entries table columns.
|
||||
const columns = useWarehouseTransferReadOnlyEntriesColumns();
|
||||
|
||||
const {
|
||||
warehouseTransfer: { entries },
|
||||
} = useWarehouseDetailDrawerContext();
|
||||
|
||||
return (
|
||||
<CommercialDocEntriesTable
|
||||
columns={columns}
|
||||
data={[]}
|
||||
data={entries}
|
||||
styleName={TableStyle.Constrant}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,10 @@ import { FastField } from 'formik';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
|
||||
import { entriesFieldShouldUpdate } from './utils';
|
||||
import {
|
||||
entriesFieldShouldUpdate,
|
||||
defaultWarehouseTransferEntry,
|
||||
} from './utils';
|
||||
import WarehouseTransferFormEntriesTable from './WarehouseTransferFormEntriesTable';
|
||||
|
||||
/**
|
||||
@@ -11,12 +14,13 @@ import WarehouseTransferFormEntriesTable from './WarehouseTransferFormEntriesTab
|
||||
*/
|
||||
export default function WarehouseTransferEditorField() {
|
||||
const { items } = useWarehouseTransferFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<FastField
|
||||
name={'entries'}
|
||||
items={items}
|
||||
// shouldUpdate={entriesFieldShouldUpdate}
|
||||
shouldUpdate={entriesFieldShouldUpdate}
|
||||
>
|
||||
{({
|
||||
form: { values, setFieldValue },
|
||||
@@ -29,6 +33,7 @@ export default function WarehouseTransferEditorField() {
|
||||
setFieldValue('entries', entries);
|
||||
}}
|
||||
items={items}
|
||||
defaultEntry={defaultWarehouseTransferEntry}
|
||||
errors={error}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Popover,
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T } from 'components';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
import { Icon } from 'components';
|
||||
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
|
||||
|
||||
/**
|
||||
* Warehouse transfer floating actions bar.
|
||||
*/
|
||||
export default function WarehouseTransferFloatingActions() {
|
||||
// History context.
|
||||
const history = useHistory();
|
||||
|
||||
// Formik form context.
|
||||
const { isSubmitting, submitForm, resetForm, values, errors } =
|
||||
useFormikContext();
|
||||
|
||||
// Warehouse tansfer form context.
|
||||
const { isNewMode, setSubmitPayload } = useWarehouseTransferFormContext();
|
||||
|
||||
// Handle submit button click.
|
||||
const handleSubmitBtnClick = (event) => {
|
||||
setSubmitPayload({ redirect: true });
|
||||
submitForm();
|
||||
};
|
||||
|
||||
// Handle clear button click.
|
||||
const handleClearBtnClick = (event) => {
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// Handle submit & new button click.
|
||||
const handleSubmitAndNewClick = (event) => {
|
||||
setSubmitPayload({ redirect: false, resetForm: true });
|
||||
submitForm();
|
||||
};
|
||||
|
||||
// Handle cancel button click.
|
||||
const handleCancelBtnClick = (event) => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
type="submit"
|
||||
onClick={handleSubmitBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={!isNewMode ? <T id={'edit'} /> : <T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitAndNewClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
// onClick={handleSubmitContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={!isNewMode ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CLASSES } from 'common/classes';
|
||||
@@ -14,11 +15,18 @@ import {
|
||||
import WarehouseTransferFormHeader from './WarehouseTransferFormHeader';
|
||||
import WarehouseTransferEditorField from './WarehouseTransferEditorField';
|
||||
import WarehouseTransferFormFooter from './WarehouseTransferFormFooter';
|
||||
import WarehouseTransferFloatingActions from './WarehouseTransferFloatingActions';
|
||||
import WarehouseTransferFormDialog from './WarehouseTransferFormDialog';
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
|
||||
import { AppToaster } from 'components';
|
||||
import { useWarehouseTransferFormContext } from './WarehouseTransferFormProvider';
|
||||
import { compose, orderingLinesIndexes, transactionNumber } from 'utils';
|
||||
import { defaultWareTransferEntry, defaultWarehouseTransfer } from './utils';
|
||||
import {
|
||||
defaultWarehouseTransfer,
|
||||
transformValueToRequest,
|
||||
transformToEditForm,
|
||||
} from './utils';
|
||||
|
||||
function WarehouseTransferForm({
|
||||
// #withSettings
|
||||
@@ -28,6 +36,14 @@ function WarehouseTransferForm({
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
const {
|
||||
isNewMode,
|
||||
warehouseTransfer,
|
||||
createWarehouseTransferMutate,
|
||||
editWarehouseTransferMutate,
|
||||
submitPayload,
|
||||
} = useWarehouseTransferFormContext();
|
||||
|
||||
// WarehouseTransfer number.
|
||||
const warehouseTransferNumber = transactionNumber(
|
||||
warehouseTransferNumberPrefix,
|
||||
@@ -37,18 +53,43 @@ function WarehouseTransferForm({
|
||||
// Form initial values.
|
||||
const initialValues = React.useMemo(
|
||||
() => ({
|
||||
...defaultWarehouseTransfer,
|
||||
...(!isEmpty(null)
|
||||
? { ...transformToEditForm(null) }
|
||||
: {
|
||||
...defaultWarehouseTransfer,
|
||||
entries: orderingLinesIndexes(defaultWarehouseTransfer.entries),
|
||||
}),
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
// Handles form submit.
|
||||
const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => {
|
||||
setSubmitting(true);
|
||||
// Transformes the values of the form to request.
|
||||
const form = {};
|
||||
const form = {
|
||||
...transformValueToRequest(values),
|
||||
};
|
||||
|
||||
// Handle the request success.
|
||||
const onSuccess = () => {};
|
||||
const onSuccess = () => {
|
||||
AppToaster.show({
|
||||
message: intl.get(
|
||||
isNewMode
|
||||
? 'warehouse_transfer.success_message'
|
||||
: 'warehouse_transfer.edit_success_message',
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
setSubmitting(false);
|
||||
|
||||
if (submitPayload.redirect) {
|
||||
history.push('/warehouses-transfers');
|
||||
}
|
||||
if (submitPayload.resetForm) {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
// Handle the request error.
|
||||
const onError = ({
|
||||
@@ -58,6 +99,14 @@ function WarehouseTransferForm({
|
||||
}) => {
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
if (isNewMode) {
|
||||
createWarehouseTransferMutate(form).then(onSuccess).catch(onError);
|
||||
} else {
|
||||
editWarehouseTransferMutate([warehouseTransfer.id, form])
|
||||
.then(onSuccess)
|
||||
.catch(onError);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -70,7 +119,7 @@ function WarehouseTransferForm({
|
||||
>
|
||||
<Formik
|
||||
validationSchema={
|
||||
true ? CreateWarehouseFormSchema : EditWarehouseFormSchema
|
||||
isNewMode ? CreateWarehouseFormSchema : EditWarehouseFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
@@ -80,6 +129,7 @@ function WarehouseTransferForm({
|
||||
<WarehouseTransferEditorField />
|
||||
<WarehouseTransferFormFooter />
|
||||
<WarehouseTransferFormDialog />
|
||||
<WarehouseTransferFloatingActions />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,15 @@ import React from 'react';
|
||||
|
||||
import { useWarehouseTransferTableColumns } from '../utils';
|
||||
import { DataTableEditable } from 'components';
|
||||
import { compose, saveInvoke, updateTableCell } from 'utils';
|
||||
|
||||
import {
|
||||
saveInvoke,
|
||||
compose,
|
||||
updateTableCell,
|
||||
updateMinEntriesLines,
|
||||
updateAutoAddNewLine,
|
||||
updateRemoveLineByIndex,
|
||||
orderingLinesIndexes,
|
||||
} from 'utils';
|
||||
/**
|
||||
* Warehouse transfer form entries table.
|
||||
*/
|
||||
@@ -11,6 +18,7 @@ export default function WarehouseTransferFormEntriesTable({
|
||||
// #ownProps
|
||||
items,
|
||||
entries,
|
||||
defaultEntry,
|
||||
onUpdateData,
|
||||
errors,
|
||||
}) {
|
||||
@@ -20,12 +28,30 @@ export default function WarehouseTransferFormEntriesTable({
|
||||
// Handle update data.
|
||||
const handleUpdateData = React.useCallback(
|
||||
(rowIndex, columnId, value) => {
|
||||
const newRows = compose(updateTableCell(rowIndex, columnId, value))(
|
||||
entries,
|
||||
);
|
||||
onUpdateData(newRows);
|
||||
const newRows = compose(
|
||||
// Update auto-adding new line.
|
||||
updateAutoAddNewLine(defaultEntry, ['item_id']),
|
||||
// Update the row value of the given row index and column id.
|
||||
updateTableCell(rowIndex, columnId, value),
|
||||
)(entries);
|
||||
|
||||
saveInvoke(onUpdateData, newRows);
|
||||
},
|
||||
[onUpdateData, entries],
|
||||
[entries, defaultEntry, onUpdateData],
|
||||
);
|
||||
// Handles click remove datatable row.
|
||||
const handleRemoveRow = React.useCallback(
|
||||
(rowIndex) => {
|
||||
const newRows = compose(
|
||||
// Ensure minimum lines count.
|
||||
updateMinEntriesLines(4, defaultEntry),
|
||||
// Remove the line by the given index.
|
||||
updateRemoveLineByIndex(rowIndex),
|
||||
)(entries);
|
||||
|
||||
saveInvoke(onUpdateData, newRows);
|
||||
},
|
||||
[entries, defaultEntry, onUpdateData],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -36,6 +62,8 @@ export default function WarehouseTransferFormEntriesTable({
|
||||
items,
|
||||
errors: errors || [],
|
||||
updateData: handleUpdateData,
|
||||
removeRow: handleRemoveRow,
|
||||
autoFocus: ['item_id', 0],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
TextArea,
|
||||
Position,
|
||||
ControlGroup,
|
||||
} from '@blueprintjs/core';
|
||||
@@ -149,7 +148,7 @@ function WarehouseTransferFormHeaderFields({
|
||||
onAccountSelected={(account) => {
|
||||
form.setFieldValue('from_warehouse_id', account.id);
|
||||
}}
|
||||
defaultSelectText={'Select Warehouse Transfer'}
|
||||
defaultSelectText={<T id={'select_warehouse_transfer'} />}
|
||||
selectedAccountId={value}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
@@ -176,7 +175,7 @@ function WarehouseTransferFormHeaderFields({
|
||||
onAccountSelected={(account) => {
|
||||
form.setFieldValue('to_warehouse_id', account.id);
|
||||
}}
|
||||
defaultSelectText={'Select Warehouse Transfer'}
|
||||
defaultSelectText={<T id={'select_warehouse_transfer'} />}
|
||||
selectedAccountId={value}
|
||||
popoverFill={true}
|
||||
allowCreate={true}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React from 'react';
|
||||
import DashboardInsider from 'components/Dashboard/DashboardInsider';
|
||||
import { useItems, useWarehouses } from 'hooks/query';
|
||||
import {
|
||||
useItems,
|
||||
useWarehouses,
|
||||
useCreateWarehouseTransfer,
|
||||
useEditWarehouseTransfer,
|
||||
} from 'hooks/query';
|
||||
import { ITEMS_FILTER_ROLES_QUERY } from './utils.js';
|
||||
|
||||
const WarehouseFormContext = React.createContext();
|
||||
@@ -26,12 +31,32 @@ function WarehouseTransferFormProvider({ warehouseTransferId, ...props }) {
|
||||
isLoading: isWarehouesLoading,
|
||||
} = useWarehouses();
|
||||
|
||||
// Create and edit warehouse mutations.
|
||||
const { mutateAsync: createWarehouseTransferMutate } =
|
||||
useCreateWarehouseTransfer();
|
||||
const { mutateAsync: editWarehouseTransferMutate } =
|
||||
useEditWarehouseTransfer();
|
||||
|
||||
// Detarmines whether the form in new mode.
|
||||
const isNewMode = !warehouseTransferId;
|
||||
|
||||
// Form submit payload.
|
||||
const [submitPayload, setSubmitPayload] = React.useState();
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
items,
|
||||
warehouses,
|
||||
warehouseTransfer: [],
|
||||
|
||||
isItemsFetching,
|
||||
isWarehouesFetching,
|
||||
|
||||
isNewMode,
|
||||
submitPayload,
|
||||
setSubmitPayload,
|
||||
createWarehouseTransferMutate,
|
||||
editWarehouseTransferMutate,
|
||||
};
|
||||
return (
|
||||
<DashboardInsider
|
||||
|
||||
@@ -3,32 +3,72 @@ import intl from 'react-intl-universal';
|
||||
import clsx from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
import moment from 'moment';
|
||||
import { omit } from 'lodash';
|
||||
|
||||
import { transactionNumber, repeatValue } from 'utils';
|
||||
import {
|
||||
compose,
|
||||
transformToForm,
|
||||
repeatValue,
|
||||
transactionNumber,
|
||||
defaultFastFieldShouldUpdate,
|
||||
} from 'utils';
|
||||
|
||||
export const defaultWareTransferEntry = {
|
||||
// import { defaultFastFieldShouldUpdate } from 'utils';
|
||||
import {
|
||||
updateItemsEntriesTotal,
|
||||
ensureEntriesHaveEmptyLine,
|
||||
} from 'containers/Entries/utils';
|
||||
|
||||
export const MIN_LINES_NUMBER = 4;
|
||||
|
||||
// Default warehouse transfer entry.
|
||||
export const defaultWarehouseTransferEntry = {
|
||||
index: 0,
|
||||
item_id: '',
|
||||
source_warehouse: '100',
|
||||
destination_warehouse: '0',
|
||||
description: '',
|
||||
quantity: '',
|
||||
};
|
||||
|
||||
export const MIN_LINES_NUMBER = 4;
|
||||
|
||||
// Default warehouse transfer entry.
|
||||
export const defaultWarehouseTransfer = {
|
||||
date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
transaction_number: '',
|
||||
from_warehouse_id: '',
|
||||
to_warehouse_id: '',
|
||||
reason: '',
|
||||
entries: [...repeatValue(defaultWareTransferEntry, MIN_LINES_NUMBER)],
|
||||
entries: [...repeatValue(defaultWarehouseTransferEntry, MIN_LINES_NUMBER)],
|
||||
};
|
||||
|
||||
export const ITEMS_FILTER_ROLES_QUERY = JSON.stringify([
|
||||
{ fieldKey: 'type', comparator: 'is', value: 'inventory', index: 1 },
|
||||
]);
|
||||
|
||||
/**
|
||||
* Transform warehouse transfer to initial values in edit mode.
|
||||
*/
|
||||
export function transformToEditForm(warehouse) {
|
||||
const initialEntries = [
|
||||
...warehouse.entries.map((warehouse) => ({
|
||||
...transformToForm(warehouse, defaultWarehouseTransferEntry),
|
||||
})),
|
||||
...repeatValue(
|
||||
defaultWarehouseTransferEntry,
|
||||
Math.max(MIN_LINES_NUMBER - warehouse.entries.length, 0),
|
||||
),
|
||||
];
|
||||
const entries = compose(
|
||||
ensureEntriesHaveEmptyLine(defaultWarehouseTransferEntry),
|
||||
updateItemsEntriesTotal,
|
||||
)(initialEntries);
|
||||
|
||||
return {
|
||||
...transformToForm(warehouse, defaultWarehouseTransfer),
|
||||
entries,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs transfer no. settings with form.
|
||||
*/
|
||||
@@ -40,3 +80,28 @@ export const useObserveTransferNoSettings = (prefix, nextNumber) => {
|
||||
setFieldValue('transaction_number', transferNo);
|
||||
}, [setFieldValue, prefix, nextNumber]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Detarmines warehouse entries field when should update.
|
||||
*/
|
||||
export const entriesFieldShouldUpdate = (newProps, oldProps) => {
|
||||
return (
|
||||
newProps.items !== oldProps.items ||
|
||||
defaultFastFieldShouldUpdate(newProps, oldProps)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes the form values to request body values.
|
||||
*/
|
||||
export function transformValueToRequest(values) {
|
||||
const entries = values.entries.filter(
|
||||
(item) => item.item_id && item.quantity,
|
||||
);
|
||||
return {
|
||||
...values,
|
||||
entries: entries.map((entry) => ({
|
||||
...omit(entry, ['destination_warehouse', 'source_warehouse']),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ function WarehouseTransfersActionsBar({
|
||||
|
||||
// Handle new warehouse transfer button click.
|
||||
const handleClickNewWarehouseTransfer = () => {
|
||||
history.push('/warehouse-transfers/new');
|
||||
history.push('/warehouses-transfers/new');
|
||||
};
|
||||
|
||||
// Handle click a refresh warehouse transfers
|
||||
|
||||
@@ -43,18 +43,26 @@ function WarehouseTransfersDataTable({
|
||||
const columns = useWarehouseTransfersTableColumns();
|
||||
|
||||
// Handle view detail.
|
||||
const handleViewDetailWarehouseTransfer = () => {
|
||||
openDrawer('warehouse-transfer-detail-drawer', {});
|
||||
const handleViewDetailWarehouseTransfer = ({ id }) => {
|
||||
openDrawer('warehouse-transfer-detail-drawer', { warehouseTransferId: id });
|
||||
};
|
||||
|
||||
// Handle edit warehouse transfer.
|
||||
const handleEditWarehouseTransfer = () => {};
|
||||
const handleEditWarehouseTransfer = ({ id }) => {
|
||||
history.push(`/warehouses-transfers/${id}/edit`);
|
||||
};
|
||||
|
||||
// Handle delete warehouse transfer.
|
||||
const handleDeleteWarehouseTransfer = () => {};
|
||||
const handleDeleteWarehouseTransfer = ({ id }) => {
|
||||
openAlert('warehouse-transfer-delete', { warehouseTransferId: id });
|
||||
};
|
||||
|
||||
// Handle cell click.
|
||||
const handleCellClick = (cell, event) => {};
|
||||
const handleCellClick = (cell, event) => {
|
||||
openDrawer('warehouse-transfer-detail-drawer', {
|
||||
warehouseTransferId: cell.row.original.id,
|
||||
});
|
||||
};
|
||||
|
||||
// Local storage memorizing columns widths.
|
||||
const [initialColumnsWidths, , handleColumnResizing] =
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
|
||||
const WarehouseTransferDeleteAlert = React.lazy(() =>
|
||||
import('../Alerts/Warehouses/WarehouseTransferDeleteAlert'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Warehouses alerts.
|
||||
*/
|
||||
export default [
|
||||
{
|
||||
name: 'warehouse-transfer-delete',
|
||||
component: WarehouseTransferDeleteAlert,
|
||||
},
|
||||
];
|
||||
@@ -1,6 +1,14 @@
|
||||
import React from 'react';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { MoneyFieldCell, FormatDateCell, AppToaster, T } from 'components';
|
||||
import intl from 'react-intl-universal';
|
||||
import { Tooltip, Button, Intent, Position } from '@blueprintjs/core';
|
||||
|
||||
import {
|
||||
MoneyFieldCell,
|
||||
FormatDateCell,
|
||||
Icon,
|
||||
AppToaster,
|
||||
T,
|
||||
} from 'components';
|
||||
import { InputGroupCell, ItemsListCell } from 'components/DataTableCells';
|
||||
|
||||
// Index table cell.
|
||||
@@ -8,6 +16,33 @@ export function IndexTableCell({ row: { index } }) {
|
||||
return <span>{index + 1}</span>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions cell renderer component.
|
||||
*/
|
||||
export function ActionsCellRenderer({
|
||||
row: { index },
|
||||
column: { id },
|
||||
cell: { value },
|
||||
data,
|
||||
payload: { removeRow },
|
||||
}) {
|
||||
const onRemoveRole = () => {
|
||||
removeRow(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip content={<T id={'remove_the_line'} />} position={Position.LEFT}>
|
||||
<Button
|
||||
icon={<Icon icon={'times-circle'} iconSize={14} />}
|
||||
iconSize={14}
|
||||
className="m12"
|
||||
intent={Intent.DANGER}
|
||||
onClick={onRemoveRole}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfer table columns.
|
||||
* @returns
|
||||
@@ -26,21 +61,29 @@ export const useWarehouseTransferTableColumns = () => {
|
||||
},
|
||||
{
|
||||
id: 'item_id',
|
||||
Header: 'Item Name',
|
||||
Header: intl.get('warehouse_transfer.column.item_name'),
|
||||
accessor: 'item_id',
|
||||
Cell: ItemsListCell,
|
||||
disableSortBy: true,
|
||||
width: '120',
|
||||
width: 130,
|
||||
className: 'item',
|
||||
fieldProps: { allowCreate: true },
|
||||
},
|
||||
{
|
||||
Header: intl.get('description'),
|
||||
accessor: 'description',
|
||||
Cell: InputGroupCell,
|
||||
disableSortBy: true,
|
||||
className: 'description',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
id: 'source_warehouse',
|
||||
Header: 'Source Warehouse',
|
||||
accessor: 'source_warehouse',
|
||||
disableSortBy: true,
|
||||
align: 'right',
|
||||
width: '100',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
id: 'destination_warehouse',
|
||||
@@ -48,15 +91,24 @@ export const useWarehouseTransferTableColumns = () => {
|
||||
accessor: 'destination_warehouse',
|
||||
disableSortBy: true,
|
||||
align: 'right',
|
||||
width: '100',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
Header: 'Transfer Quantity',
|
||||
Header: intl.get('warehouse_transfer.column.transfer_quantity'),
|
||||
accessor: 'quantity',
|
||||
Cell: MoneyFieldCell,
|
||||
disableSortBy: true,
|
||||
align: 'right',
|
||||
width: '150',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: '',
|
||||
accessor: 'action',
|
||||
Cell: ActionsCellRenderer,
|
||||
className: 'actions',
|
||||
disableSortBy: true,
|
||||
disableResizing: true,
|
||||
width: 45,
|
||||
},
|
||||
],
|
||||
[],
|
||||
|
||||
@@ -186,7 +186,7 @@ export function useWarehouseTransfer(id, props, requestProps) {
|
||||
[t.WAREHOUSE_TRANSFER, id],
|
||||
{ method: 'get', url: `warehouses/transfers/${id}`, ...requestProps },
|
||||
{
|
||||
select: (res) => res.data,
|
||||
select: (res) => res.data.warehouse_transfer,
|
||||
defaultData: {},
|
||||
...props,
|
||||
},
|
||||
|
||||
@@ -1818,5 +1818,10 @@
|
||||
"warehouse_transfer.drawer.label.to_warehouse": "To Warehouse",
|
||||
"warehouse_transfer.label.edit_warehouse_transfer": "Edit Warehouse Transfer",
|
||||
"warehouse_transfer.label.new_warehouse_transfer": "New Warehouse Transfer",
|
||||
"warehouse_transfer.label.warehouse_transfer_list": "Warehouse Transfers List"
|
||||
"warehouse_transfer.label.warehouse_transfer_list": "Warehouse Transfers List",
|
||||
"warehouse_transfer.success_message":"The warehouse transfer transaction has been created successfully.",
|
||||
"warehouse_transfer.edit_success_message":"The warehouse transfer transaction has been created successfully.",
|
||||
"select_warehouse_transfer":"Select Warehouse Transfer",
|
||||
"warehouse_transfer.alert.delete_message":"The warehouse transfer transaction has been deleted successfully",
|
||||
"warehouse_transfer.once_delete_this_warehouse_transfer":"Once you delete this warehouse transfer, you won't be able to restore it later. Are you sure you want to delete this warehouse transfer?"
|
||||
}
|
||||
@@ -119,25 +119,25 @@ export const getDashboardRoutes = () => [
|
||||
},
|
||||
// Warehouse Transfer.
|
||||
{
|
||||
path: `/warehouse-transfers/:id/edit`,
|
||||
path: `/warehouses-transfers/:id/edit`,
|
||||
component: lazy(() => import('containers/Items/ItemFormPage')),
|
||||
name: 'warehouse-transfer-edit',
|
||||
pageTitle: intl.get('warehouse_transfer.label.edit_warehouse_transfer'),
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
path: `/warehouse-transfers/new`,
|
||||
path: `/warehouses-transfers/new`,
|
||||
component: lazy(() =>
|
||||
import(
|
||||
'../containers/WarehouseTransfers/WarehouseTransferForm/WarehouseTransferFormPage'
|
||||
),
|
||||
),
|
||||
name: 'warehouse-transfer-new',
|
||||
name: 'warehouses-transfer-new',
|
||||
pageTitle: intl.get('warehouse_transfer.label.new_warehouse_transfer'),
|
||||
backLink: true,
|
||||
},
|
||||
{
|
||||
path: `/warehouse-transfers`,
|
||||
path: `/warehouses-transfers`,
|
||||
component: lazy(() =>
|
||||
import(
|
||||
'../containers/WarehouseTransfers/WarehouseTransfersLanding/WarehouseTransfersList'
|
||||
|
||||
Reference in New Issue
Block a user