mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
feat(Sales & Purchases ): add branch & warehouse.
This commit is contained in:
@@ -19,6 +19,7 @@ import ReceiptItemsEntriesEditor from './ReceiptItemsEntriesEditor';
|
||||
import ReceiptFormFloatingActions from './ReceiptFormFloatingActions';
|
||||
import ReceiptFormFooter from './ReceiptFormFooter';
|
||||
import ReceiptFormDialogs from './ReceiptFormDialogs';
|
||||
import ReceiptFormTopbar from './ReceiptFormTopbar';
|
||||
|
||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
@@ -157,6 +158,7 @@ function ReceiptForm({
|
||||
onSubmit={handleFormSubmit}
|
||||
>
|
||||
<Form>
|
||||
<ReceiptFormTopbar />
|
||||
<ReceiptFromHeader />
|
||||
<ReceiptItemsEntriesEditor />
|
||||
<ReceiptFormFooter />
|
||||
|
||||
@@ -4,12 +4,8 @@ import { DATATYPES_LENGTH } from 'common/dataTypes';
|
||||
import { isBlank } from 'utils';
|
||||
|
||||
const Schema = Yup.object().shape({
|
||||
customer_id: Yup.string()
|
||||
.label(intl.get('customer_name_'))
|
||||
.required(),
|
||||
receipt_date: Yup.date()
|
||||
.required()
|
||||
.label(intl.get('receipt_date_')),
|
||||
customer_id: Yup.string().label(intl.get('customer_name_')).required(),
|
||||
receipt_date: Yup.date().required().label(intl.get('receipt_date_')),
|
||||
receipt_number: Yup.string()
|
||||
.nullable()
|
||||
.max(DATATYPES_LENGTH.STRING)
|
||||
@@ -29,6 +25,8 @@ const Schema = Yup.object().shape({
|
||||
.max(DATATYPES_LENGTH.TEXT)
|
||||
.label(intl.get('note')),
|
||||
closed: Yup.boolean(),
|
||||
branch_id: Yup.string(),
|
||||
warehouse_id: Yup.string(),
|
||||
entries: Yup.array().of(
|
||||
Yup.object().shape({
|
||||
quantity: Yup.number()
|
||||
|
||||
@@ -5,6 +5,8 @@ import {
|
||||
useAccounts,
|
||||
useSettingsReceipts,
|
||||
useCustomers,
|
||||
useWarehouses,
|
||||
useBranches,
|
||||
useItems,
|
||||
useCreateReceipt,
|
||||
useEditReceipt,
|
||||
@@ -17,12 +19,9 @@ const ReceiptFormContext = createContext();
|
||||
*/
|
||||
function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
// Fetch sale receipt details.
|
||||
const { data: receipt, isLoading: isReceiptLoading } = useReceipt(
|
||||
receiptId,
|
||||
{
|
||||
enabled: !!receiptId,
|
||||
},
|
||||
);
|
||||
const { data: receipt, isLoading: isReceiptLoading } = useReceipt(receiptId, {
|
||||
enabled: !!receiptId,
|
||||
});
|
||||
// Fetch accounts list.
|
||||
const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
|
||||
|
||||
@@ -32,12 +31,38 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
isLoading: isCustomersLoading,
|
||||
} = useCustomers({ page_size: 10000 });
|
||||
|
||||
// Fetch warehouses list.
|
||||
const {
|
||||
data: warehouses,
|
||||
isLoading: isWarehouesLoading,
|
||||
isSuccess: isWarehousesSuccess,
|
||||
} = useWarehouses();
|
||||
|
||||
// Fetches the branches list.
|
||||
const {
|
||||
data: branches,
|
||||
isLoading: isBranchesLoading,
|
||||
isSuccess: isBranchesSuccess,
|
||||
} = useBranches();
|
||||
|
||||
// Filter all sellable items only.
|
||||
const stringifiedFilterRoles = React.useMemo(
|
||||
() =>
|
||||
JSON.stringify([
|
||||
{ index: 1, fieldKey: 'sellable', value: true, condition: '&&', comparator: 'equals', },
|
||||
{ index: 2, fieldKey: 'active', value: true, condition: '&&', comparator: 'equals' },
|
||||
{
|
||||
index: 1,
|
||||
fieldKey: 'sellable',
|
||||
value: true,
|
||||
condition: '&&',
|
||||
comparator: 'equals',
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
fieldKey: 'active',
|
||||
value: true,
|
||||
condition: '&&',
|
||||
comparator: 'equals',
|
||||
},
|
||||
]),
|
||||
[],
|
||||
);
|
||||
@@ -61,12 +86,16 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
|
||||
const isNewMode = !receiptId;
|
||||
|
||||
const isFeatureLoading = isWarehouesLoading || isBranchesLoading;
|
||||
|
||||
const provider = {
|
||||
receiptId,
|
||||
receipt,
|
||||
accounts,
|
||||
customers,
|
||||
items,
|
||||
branches,
|
||||
warehouses,
|
||||
submitPayload,
|
||||
|
||||
isNewMode,
|
||||
@@ -74,7 +103,12 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
isAccountsLoading,
|
||||
isCustomersLoading,
|
||||
isItemsLoading,
|
||||
isWarehouesLoading,
|
||||
isBranchesLoading,
|
||||
isFeatureLoading,
|
||||
isSettingLoading,
|
||||
isBranchesSuccess,
|
||||
isWarehousesSuccess,
|
||||
|
||||
createReceiptMutate,
|
||||
editReceiptMutate,
|
||||
|
||||
127
src/containers/Sales/Receipts/ReceiptForm/ReceiptFormTopbar.js
Normal file
127
src/containers/Sales/Receipts/ReceiptForm/ReceiptFormTopbar.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Alignment,
|
||||
Navbar,
|
||||
NavbarGroup,
|
||||
NavbarDivider,
|
||||
Button,
|
||||
Classes,
|
||||
} from '@blueprintjs/core';
|
||||
import {
|
||||
useSetPrimaryWarehouseToForm,
|
||||
useSetPrimaryBranchToForm,
|
||||
} from './utils';
|
||||
|
||||
import { useFeatureCan } from 'hooks/state';
|
||||
import { Icon, BranchSelect, FeatureCan, WarehouseSelect } from 'components';
|
||||
import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import { Features } from 'common';
|
||||
|
||||
/**
|
||||
* Receipt form topbar .
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
export default function ReceiptFormTopbar() {
|
||||
// Features guard.
|
||||
const { featureCan } = useFeatureCan();
|
||||
|
||||
// Sets the primary warehouse to form.
|
||||
useSetPrimaryWarehouseToForm();
|
||||
|
||||
// Sets the primary branch to form.
|
||||
useSetPrimaryBranchToForm();
|
||||
|
||||
// Can't display the navigation bar if warehouses or branches feature is not enabled.
|
||||
if (!featureCan(Features.Warehouses) || !featureCan(Features.Branches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Navbar className={'navbar--dashboard-topbar'}>
|
||||
<NavbarGroup align={Alignment.LEFT}>
|
||||
<FeatureCan feature={Features.Branches}>
|
||||
<ReceiptFormSelectBranch />
|
||||
</FeatureCan>
|
||||
{featureCan(Features.Warehouses) && featureCan(Features.Branches) && (
|
||||
<NavbarDivider />
|
||||
)}
|
||||
<FeatureCan feature={Features.Warehouses}>
|
||||
<ReceiptFormSelectWarehouse />
|
||||
</FeatureCan>
|
||||
</NavbarGroup>
|
||||
</Navbar>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receipt select branch.
|
||||
* @returns
|
||||
*/
|
||||
function ReceiptFormSelectBranch() {
|
||||
// Receipt form context.
|
||||
const { branches, isBranchesLoading } = useReceiptFormContext();
|
||||
|
||||
return isBranchesLoading ? (
|
||||
<DetailsBarSkeletonBase className={Classes.SKELETON} />
|
||||
) : (
|
||||
<BranchSelect
|
||||
name={'branch_id'}
|
||||
branches={branches}
|
||||
input={ReceiptBranchSelectButton}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receipt select warehouse.
|
||||
* @returns
|
||||
*/
|
||||
function ReceiptFormSelectWarehouse() {
|
||||
// Receipt form context.
|
||||
const { warehouses, isWarehouesLoading } = useReceiptFormContext();
|
||||
|
||||
return isWarehouesLoading ? (
|
||||
<DetailsBarSkeletonBase className={Classes.SKELETON} />
|
||||
) : (
|
||||
<WarehouseSelect
|
||||
name={'warehouse_id'}
|
||||
warehouses={warehouses}
|
||||
input={ReceiptWarehouseSelectButton}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ReceiptBranchSelectButton({ label }) {
|
||||
return (
|
||||
<Button
|
||||
text={intl.get('invoice.branch_button.label', { label })}
|
||||
minimal={true}
|
||||
small={true}
|
||||
icon={<Icon icon={'branch-16'} iconSize={16} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ReceiptWarehouseSelectButton({ label }) {
|
||||
return (
|
||||
<Button
|
||||
text={intl.get('invoice.warehouse_button.label', { label })}
|
||||
minimal={true}
|
||||
small={true}
|
||||
icon={<Icon icon={'warehouse-16'} iconSize={16} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const DetailsBarSkeletonBase = styled.div`
|
||||
letter-spacing: 10px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
font-size: 8px;
|
||||
width: 140px;
|
||||
height: 10px;
|
||||
`;
|
||||
@@ -3,13 +3,14 @@ import { useFormikContext } from 'formik';
|
||||
import moment from 'moment';
|
||||
import * as R from 'ramda';
|
||||
import intl from 'react-intl-universal';
|
||||
import { omit } from 'lodash';
|
||||
import { omit, first } from 'lodash';
|
||||
import {
|
||||
defaultFastFieldShouldUpdate,
|
||||
transactionNumber,
|
||||
repeatValue,
|
||||
transformToForm,
|
||||
} from 'utils';
|
||||
import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import {
|
||||
updateItemsEntriesTotal,
|
||||
ensureEntriesHaveEmptyLine,
|
||||
@@ -36,6 +37,8 @@ export const defaultReceipt = {
|
||||
receipt_message: '',
|
||||
statement: '',
|
||||
closed: '',
|
||||
branch_id: '',
|
||||
warehouse_id: '',
|
||||
entries: [...repeatValue(defaultReceiptEntry, MIN_LINES_NUMBER)],
|
||||
};
|
||||
|
||||
@@ -142,3 +145,34 @@ export const transformFormValuesToRequest = (values) => {
|
||||
closed: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const useSetPrimaryWarehouseToForm = () => {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
const { warehouses, isWarehousesSuccess } = useReceiptFormContext();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isWarehousesSuccess) {
|
||||
const primaryWarehouse =
|
||||
warehouses.find((b) => b.primary) || first(warehouses);
|
||||
|
||||
if (primaryWarehouse) {
|
||||
setFieldValue('warehouse_id', primaryWarehouse.id);
|
||||
}
|
||||
}
|
||||
}, [isWarehousesSuccess, setFieldValue, warehouses]);
|
||||
};
|
||||
|
||||
export const useSetPrimaryBranchToForm = () => {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
const { branches, isBranchesSuccess } = useReceiptFormContext();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isBranchesSuccess) {
|
||||
const primaryBranch = branches.find((b) => b.primary) || first(branches);
|
||||
|
||||
if (primaryBranch) {
|
||||
setFieldValue('branch_id', primaryBranch.id);
|
||||
}
|
||||
}
|
||||
}, [isBranchesSuccess, setFieldValue, branches]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user