mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 07:40:32 +00:00
fix: converting API body attributes empty strings to null.
This commit is contained in:
@@ -17,11 +17,6 @@ import MakeJournalEntriesField from './MakeJournalEntriesField';
|
|||||||
import MakeJournalNumberWatcher from './MakeJournalNumberWatcher';
|
import MakeJournalNumberWatcher from './MakeJournalNumberWatcher';
|
||||||
import MakeJournalFormFooter from './MakeJournalFormFooter';
|
import MakeJournalFormFooter from './MakeJournalFormFooter';
|
||||||
|
|
||||||
import {
|
|
||||||
CreateMakeJournalFormSchema,
|
|
||||||
EditMakeJournalFormSchema,
|
|
||||||
} from './MakeJournalEntriesForm.schema';
|
|
||||||
|
|
||||||
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
import withJournalsActions from 'containers/Accounting/withJournalsActions';
|
||||||
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
import withManualJournalDetail from 'containers/Accounting/withManualJournalDetail';
|
||||||
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
import withAccountsActions from 'containers/Accounts/withAccountsActions';
|
||||||
@@ -201,11 +196,11 @@ function MakeJournalEntriesForm({
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (isNewMode) {
|
if (isNewMode) {
|
||||||
|
requestMakeJournalEntries(form).then(handleSuccess).catch(handleError);
|
||||||
|
} else {
|
||||||
requestEditManualJournal(manualJournal.id, form)
|
requestEditManualJournal(manualJournal.id, form)
|
||||||
.then(handleSuccess)
|
.then(handleSuccess)
|
||||||
.catch(handleError);
|
.catch(handleError);
|
||||||
} else {
|
|
||||||
requestMakeJournalEntries(form).then(handleSuccess).catch(handleError);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
import * as Yup from 'yup';
|
|
||||||
import { formatMessage } from 'services/intl';
|
|
||||||
import { DATATYPES_LENGTH } from 'common/dataTypes';
|
|
||||||
|
|
||||||
const Schema = Yup.object().shape({
|
|
||||||
journal_number: Yup.string()
|
|
||||||
// .required()
|
|
||||||
.min(1)
|
|
||||||
.max(DATATYPES_LENGTH.STRING)
|
|
||||||
.label(formatMessage({ id: 'journal_number_' })),
|
|
||||||
journal_type: Yup.string()
|
|
||||||
.required()
|
|
||||||
.min(1)
|
|
||||||
.max(DATATYPES_LENGTH.STRING)
|
|
||||||
.label(formatMessage({ id: 'journal_type' })),
|
|
||||||
date: Yup.date()
|
|
||||||
.required()
|
|
||||||
.label(formatMessage({ id: 'date' })),
|
|
||||||
currency_code: Yup.string().max(3),
|
|
||||||
reference: Yup.string().nullable().min(1).max(DATATYPES_LENGTH.STRING),
|
|
||||||
description: Yup.string().min(1).max(DATATYPES_LENGTH.STRING),
|
|
||||||
status: Yup.boolean(),
|
|
||||||
entries: Yup.array().of(
|
|
||||||
Yup.object().shape({
|
|
||||||
credit: Yup.number().decimalScale(13).nullable(),
|
|
||||||
debit: Yup.number().decimalScale(13).nullable(),
|
|
||||||
account_id: Yup.number()
|
|
||||||
.nullable()
|
|
||||||
.when(['credit', 'debit'], {
|
|
||||||
is: (credit, debit) => credit || debit,
|
|
||||||
then: Yup.number().required(),
|
|
||||||
}),
|
|
||||||
contact_id: Yup.number().nullable(),
|
|
||||||
contact_type: Yup.string().nullable(),
|
|
||||||
note: Yup.string().max(DATATYPES_LENGTH.TEXT).nullable(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CreateMakeJournalFormSchema = Schema;
|
|
||||||
export const EditMakeJournalFormSchema = Schema;
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Intent, Button } from '@blueprintjs/core';
|
import { Intent, Button } from '@blueprintjs/core';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { FormattedMessage as T } from 'react-intl';
|
import { FormattedMessage as T } from 'react-intl';
|
||||||
import { saveInvoke } from 'utils';
|
import { saveInvoke } from 'utils';
|
||||||
@@ -11,6 +12,8 @@ export default function MakeJournalFloatingAction({
|
|||||||
onCancelClick,
|
onCancelClick,
|
||||||
manualJournalId,
|
manualJournalId,
|
||||||
}) {
|
}) {
|
||||||
|
const { submitForm } = useFormikContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
<div className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||||
<Button
|
<Button
|
||||||
@@ -18,6 +21,7 @@ export default function MakeJournalFloatingAction({
|
|||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
name={'save'}
|
name={'save'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
submitForm();
|
||||||
saveInvoke(onSubmitClick, { publish: true, redirect: true });
|
saveInvoke(onSubmitClick, { publish: true, redirect: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -29,8 +29,10 @@
|
|||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"crypto-random-string": "^3.2.0",
|
"crypto-random-string": "^3.2.0",
|
||||||
"csurf": "^1.10.0",
|
"csurf": "^1.10.0",
|
||||||
|
"deep-map": "^2.0.0",
|
||||||
"dotenv": "^8.1.0",
|
"dotenv": "^8.1.0",
|
||||||
"errorhandler": "^1.5.1",
|
"errorhandler": "^1.5.1",
|
||||||
|
"es6-weak-map": "^2.0.3",
|
||||||
"esm": "^3.2.25",
|
"esm": "^3.2.25",
|
||||||
"event-dispatch": "^0.4.1",
|
"event-dispatch": "^0.4.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
import { convertEmptyStringsToNull } from 'utils';
|
import deepMap from 'deep-map';
|
||||||
|
import { convertEmptyStringToNull } from 'utils';
|
||||||
|
|
||||||
|
function convertEmptyStringsToNull(data) {
|
||||||
|
return deepMap(data, (value) => convertEmptyStringToNull(value));
|
||||||
|
}
|
||||||
|
|
||||||
export default (req: Request, res: Response, next: NextFunction) => {
|
export default (req: Request, res: Response, next: NextFunction) => {
|
||||||
const transfomedBody = convertEmptyStringsToNull(req.body);
|
const transfomedBody = convertEmptyStringsToNull(req.body);
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ const getDefinedOptions = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDefinedOption = (key, group) => {
|
const getDefinedOption = (key, group) => {
|
||||||
return definedOptions?.[group]?.find(option => option.key == key);
|
return definedOptions?.[group]?.find((option) => option.key == key);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isDefinedOptionConfigurable = (key, group) => {
|
const isDefinedOptionConfigurable = (key, group) => {
|
||||||
@@ -179,30 +179,36 @@ const isDefinedOptionConfigurable = (key, group) => {
|
|||||||
return definedOption?.config || false;
|
return definedOption?.config || false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const entriesAmountDiff = (newEntries, oldEntries, amountAttribute, idAttribute) => {
|
const entriesAmountDiff = (
|
||||||
|
newEntries,
|
||||||
|
oldEntries,
|
||||||
|
amountAttribute,
|
||||||
|
idAttribute
|
||||||
|
) => {
|
||||||
const oldEntriesTable = _.chain(oldEntries)
|
const oldEntriesTable = _.chain(oldEntries)
|
||||||
.groupBy(idAttribute)
|
.groupBy(idAttribute)
|
||||||
.mapValues((group) => (_.sumBy(group, amountAttribute) || 0))
|
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return _.chain(newEntries)
|
return _.chain(newEntries)
|
||||||
.groupBy(idAttribute)
|
.groupBy(idAttribute)
|
||||||
.mapValues((group) => (_.sumBy(group, amountAttribute) || 0))
|
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
||||||
.mapValues((value, key) => value - (oldEntriesTable[key] || 0))
|
.mapValues((value, key) => value - (oldEntriesTable[key] || 0))
|
||||||
.mapValues((value, key) => ({ [idAttribute]: key, [amountAttribute]: value }))
|
.mapValues((value, key) => ({
|
||||||
|
[idAttribute]: key,
|
||||||
|
[amountAttribute]: value,
|
||||||
|
}))
|
||||||
.filter((entry) => entry[amountAttribute] != 0)
|
.filter((entry) => entry[amountAttribute] != 0)
|
||||||
.values()
|
.values()
|
||||||
.value();
|
.value();
|
||||||
};
|
};
|
||||||
|
|
||||||
const convertEmptyStringsToNull = (obj) => {
|
const convertEmptyStringToNull = (value) => {
|
||||||
return _.mapValues(obj, (value, key) => {
|
return typeof value === 'string'
|
||||||
return typeof value === 'string' ?
|
? value.trim() === ''
|
||||||
value.trim() === '' ?
|
? null
|
||||||
null :
|
: value
|
||||||
value :
|
: value;
|
||||||
value;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -218,11 +224,9 @@ export {
|
|||||||
getTotalDeep,
|
getTotalDeep,
|
||||||
applyMixins,
|
applyMixins,
|
||||||
formatDateFields,
|
formatDateFields,
|
||||||
|
|
||||||
isDefinedOptionConfigurable,
|
isDefinedOptionConfigurable,
|
||||||
getDefinedOption,
|
getDefinedOption,
|
||||||
getDefinedOptions,
|
getDefinedOptions,
|
||||||
|
|
||||||
entriesAmountDiff,
|
entriesAmountDiff,
|
||||||
convertEmptyStringsToNull,
|
convertEmptyStringToNull,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user