Merge branch 'currencyCode'

This commit is contained in:
a.bouhuolia
2021-04-06 18:58:25 +02:00
40 changed files with 275 additions and 138 deletions

View File

@@ -39,7 +39,7 @@ const MoneyFieldCellRenderer = ({
className={CLASSES.FILL}>
<MoneyInputGroup
value={value}
prefix={'$'}
// prefix={'$'}
onChange={handleFieldChange}
onBlur={handleFieldBlur}
{...moneyInputGroupProps}

View File

@@ -22,18 +22,23 @@ import { formatMessage } from 'services/intl';
*/
export const AmountAccessor = (r) => (
<Tooltip
content={<AmountPopoverContent journalEntries={r.entries} />}
content={
<AmountPopoverContent
journalEntries={r.entries}
currencyCode={r.currency_code}
/>
}
position={Position.RIGHT_TOP}
boundary={'viewport'}
>
<Money amount={r.amount} currency={'USD'} />
{r.amount_formatted}
</Tooltip>
);
/**
* Amount popover content line.
*/
export const AmountPopoverContentLine = ({ journalEntry }) => {
export const AmountPopoverContentLine = ({ journalEntry, currencyCode }) => {
const isCredit = !!journalEntry.credit;
const isDebit = !!journalEntry.debit;
const { account } = journalEntry;
@@ -42,14 +47,14 @@ export const AmountPopoverContentLine = ({ journalEntry }) => {
<Choose>
<Choose.When condition={isDebit}>
<div>
C. <Money amount={journalEntry.debit} currency={'USD'} /> USD -{' '}
C. <Money amount={journalEntry.debit} currency={currencyCode} /> -{' '}
{account.name} <If condition={account.code}>({account.code})</If>
</div>
</Choose.When>
<Choose.When condition={isCredit}>
<div>
D. <Money amount={journalEntry.credit} currency={'USD'} /> USD -{' '}
D. <Money amount={journalEntry.credit} currency={currencyCode} /> -{' '}
{account.name} <If condition={account.code}>({account.code})</If>
</div>
</Choose.When>
@@ -60,7 +65,7 @@ export const AmountPopoverContentLine = ({ journalEntry }) => {
/**
* Amount popover content.
*/
export function AmountPopoverContent({ journalEntries }) {
export function AmountPopoverContent({ journalEntries, currencyCode }) {
const journalLinesProps = journalEntries.map((journalEntry) => ({
journalEntry,
accountId: journalEntry.account_id,
@@ -72,6 +77,7 @@ export function AmountPopoverContent({ journalEntries }) {
<AmountPopoverContentLine
journalEntry={journalEntry}
accountId={accountId}
currencyCode={currencyCode}
/>
))}
</div>

View File

@@ -12,15 +12,16 @@ export default function MakeJournalEntriesField() {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({ form:{values ,setFieldValue}, field: { value }, meta: { error, touched } }) => (
<MakeJournalEntriesTable
onChange={(entries) => {
form.setFieldValue('entries', entries);
setFieldValue('entries', entries);
}}
entries={value}
defaultEntry={defaultEntry}
initialLinesNumber={MIN_LINES_NUMBER}
error={error}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -65,10 +65,10 @@ function MakeJournalEntriesForm({
}
: {
...defaultManualJournal,
...(journalAutoIncrement) && ({
...(journalAutoIncrement && {
journal_number: defaultTo(journalNumber, ''),
}),
currency_code: defaultTo(baseCurrency, ''),
currency_code: baseCurrency,
entries: orderingLinesIndexes(defaultManualJournal.entries),
}),
}),
@@ -111,7 +111,7 @@ function MakeJournalEntriesForm({
}
const form = {
...omit(values, ['journal_number', 'journal_number_manually']),
...(values.journal_number_manually) && ({
...(values.journal_number_manually && {
journal_number: values.journal_number,
}),
entries,

View File

@@ -2,12 +2,14 @@ import React from 'react';
import classNames from 'classnames';
import { useFormikContext } from 'formik';
import { CLASSES } from 'common/classes';
import MakeJournalEntriesHeaderFields from "./MakeJournalEntriesHeaderFields";
import MakeJournalEntriesHeaderFields from './MakeJournalEntriesHeaderFields';
import { PageFormBigNumber } from 'components';
import { safeSumBy } from 'utils';
export default function MakeJournalEntriesHeader() {
const { values: { entries } } = useFormikContext();
const {
values: { entries, currency_code },
} = useFormikContext();
const totalCredit = safeSumBy(entries, 'credit');
const totalDebit = safeSumBy(entries, 'debit');
@@ -20,8 +22,8 @@ export default function MakeJournalEntriesHeader() {
<PageFormBigNumber
label={'Due Amount'}
amount={total}
currencyCode={'USD'}
currencyCode={currency_code}
/>
</div>
)
}
);
}

View File

@@ -23,6 +23,7 @@ export default function MakeJournalEntriesTable({
error,
initialLinesNumber = 4,
minLinesNumber = 4,
currencyCode,
}) {
const { accounts, customers } = useMakeJournalFormContext();
@@ -72,7 +73,8 @@ export default function MakeJournalEntriesTable({
contact_type: 'customer',
})),
autoFocus: ['account_id', 0],
currencyCode,
}}
/>
);
}
}

View File

@@ -1,7 +1,8 @@
import React from 'react';
import { Intent, Position, Button, Tooltip } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { FormattedMessage as T } from 'react-intl';
import { Icon, Money, Hint } from 'components';
import { formatMessage } from 'services/intl';
import {
AccountsListFieldCell,
MoneyFieldCell,
@@ -25,22 +26,36 @@ export function ContactHeaderCell() {
);
}
/**
* Credit header cell.
*/
export function CreditHeaderCell({ payload: { currencyCode } }) {
return formatMessage({ id: 'credit_currency' }, { currency: currencyCode });
}
/**
* debit header cell.
*/
export function DebitHeaderCell({ payload: { currencyCode } }) {
return formatMessage({ id: 'debit_currency' }, { currency: currencyCode });
}
/**
* Account footer cell.
*/
function AccountFooterCell() {
return <span>{'Total USD'}</span>;
function AccountFooterCell({ payload: { currencyCode } }) {
return <span>{`Total ${currencyCode} `}</span>;
}
/**
* Total credit table footer cell.
*/
function TotalCreditFooterCell({ rows }) {
function TotalCreditFooterCell({ payload: { currencyCode }, rows }) {
const credit = safeSumBy(rows, 'original.credit');
return (
<span>
<Money amount={credit} currency={'USD'} />
<Money amount={credit} currency={currencyCode} />
</span>
);
}
@@ -48,12 +63,12 @@ function TotalCreditFooterCell({ rows }) {
/**
* Total debit table footer cell.
*/
function TotalDebitFooterCell({ rows }) {
function TotalDebitFooterCell({ payload: { currencyCode }, rows }) {
const debit = safeSumBy(rows, 'original.debit');
return (
<span>
<Money amount={debit} currency={'USD'} />
<Money amount={debit} currency={currencyCode} />
</span>
);
}
@@ -88,8 +103,6 @@ export const ActionsCellRenderer = ({
* Retrieve columns of make journal entries table.
*/
export const useJournalTableEntriesColumns = () => {
const { formatMessage } = useIntl();
return React.useMemo(
() => [
{
@@ -113,7 +126,7 @@ export const useJournalTableEntriesColumns = () => {
width: 160,
},
{
Header: formatMessage({ id: 'credit_currency' }, { currency: 'USD' }),
Header: CreditHeaderCell,
accessor: 'credit',
Cell: MoneyFieldCell,
Footer: TotalCreditFooterCell,
@@ -122,7 +135,7 @@ export const useJournalTableEntriesColumns = () => {
width: 100,
},
{
Header: formatMessage({ id: 'debit_currency' }, { currency: 'USD' }),
Header: DebitHeaderCell,
accessor: 'debit',
Cell: MoneyFieldCell,
Footer: TotalDebitFooterCell,

View File

@@ -117,7 +117,7 @@ export function BalanceCell({ cell }) {
return account.amount !== null ? (
<span>
<Money amount={account.amount} currency={'USD'} />
<Money amount={account.amount} currency={account.currency_code} />
</span>
) : (
<span class="placeholder"></span>

View File

@@ -78,7 +78,7 @@ export const useAccountsTableColumns = () => {
{
id: 'currency',
Header: formatMessage({ id: 'currency' }),
accessor: (row) => 'USD',
accessor: 'currency_code',
width: 75,
},
{

View File

@@ -28,6 +28,7 @@ function ItemsEntriesTable({
errors,
onUpdateData,
linesNumber,
currencyCode,
itemType, // sellable or purchasable
}) {
const [rows, setRows] = React.useState(initialEntries);
@@ -35,13 +36,14 @@ function ItemsEntriesTable({
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),
},
);
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) {
@@ -141,6 +143,7 @@ function ItemsEntriesTable({
updateData: handleUpdateData,
removeRow: handleRemoveRow,
autoFocus: ['item_id', 0],
currencyCode,
}}
/>
);

View File

@@ -8,7 +8,7 @@ import {
MoneyFieldCell,
ItemsListCell,
PercentFieldCell,
NumericInputCell
NumericInputCell,
} from 'components/DataTableCells';
/**
@@ -62,27 +62,27 @@ export function ActionsCellRenderer({
*/
export function QuantityTotalFooterCell({ rows }) {
const quantity = safeSumBy(rows, 'original.quantity');
return <span>{ quantity }</span>;
return <span>{quantity}</span>;
}
/**
* Total footer cell.
*/
export function TotalFooterCell({ rows }) {
export function TotalFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.total');
return <span>{ formattedAmount(total, 'USD') }</span>;
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Total accessor.
*/
export function TotalCell({ value }) {
return <span>{ formattedAmount(value, 'USD', { noZero: true }) }</span>;
export function TotalCell({ payload: { currencyCode }, value }) {
return <span>{formattedAmount(value, currencyCode, { noZero: true })}</span>;
}
// Index table cell.
export function IndexTableCell({ row: { index } }){
return (<span>{index + 1}</span>);
export function IndexTableCell({ row: { index } }) {
return <span>{index + 1}</span>;
}
/**
@@ -167,4 +167,3 @@ export function useEditableItemsEntriesColumns() {
[formatMessage],
);
}

View File

@@ -6,20 +6,23 @@ import { defaultExpenseEntry } from './utils';
/**
* Expense form entries field.
*/
export default function ExpenseFormEntriesField({
linesNumber = 4,
}) {
export default function ExpenseFormEntriesField({ linesNumber = 4 }) {
return (
<FastField name={'categories'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<ExpenseFormEntriesTable
entries={value}
error={error}
onChange={(entries) => {
form.setFieldValue('categories', entries);
setFieldValue('categories', entries);
}}
defaultEntry={defaultExpenseEntry}
linesNumber={linesNumber}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -21,6 +21,7 @@ export default function ExpenseFormEntriesTable({
defaultEntry,
error,
onChange,
currencyCode,
}) {
// Expense form context.
const { accounts } = useExpenseFormContext();
@@ -69,6 +70,7 @@ export default function ExpenseFormEntriesTable({
updateData: handleUpdateData,
removeRow: handleRemoveRow,
autoFocus: ['expense_account_id', 0],
currencyCode
}}
footer={true}
/>

View File

@@ -1,7 +1,8 @@
import React from 'react';
import { Button, Tooltip, Intent, Position } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import { FormattedMessage as T } from 'react-intl';
import { Icon, Hint } from 'components';
import { formatMessage } from 'services/intl';
import {
InputGroupCell,
MoneyFieldCell,
@@ -51,9 +52,16 @@ const ActionsCellRenderer = ({
/**
* Amount footer cell.
*/
function AmountFooterCell({ rows }) {
function AmountFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.amount');
return <span>{formattedAmount(total, 'USD')}</span>;
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Expense amount header cell.
*/
export function ExpenseAmountHeaderCell({ payload: { currencyCode } }) {
return formatMessage({ id: 'amount_currency' }, { currency: currencyCode });
}
/**
@@ -67,7 +75,6 @@ function ExpenseAccountFooterCell() {
* Retrieve expense form table entries columns.
*/
export function useExpenseFormTableColumns() {
const { formatMessage } = useIntl();
return React.useMemo(
() => [
@@ -92,7 +99,7 @@ export function useExpenseFormTableColumns() {
filterAccountsByRootTypes: ['expense'],
},
{
Header: formatMessage({ id: 'amount_currency' }, { currency: 'USD' }),
Header: ExpenseAmountHeaderCell,
accessor: 'amount',
Cell: MoneyFieldCell,
Footer: AmountFooterCell,

View File

@@ -181,16 +181,16 @@ export const useItemsTableColumns = () => {
{
id: 'sell_price',
Header: formatMessage({ id: 'sell_price' }),
Cell: SellPriceCell,
accessor: 'sell_price',
// Cell: SellPriceCell,
accessor: 'sell_price_formatted',
className: 'sell-price',
width: 150,
},
{
id: 'cost_price',
Header: formatMessage({ id: 'cost_price' }),
Cell: CostPriceCell,
accessor: 'cost_price',
// Cell: CostPriceCell,
accessor: 'cost_price_formatted',
className: 'cost-price',
width: 150,
},

View File

@@ -17,13 +17,17 @@ import { AppToaster } from 'components';
import { ERROR } from 'common/errors';
import { useBillFormContext } from './BillFormProvider';
import { orderingLinesIndexes, safeSumBy } from 'utils';
import { compose, orderingLinesIndexes, safeSumBy } from 'utils';
import { defaultBill, transformToEditForm } from './utils';
import withSettings from 'containers/Settings/withSettings';
/**
* Bill form.
*/
export default function BillForm() {
function BillForm({
// #withSettings
baseCurrency,
}) {
const { formatMessage } = useIntl();
const history = useHistory();
@@ -46,6 +50,7 @@ export default function BillForm() {
: {
...defaultBill,
entries: orderingLinesIndexes(defaultBill.entries),
currency_code: baseCurrency,
}),
}),
[bill],
@@ -142,3 +147,8 @@ export default function BillForm() {
</div>
);
}
export default compose(
withSettings(({ organizationSettings }) => ({
baseCurrency: organizationSettings?.baseCurrency,
})),
)(BillForm);

View File

@@ -11,15 +11,20 @@ export default function BillFormBody({ defaultBill }) {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<ItemsEntriesTable
entries={value}
onUpdateData={(entries) => {
form.setFieldValue('entries', entries);
setFieldValue('entries', entries);
}}
items={items}
errors={error}
linesNumber={4}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -16,6 +16,7 @@ import { useFormikContext } from 'formik';
export default function PaymentMadeEntriesTable({
onUpdateData,
entries,
currencyCode,
}) {
// Payment made inner context.
const { isNewEntriesFetching } = usePaymentMadeInnerContext();
@@ -24,7 +25,9 @@ export default function PaymentMadeEntriesTable({
const columns = usePaymentMadeEntriesTableColumns();
// Formik context.
const { values: { vendor_id } } = useFormikContext();
const {
values: { vendor_id },
} = useFormikContext();
// Handle update data.
const handleUpdateData = useCallback(
@@ -54,10 +57,11 @@ export default function PaymentMadeEntriesTable({
payload={{
errors: [],
updateData: handleUpdateData,
currencyCode,
}}
noResults={noResultsMessage}
footer={true}
/>
</CloudLoadingIndicator>
);
}
}

View File

@@ -29,6 +29,7 @@ import { defaultPaymentMade, transformToEditForm, ERRORS } from './utils';
function PaymentMadeForm({
// #withSettings
preferredPaymentAccount,
baseCurrency,
}) {
const history = useHistory();
const { formatMessage } = useIntl();
@@ -54,6 +55,7 @@ function PaymentMadeForm({
: {
...defaultPaymentMade,
payment_account_id: defaultTo(preferredPaymentAccount),
currency_code: baseCurrency,
entries: orderingLinesIndexes(defaultPaymentMade.entries),
}),
}),
@@ -157,9 +159,10 @@ function PaymentMadeForm({
}
export default compose(
withSettings(({ billPaymentSettings }) => ({
withSettings(({ billPaymentSettings, organizationSettings }) => ({
paymentNextNumber: billPaymentSettings?.next_number,
paymentNumberPrefix: billPaymentSettings?.number_prefix,
preferredPaymentAccount: parseInt(billPaymentSettings?.withdrawalAccount),
baseCurrency: organizationSettings?.baseCurrency,
})),
)(PaymentMadeForm);

View File

@@ -5,18 +5,23 @@ import { CLASSES } from 'common/classes';
import PaymentMadeEntriesTable from './PaymentMadeEntriesTable';
export default function PaymentMadeFormBody() {
return (
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
<PaymentMadeEntriesTable
{({
form: { setFieldValue, values },
field: { value },
meta: { error, touched },
}) => (
<PaymentMadeEntriesTable
entries={value}
onUpdateData={(newEntries) => {
form.setFieldValue('entries', newEntries);
setFieldValue('entries', newEntries);
}}
currencyCode={values.currency_code}
/>
)}
</FastField>
</div>
)
}
);
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { useIntl } from "react-intl";
import { useIntl } from 'react-intl';
import moment from 'moment';
import { Money } from 'components';
import { safeSumBy, formattedAmount } from 'utils';
@@ -10,7 +10,7 @@ function BillNumberAccessor(row) {
}
function IndexTableCell({ row: { index } }) {
return (<span>{index + 1}</span>);
return <span>{index + 1}</span>;
}
function BillDateCell({ value }) {
@@ -19,35 +19,34 @@ function BillDateCell({ value }) {
/**
* Balance footer cell.
*/
function AmountFooterCell({ rows }) {
function AmountFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.amount');
return <span>{ formattedAmount(total, 'USD') }</span>;
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Due amount footer cell.
*/
function DueAmountFooterCell({ rows }) {
function DueAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalDueAmount = safeSumBy(rows, 'original.due_amount');
return <span>{ formattedAmount(totalDueAmount, 'USD') }</span>;
return <span>{formattedAmount(totalDueAmount, currencyCode)}</span>;
}
/**
* Payment amount footer cell.
*/
function PaymentAmountFooterCell({ rows }) {
function PaymentAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalPaymentAmount = safeSumBy(rows, 'original.payment_amount');
return <span>{ formattedAmount(totalPaymentAmount, 'USD') }</span>;
return <span>{formattedAmount(totalPaymentAmount, currencyCode)}</span>;
}
/**
* Mobey table cell.
*/
function MoneyTableCell({ value }) {
return <Money amount={value} currency={"USD"} />
function MoneyTableCell({ row: { original }, value }) {
return <Money amount={value} currency={original.currency_code} />;
}
/**
* Payment made entries table columns
*/
@@ -63,7 +62,7 @@ export function usePaymentMadeEntriesTableColumns() {
width: 40,
disableResizing: true,
disableSortBy: true,
className: 'index'
className: 'index',
},
{
Header: formatMessage({ id: 'Date' }),
@@ -106,5 +105,5 @@ export function usePaymentMadeEntriesTableColumns() {
},
],
[formatMessage],
)
}
);
}

View File

@@ -12,6 +12,7 @@ export const defaultPaymentMadeEntry = {
currency_code:'',
id: null,
due_amount: null,
amount:''
};
// Default initial values of payment made.
@@ -46,5 +47,7 @@ export const transformToNewPageEntries = (entries) => {
return entries.map((entry) => ({
...transformToForm(entry, defaultPaymentMadeEntry),
payment_amount: '',
currency_code:entry.currency_code,
}));
}

View File

@@ -34,6 +34,7 @@ function EstimateForm({
estimateNextNumber,
estimateNumberPrefix,
estimateIncrementMode,
baseCurrency,
}) {
const { formatMessage } = useIntl();
const history = useHistory();
@@ -57,10 +58,11 @@ function EstimateForm({
? { ...transformToEditForm(estimate) }
: {
...defaultEstimate,
...(estimateIncrementMode) && ({
...(estimateIncrementMode && {
estimate_number: estimateNumber,
}),
entries: orderingLinesIndexes(defaultEstimate.entries),
currency_code: baseCurrency,
}),
}),
[estimate, estimateNumber, estimateIncrementMode],
@@ -101,7 +103,7 @@ function EstimateForm({
}
const form = {
...omit(values, ['estimate_number_manually', 'estimate_number']),
...(values.estimate_number_manually) && ({
...(values.estimate_number_manually && {
estimate_number: values.estimate_number,
}),
delivered: submitPayload.deliver,
@@ -175,9 +177,10 @@ function EstimateForm({
}
export default compose(
withSettings(({ estimatesSettings }) => ({
withSettings(({ estimatesSettings, organizationSettings }) => ({
estimateNextNumber: estimatesSettings?.nextNumber,
estimateNumberPrefix: estimatesSettings?.numberPrefix,
estimateIncrementMode: estimatesSettings?.autoIncrement,
baseCurrency: organizationSettings?.baseCurrency,
})),
)(EstimateForm);

View File

@@ -14,15 +14,20 @@ export default function EstimateFormItemsEntriesField() {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<ItemsEntriesTable
entries={value}
onUpdateData={(entries) => {
form.setFieldValue('entries', entries);
setFieldValue('entries', entries);
}}
items={items}
errors={error}
linesNumber={4}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -34,6 +34,7 @@ function InvoiceForm({
invoiceNextNumber,
invoiceNumberPrefix,
invoiceIncrementMode,
baseCurrency,
}) {
const { formatMessage } = useIntl();
const history = useHistory();
@@ -61,11 +62,12 @@ function InvoiceForm({
? transformToEditForm(invoice)
: {
...defaultInvoice,
...(invoiceIncrementMode) && ({
...(invoiceIncrementMode && {
invoice_no: invoiceNumber,
}),
entries: orderingLinesIndexes(defaultInvoice.entries),
...newInvoice,
currency_code: baseCurrency,
}),
}),
[invoice, newInvoice, invoiceNumber, invoiceIncrementMode],
@@ -91,7 +93,7 @@ function InvoiceForm({
}
const form = {
...omit(values, ['invoice_no', 'invoice_no_manually']),
...(values.invoice_no_manually) && ({
...(values.invoice_no_manually && {
invoice_no: values.invoice_no,
}),
delivered: submitPayload.deliver,
@@ -169,9 +171,10 @@ function InvoiceForm({
export default compose(
withDashboardActions,
withMediaActions,
withSettings(({ invoiceSettings }) => ({
withSettings(({ invoiceSettings, organizationSettings }) => ({
invoiceNextNumber: invoiceSettings?.nextNumber,
invoiceNumberPrefix: invoiceSettings?.numberPrefix,
invoiceIncrementMode: invoiceSettings?.incrementMode,
baseCurrency: organizationSettings?.baseCurrency,
})),
)(InvoiceForm);

View File

@@ -14,15 +14,20 @@ export default function InvoiceItemsEntriesEditorField() {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<ItemsEntriesTable
entries={value}
onUpdateData={(entries) => {
form.setFieldValue('entries', entries);
setFieldValue('entries', entries);
}}
items={items}
errors={error}
linesNumber={4}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -37,6 +37,7 @@ function PaymentReceiveForm({
paymentReceiveNextNumber,
paymentReceiveNumberPrefix,
paymentReceiveAutoIncrement,
baseCurrency,
}) {
const history = useHistory();
const { formatMessage } = useIntl();
@@ -68,6 +69,7 @@ function PaymentReceiveForm({
payment_receive_no: nextPaymentNumber,
deposit_account_id: defaultTo(preferredDepositAccount, ''),
}),
currency_code: baseCurrency,
}),
}),
[
@@ -199,11 +201,12 @@ function PaymentReceiveForm({
}
export default compose(
withSettings(({ paymentReceiveSettings }) => ({
withSettings(({ paymentReceiveSettings, organizationSettings }) => ({
paymentReceiveSettings,
paymentReceiveNextNumber: paymentReceiveSettings?.nextNumber,
paymentReceiveNumberPrefix: paymentReceiveSettings?.numberPrefix,
paymentReceiveAutoIncrement: paymentReceiveSettings?.autoIncrement,
preferredDepositAccount: paymentReceiveSettings?.depositAccount,
baseCurrency: organizationSettings?.baseCurrency,
})),
)(PaymentReceiveForm);

View File

@@ -11,12 +11,13 @@ export default function PaymentReceiveFormBody() {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value } }) => (
{({ form: { values, setFieldValue }, field: { value } }) => (
<PaymentReceiveItemsTable
entries={value}
onUpdateData={(newEntries) => {
form.setFieldValue('entries', newEntries);
setFieldValue('entries', newEntries);
}}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -15,6 +15,7 @@ import { compose, updateTableRow } from 'utils';
export default function PaymentReceiveItemsTable({
entries,
onUpdateData,
currencyCode
}) {
// Payment receive form context.
const {
@@ -52,6 +53,7 @@ export default function PaymentReceiveItemsTable({
payload={{
errors: [],
updateData: handleUpdateData,
currencyCode
}}
noResults={noResultsMessage}
footer={true}

View File

@@ -9,14 +9,14 @@ import { safeSumBy, formattedAmount } from 'utils';
* Invoice date cell.
*/
function InvoiceDateCell({ value }) {
return <span>{ moment(value).format('YYYY MMM DD') }</span>
return <span>{moment(value).format('YYYY MMM DD')}</span>;
}
/**
* Index table cell.
*/
function IndexCell({ row: { index } }) {
return (<span>{index + 1}</span>);
return <span>{index + 1}</span>;
}
/**
@@ -29,33 +29,32 @@ function InvNumberCellAccessor(row) {
/**
* Balance footer cell.
*/
function BalanceFooterCell({ rows }) {
function BalanceFooterCell({ payload: { currencyCode }, rows }) {
const total = safeSumBy(rows, 'original.amount');
return <span>{ formattedAmount(total, 'USD') }</span>;
return <span>{formattedAmount(total, currencyCode)}</span>;
}
/**
* Due amount footer cell.
*/
function DueAmountFooterCell({ rows }) {
function DueAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalDueAmount = safeSumBy(rows, 'original.due_amount');
return <span>{ formattedAmount(totalDueAmount, 'USD') }</span>;
return <span>{formattedAmount(totalDueAmount, currencyCode)}</span>;
}
/**
* Payment amount footer cell.
*/
function PaymentAmountFooterCell({ rows }) {
function PaymentAmountFooterCell({ payload: { currencyCode }, rows }) {
const totalPaymentAmount = safeSumBy(rows, 'original.payment_amount');
return <span>{ formattedAmount(totalPaymentAmount, 'USD') }</span>;
return <span>{formattedAmount(totalPaymentAmount, currencyCode)}</span>;
}
/**
* Mobey table cell.
*/
function MoneyTableCell({ value }) {
return <Money amount={value} currency={"USD"} />
function MoneyTableCell({ row: { original }, value }) {
return <Money amount={value} currency={original.currency_code} />;
}
function DateFooterCell() {
@@ -77,7 +76,7 @@ export const usePaymentReceiveEntriesColumns = () => {
width: 40,
disableResizing: true,
disableSortBy: true,
className: 'index'
className: 'index',
},
{
Header: formatMessage({ id: 'Date' }),
@@ -88,7 +87,7 @@ export const usePaymentReceiveEntriesColumns = () => {
disableSortBy: true,
disableResizing: true,
width: 250,
className: 'date'
className: 'date',
},
{
Header: formatMessage({ id: 'invocie_number' }),
@@ -125,5 +124,5 @@ export const usePaymentReceiveEntriesColumns = () => {
},
],
[formatMessage],
)
}
);
};

View File

@@ -50,6 +50,7 @@ export const transformInvoicesNewPageEntries = (invoices) => [
due_amount: invoice.due_amount,
date: invoice.invoice_date,
amount: invoice.balance,
currency_code:invoice.currency_code,
payment_amount: '',
invoice_no: invoice.invoice_no,
total_payment_amount: invoice.payment_amount,

View File

@@ -37,6 +37,7 @@ function ReceiptForm({
receiptNumberPrefix,
receiptAutoIncrement,
preferredDepositAccount,
baseCurrency,
}) {
const { formatMessage } = useIntl();
const history = useHistory();
@@ -67,6 +68,7 @@ function ReceiptForm({
}),
deposit_account_id: parseInt(preferredDepositAccount),
entries: orderingLinesIndexes(defaultReceipt.entries),
currency_code: baseCurrency,
}),
}),
[receipt, preferredDepositAccount, nextReceiptNumber, receiptAutoIncrement],
@@ -105,8 +107,9 @@ function ReceiptForm({
}
const form = {
...omit(values, ['receipt_number_manually', 'receipt_number']),
...(values.receipt_number_manually) && ({
...(values.receipt_number_manually && {
receipt_number: values.receipt_number,
currency_code: baseCurrency,
}),
closed: submitPayload.status,
entries: entries.map((entry) => ({ ...omit(entry, ['total']) })),
@@ -182,10 +185,11 @@ function ReceiptForm({
export default compose(
withDashboardActions,
withSettings(({ receiptSettings }) => ({
withSettings(({ receiptSettings, organizationSettings }) => ({
receiptNextNumber: receiptSettings?.nextNumber,
receiptNumberPrefix: receiptSettings?.numberPrefix,
receiptAutoIncrement: receiptSettings?.autoIncrement,
preferredDepositAccount: receiptSettings?.preferredDepositAccount,
baseCurrency: organizationSettings?.baseCurrency,
})),
)(ReceiptForm);

View File

@@ -11,15 +11,20 @@ export default function ReceiptItemsEntriesEditor({ defaultReceipt }) {
return (
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
<FastField name={'entries'}>
{({ form, field: { value }, meta: { error, touched } }) => (
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<ItemsEntriesTable
entries={value}
onUpdateData={(entries) => {
form.setFieldValue('entries', entries);
setFieldValue('entries', entries);
}}
items={items}
errors={error}
linesNumber={4}
currencyCode={values.currency_code}
/>
)}
</FastField>

View File

@@ -94,6 +94,7 @@ function VendorForm({
const initialValues = useMemo(
() => ({
...defaultInitialValues,
currency_code: baseCurrency,
...transformToForm(vendor, defaultInitialValues),
...transformToForm(contactDuplicate, defaultInitialValues),
}),

View File

@@ -324,7 +324,9 @@ export default class ItemsController extends BaseController {
try {
const storedItem = await this.itemsService.getItem(tenantId, itemId);
return res.status(200).send({ item: storedItem });
return res.status(200).send({
item: this.transfromToResponse(storedItem)
});
} catch (error) {
next(error);
}
@@ -356,7 +358,7 @@ export default class ItemsController extends BaseController {
} = await this.itemsService.itemsList(tenantId, filter);
return res.status(200).send({
items,
items: this.transfromToResponse(items),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
@@ -390,7 +392,7 @@ export default class ItemsController extends BaseController {
filter
);
return res.status(200).send({
items,
items: this.transfromToResponse(items),
});
} catch (error) {
next(error);

View File

@@ -6,6 +6,7 @@ exports.up = function(knex) {
table.string('reference').index();
table.string('journal_type').index();
table.decimal('amount', 13, 3);
table.string('currency_code', 3);
table.date('date').index();
table.string('description');
table.date('published_at').index();

View File

@@ -9,6 +9,7 @@ export interface IManualJournal {
journalType: string;
reference: string;
amount: number;
currencyCode: string;
publishedAt: Date | null;
description: string;
userId: number;

View File

@@ -1,6 +1,6 @@
import { Model } from 'objection';
import TenantModel from 'models/TenantModel';
import { query } from 'winston';
import { formatNumber } from 'utils';
export default class ManualJournal extends TenantModel {
/**
@@ -21,7 +21,14 @@ export default class ManualJournal extends TenantModel {
* Virtual attributes.
*/
static get virtualAttributes() {
return ['isPublished'];
return ['isPublished', 'amountFormatted'];
}
/**
* Retrieve the amount formatted value.
*/
get amountFormatted() {
return formatNumber(this.amount, { currencyCode: this.currencyCode });
}
/**

View File

@@ -22,6 +22,7 @@ import {
ACCOUNT_TYPE,
} from 'data/AccountTypes';
import { ERRORS } from './constants';
import { formatNumber } from 'utils';
@Service()
export default class ItemsService implements IItemsService {
@@ -289,12 +290,12 @@ export default class ItemsService implements IItemsService {
}
/**
* Validate the item inventory account whether modified and item
* Validate the item inventory account whether modified and item
* has assocaited inventory transactions.
* @param {numnber} tenantId
* @param {IItem} oldItem
* @param {IItemDTO} newItemDTO
* @returns
* @param {numnber} tenantId
* @param {IItem} oldItem
* @param {IItemDTO} newItemDTO
* @returns
*/
async validateItemInvnetoryAccountModified(
tenantId: number,
@@ -418,11 +419,7 @@ export default class ItemsService implements IItemsService {
);
}
await this.validateItemInvnetoryAccountModified(
tenantId,
oldItem,
itemDTO
);
await this.validateItemInvnetoryAccountModified(tenantId, oldItem, itemDTO);
const newItem = await Item.query().patchAndFetchById(itemId, {
...itemModel,
@@ -525,7 +522,7 @@ export default class ItemsService implements IItemsService {
if (!item) {
throw new ServiceError(ERRORS.NOT_FOUND);
}
return item;
return this.transformItemToResponse(tenantId, item);
}
/**
@@ -540,7 +537,7 @@ export default class ItemsService implements IItemsService {
Item,
itemsFilter
);
const { results, pagination } = await Item.query()
const { results: items, pagination } = await Item.query()
.onBuild((builder) => {
builder.withGraphFetched('inventoryAccount');
builder.withGraphFetched('sellAccount');
@@ -551,6 +548,10 @@ export default class ItemsService implements IItemsService {
})
.pagination(itemsFilter.page - 1, itemsFilter.pageSize);
const results = items.map((item) =>
this.transformItemToResponse(tenantId, item)
);
return {
items: results,
pagination,
@@ -583,7 +584,7 @@ export default class ItemsService implements IItemsService {
builder.where('name', 'LIKE', `%${itemsFilter.keyword}%`);
}
});
return items;
return items.map((item) => this.transformItemToResponse(tenantId, item));
}
/**
@@ -630,4 +631,24 @@ export default class ItemsService implements IItemsService {
throw new ServiceError(ERRORS.ITEM_HAS_ASSOCIATED_INVENTORY_ADJUSTMENT);
}
}
/**
* Transformes the item object to response.
* @param {number} tenantId -
* @param {IItem} item -
* @returns
*/
private transformItemToResponse(tenantId: number, item: IItem) {
// Settings tenant service.
const settings = this.tenancy.settings(tenantId);
const currencyCode = settings.get({
group: 'organization', key: 'base_currency',
});
return {
...item,
sellPriceFormatted: formatNumber(item.sellPrice, { currencyCode }),
costPriceFormatted: formatNumber(item.costPrice, { currencyCode }),
};
}
}

View File

@@ -344,6 +344,11 @@ export default class ManualJournalsService implements IManualJournalsService {
const journalNumber = manualJournalDTO.journalNumber || autoNextNumber;
// Settings tenant service.
const settings = this.tenancy.settings(tenantId);
const currencyCode = settings.get({
group: 'organization', key: 'base_currency',
});
// Validate manual journal number require.
this.validateJournalNoRequire(journalNumber);
@@ -353,6 +358,7 @@ export default class ManualJournalsService implements IManualJournalsService {
? { publishedAt: moment().toMySqlDateTime() }
: {}),
amount,
currencyCode,
date,
journalNumber,
userId: authorizedUser.id,