mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
Merge branch 'master' of https://github.com/abouolia/Ratteb
# Conflicts: # client/src/lang/en/index.js
This commit is contained in:
@@ -6,6 +6,7 @@ import { useHistory } from 'react-router-dom';
|
||||
import { useIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { defaultTo } from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { CLASSES } from 'common/classes';
|
||||
import AppToaster from 'components/AppToaster';
|
||||
@@ -42,6 +43,9 @@ const defaultInitialValues = {
|
||||
category_id: '',
|
||||
sellable: 1,
|
||||
purchasable: true,
|
||||
opening_quantity: '',
|
||||
opening_cost: '',
|
||||
opening_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as Yup from 'yup';
|
||||
import { defaultTo } from 'lodash';
|
||||
import { formatMessage } from 'services/intl';
|
||||
import { DATATYPES_LENGTH } from 'common/dataTypes';
|
||||
import { isBlank } from 'utils';
|
||||
|
||||
const Schema = Yup.object().shape({
|
||||
active: Yup.boolean(),
|
||||
@@ -17,20 +18,24 @@ const Schema = Yup.object().shape({
|
||||
.max(DATATYPES_LENGTH.STRING)
|
||||
.label(formatMessage({ id: 'item_type_' })),
|
||||
code: Yup.string().trim().min(0).max(DATATYPES_LENGTH.STRING),
|
||||
cost_price: Yup.number().min(0).when(['purchasable'], {
|
||||
is: true,
|
||||
then: Yup.number()
|
||||
.required()
|
||||
.label(formatMessage({ id: 'cost_price_' })),
|
||||
otherwise: Yup.number().nullable(true),
|
||||
}),
|
||||
sell_price: Yup.number().min(0).when(['sellable'], {
|
||||
is: true,
|
||||
then: Yup.number()
|
||||
.required()
|
||||
.label(formatMessage({ id: 'sell_price_' })),
|
||||
otherwise: Yup.number().nullable(true),
|
||||
}),
|
||||
cost_price: Yup.number()
|
||||
.min(0)
|
||||
.when(['purchasable'], {
|
||||
is: true,
|
||||
then: Yup.number()
|
||||
.required()
|
||||
.label(formatMessage({ id: 'cost_price_' })),
|
||||
otherwise: Yup.number().nullable(true),
|
||||
}),
|
||||
sell_price: Yup.number()
|
||||
.min(0)
|
||||
.when(['sellable'], {
|
||||
is: true,
|
||||
then: Yup.number()
|
||||
.required()
|
||||
.label(formatMessage({ id: 'sell_price_' })),
|
||||
otherwise: Yup.number().nullable(true),
|
||||
}),
|
||||
cost_account_id: Yup.number()
|
||||
.when(['purchasable'], {
|
||||
is: true,
|
||||
@@ -56,9 +61,28 @@ const Schema = Yup.object().shape({
|
||||
stock: Yup.string() || Yup.boolean(),
|
||||
sellable: Yup.boolean().required(),
|
||||
purchasable: Yup.boolean().required(),
|
||||
opening_cost: Yup.number().when(['opening_quantity'], {
|
||||
is: (value) => value,
|
||||
then: Yup.number()
|
||||
.min(0)
|
||||
.required()
|
||||
.label(formatMessage({ id: 'opening_cost_' })),
|
||||
otherwise: Yup.number().nullable(),
|
||||
}),
|
||||
opening_quantity: Yup.number()
|
||||
.integer()
|
||||
.min(1)
|
||||
.nullable()
|
||||
.label(formatMessage({ id: 'opening_quantity_' })),
|
||||
opening_date: Yup.date().when(['opening_quantity', 'opening_cost'], {
|
||||
is: (quantity, cost) => !isBlank(quantity) && !isBlank(cost),
|
||||
then: Yup.date()
|
||||
.required()
|
||||
.label(formatMessage({ id: 'opening_date_' })),
|
||||
otherwise: Yup.date().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
export const transformItemFormData = (item, defaultValue) => {
|
||||
return {
|
||||
...item,
|
||||
@@ -66,7 +90,7 @@ export const transformItemFormData = (item, defaultValue) => {
|
||||
purchasable: !!defaultTo(item?.purchasable, defaultValue.purchasable),
|
||||
active: !!defaultTo(item?.active, defaultValue.active),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const CreateItemFormSchema = Schema;
|
||||
export const EditItemFormSchema = Schema;
|
||||
|
||||
@@ -57,7 +57,6 @@ function ItemFormBody({ accountsList, baseCurrency }) {
|
||||
<InputPrependText text={baseCurrency} />
|
||||
<MoneyInputGroup
|
||||
value={value}
|
||||
prefix={'$'}
|
||||
inputGroupProps={{ fill: true }}
|
||||
disabled={!form.values.sellable}
|
||||
onChange={(unformattedValue) => {
|
||||
@@ -132,7 +131,6 @@ function ItemFormBody({ accountsList, baseCurrency }) {
|
||||
<InputPrependText text={baseCurrency} />
|
||||
<MoneyInputGroup
|
||||
value={value}
|
||||
prefix={'$'}
|
||||
inputGroupProps={{ medium: true }}
|
||||
disabled={!form.values.purchasable}
|
||||
onChange={(unformattedValue) => {
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
import React from 'react';
|
||||
import { FastField, ErrorMessage } from 'formik';
|
||||
import { FormGroup, InputGroup, Position } from '@blueprintjs/core';
|
||||
import {
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
ControlGroup,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { AccountsSelectList, Col, Row, Hint } from 'components';
|
||||
import {
|
||||
AccountsSelectList,
|
||||
MoneyInputGroup,
|
||||
InputPrependText,
|
||||
Col,
|
||||
Row,
|
||||
Hint,
|
||||
} from 'components';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { FormattedMessage as T } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import withAccounts from 'containers/Accounts/withAccounts';
|
||||
import { compose, tansformDateValue, momentFormatter, inputIntent } from 'utils';
|
||||
import withSettings from 'containers/Settings/withSettings';
|
||||
import {
|
||||
compose,
|
||||
tansformDateValue,
|
||||
momentFormatter,
|
||||
inputIntent,
|
||||
handleDateChange,
|
||||
} from 'utils';
|
||||
|
||||
/**
|
||||
* Item form inventory sections.
|
||||
*/
|
||||
function ItemFormInventorySection({ accountsList }) {
|
||||
function ItemFormInventorySection({ accountsList, baseCurrency }) {
|
||||
return (
|
||||
<div class="page-form__section page-form__section--inventory">
|
||||
<h3>
|
||||
@@ -47,23 +66,23 @@ function ItemFormInventorySection({ accountsList }) {
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/*------------- Opening quantity ------------- */}
|
||||
<FastField name={'opening_quantity'}>
|
||||
{({ field, field: { value }, meta: { touched, error } }) => (
|
||||
{({ field, meta: { touched, error } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'opening_quantity'} />}
|
||||
labelInfo={<Hint />}
|
||||
className={'form-group--opening_quantity'}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'opening_quantity'} />}
|
||||
inline={true}
|
||||
>
|
||||
<InputGroup
|
||||
medium={true}
|
||||
{...field}
|
||||
/>
|
||||
<InputGroup medium={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/*------------- Opening date ------------- */}
|
||||
<FastField name={'opening_date'}>
|
||||
{({ form, field: { value }, meta: { touched, error } }) => (
|
||||
<FormGroup
|
||||
@@ -75,14 +94,16 @@ function ItemFormInventorySection({ accountsList }) {
|
||||
CLASSES.FILL,
|
||||
)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'opening_date'} />}
|
||||
inline={true}
|
||||
>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={tansformDateValue(value)}
|
||||
onChange={(value) => {
|
||||
onChange={handleDateChange((value) => {
|
||||
form.setFieldValue('opening_date', value);
|
||||
}}
|
||||
})}
|
||||
helperText={<ErrorMessage name={'opening_date'} />}
|
||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -90,20 +111,28 @@ function ItemFormInventorySection({ accountsList }) {
|
||||
</FastField>
|
||||
</Col>
|
||||
|
||||
{/*------------- Opening cost ------------- */}
|
||||
<Col xs={6}>
|
||||
<FastField name={'opening_average_rate'}>
|
||||
{({ field, field: { value }, meta: { touched, error } }) => (
|
||||
<FastField name={'opening_cost'}>
|
||||
{({ form, field: { value }, meta: { touched, error } }) => (
|
||||
<FormGroup
|
||||
label={'Opening average rate'}
|
||||
label={<T id={'opening_average_cost'} />}
|
||||
labelInfo={<Hint />}
|
||||
className={'form-group--opening_average_rate'}
|
||||
className={'form-group--opening_cost'}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name={'opening_cost'} />}
|
||||
inline={true}
|
||||
>
|
||||
<InputGroup
|
||||
medium={true}
|
||||
{...field}
|
||||
/>
|
||||
<ControlGroup>
|
||||
<InputPrependText text={baseCurrency} />
|
||||
<MoneyInputGroup
|
||||
value={value}
|
||||
inputGroupProps={{ fill: true }}
|
||||
onChange={(unformattedValue) => {
|
||||
form.setFieldValue('opening_cost', unformattedValue);
|
||||
}}
|
||||
/>
|
||||
</ControlGroup>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
@@ -117,4 +146,7 @@ export default compose(
|
||||
withAccounts(({ accountsList }) => ({
|
||||
accountsList,
|
||||
})),
|
||||
withSettings(({ organizationSettings }) => ({
|
||||
baseCurrency: organizationSettings?.baseCurrency,
|
||||
})),
|
||||
)(ItemFormInventorySection);
|
||||
|
||||
@@ -124,6 +124,14 @@ function ItemsDataTable({
|
||||
],
|
||||
);
|
||||
|
||||
const quantityonHandCell = ({ value: quantity }) => {
|
||||
return quantity <= 0 ? (
|
||||
<span className={'quantity_on_hand'}>{quantity}</span>
|
||||
) : (
|
||||
<span>{quantity}</span>
|
||||
);
|
||||
};
|
||||
|
||||
const handleRowContextMenu = useCallback(
|
||||
(cell) => {
|
||||
return actionMenuList(cell.row.original);
|
||||
@@ -178,7 +186,7 @@ function ItemsDataTable({
|
||||
{
|
||||
Header: formatMessage({ id: 'cost_price' }),
|
||||
accessor: (row) =>
|
||||
!isBlank(row.sell_price) ? (
|
||||
!isBlank(row.cost_price) ? (
|
||||
<Money amount={row.cost_price} currency={'USD'} />
|
||||
) : (
|
||||
''
|
||||
@@ -189,13 +197,7 @@ function ItemsDataTable({
|
||||
{
|
||||
Header: formatMessage({ id: 'quantity_on_hand' }),
|
||||
accessor: 'quantity_on_hand',
|
||||
className: 'quantity_on_hand',
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
Header: formatMessage({ id: 'average_rate' }),
|
||||
accessor: 'average_cost_rate',
|
||||
className: 'average_cost_rate',
|
||||
Cell: quantityonHandCell,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user