mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-12 10:50:31 +00:00
252 lines
6.3 KiB
TypeScript
252 lines
6.3 KiB
TypeScript
// @ts-nocheck
|
|
import { useMemo } from 'react';
|
|
import intl from 'react-intl-universal';
|
|
import { Intent } from '@blueprintjs/core';
|
|
import { defaultTo, includes } from 'lodash';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { AppToaster } from '@/components';
|
|
import {
|
|
transformToForm,
|
|
transformTableStateToQuery,
|
|
defaultFastFieldShouldUpdate,
|
|
} from '@/utils';
|
|
import { useSettingsSelector } from '@/hooks/state';
|
|
import { transformItemFormData } from './ItemForm.schema';
|
|
import { useWatch } from '@/hooks/utils';
|
|
|
|
const defaultInitialValues = {
|
|
active: 1,
|
|
name: '',
|
|
type: 'service',
|
|
code: '',
|
|
cost_price: '',
|
|
sell_price: '',
|
|
cost_account_id: '',
|
|
sell_account_id: '',
|
|
inventory_account_id: '',
|
|
category_id: '',
|
|
sellable: 1,
|
|
purchasable: true,
|
|
sell_description: '',
|
|
purchase_description: '',
|
|
};
|
|
|
|
/**
|
|
* Initial values in create and edit mode.
|
|
*/
|
|
export const useItemFormInitialValues = (item, initialValues) => {
|
|
const { items: itemsSettings } = useSettingsSelector();
|
|
|
|
return useMemo(
|
|
() => ({
|
|
...defaultInitialValues,
|
|
cost_account_id: defaultTo(itemsSettings?.preferredCostAccount, ''),
|
|
sell_account_id: defaultTo(itemsSettings?.preferredSellAccount, ''),
|
|
inventory_account_id: defaultTo(
|
|
itemsSettings?.preferredInventoryAccount,
|
|
'',
|
|
),
|
|
/**
|
|
* We only care about the fields in the form. Previously unfilled optional
|
|
* values such as `notes` come back from the API as null, so remove those
|
|
* as well.
|
|
*/
|
|
...transformToForm(
|
|
transformItemFormData(item, defaultInitialValues),
|
|
defaultInitialValues,
|
|
),
|
|
...initialValues,
|
|
}),
|
|
[item, itemsSettings, initialValues],
|
|
);
|
|
};
|
|
|
|
export const transitionItemTypeKeyToLabel = (itemTypeKey) => {
|
|
const table = {
|
|
service: intl.get('service'),
|
|
inventory: intl.get('inventory'),
|
|
};
|
|
return typeof table[itemTypeKey] === 'string' ? table[itemTypeKey] : '';
|
|
};
|
|
|
|
// handle delete errors.
|
|
export const handleDeleteErrors = (errors) => {
|
|
if (
|
|
errors.find((error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTINS')
|
|
) {
|
|
AppToaster.show({
|
|
message: intl.get('the_item_has_associated_transactions'),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
|
|
if (
|
|
errors.find(
|
|
(error) => error.type === 'ITEM_HAS_ASSOCIATED_INVENTORY_ADJUSTMENT',
|
|
)
|
|
) {
|
|
AppToaster.show({
|
|
message: intl.get(
|
|
'you_could_not_delete_item_that_has_associated_inventory_adjustments_transacions',
|
|
),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
if (
|
|
errors.find(
|
|
(error) => error.type === 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS',
|
|
)
|
|
) {
|
|
AppToaster.show({
|
|
message: intl.get(
|
|
'cannot_change_item_type_to_inventory_with_item_has_associated_transactions',
|
|
),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
if (
|
|
errors.find((error) => error.type === 'ITEM_HAS_ASSOCIATED_TRANSACTIONS')
|
|
) {
|
|
AppToaster.show({
|
|
message: intl.get('item.error.you_could_not_delete_item_has_associated'),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Detarmines accounts fast field should update.
|
|
*/
|
|
export const accountsFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.items !== oldProps.items ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Detarmines categories fast field should update.
|
|
*/
|
|
export const categoriesFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.categories !== oldProps.categories ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Sell price fast field should update.
|
|
*/
|
|
export const sellPriceFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.sellable !== oldProps.sellable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Sell account fast field should update.
|
|
*/
|
|
export const sellAccountFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.items !== oldProps.items ||
|
|
newProps.sellable !== oldProps.sellable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Sell description fast field should update.
|
|
*/
|
|
export const sellDescriptionFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.sellable !== oldProps.sellable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
export const costAccountFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.accounts !== oldProps.accounts ||
|
|
newProps.purchasable !== oldProps.purchasable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
export const costPriceFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.purchasable !== oldProps.purchasable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
export const purchaseDescFieldShouldUpdate = (newProps, oldProps) => {
|
|
return (
|
|
newProps.purchasable !== oldProps.purchasable ||
|
|
defaultFastFieldShouldUpdate(newProps, oldProps)
|
|
);
|
|
};
|
|
|
|
export function transformItemsTableState(tableState) {
|
|
return {
|
|
...transformTableStateToQuery(tableState),
|
|
inactive_mode: tableState.inactiveMode,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Transform API errors.
|
|
*/
|
|
export const transformSubmitRequestErrors = (error) => {
|
|
const {
|
|
response: {
|
|
data: { errors },
|
|
},
|
|
} = error;
|
|
const fields = {};
|
|
|
|
if (errors.find((e) => e.type === 'ITEM.NAME.ALREADY.EXISTS')) {
|
|
fields.name = intl.get('the_name_used_before');
|
|
}
|
|
if (errors.find((e) => e.type === 'INVENTORY_ACCOUNT_CANNOT_MODIFIED')) {
|
|
AppToaster.show({
|
|
message: intl.get('cannot_change_item_inventory_account'),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
if (
|
|
errors.find(
|
|
(e) => e.type === 'TYPE_CANNOT_CHANGE_WITH_ITEM_HAS_TRANSACTIONS',
|
|
)
|
|
) {
|
|
AppToaster.show({
|
|
message: intl.get(
|
|
'item.error.type_cannot_change_with_item_has_transactions',
|
|
),
|
|
intent: Intent.DANGER,
|
|
});
|
|
}
|
|
return fields;
|
|
};
|
|
|
|
/**
|
|
* Watches and handles item response not found error.
|
|
* @param {*} itemQuery
|
|
*/
|
|
export function useWatchItemError(itemQuery) {
|
|
const { error, isError } = itemQuery;
|
|
|
|
// History context.
|
|
const history = useHistory();
|
|
|
|
useWatch(() => {
|
|
if (isError && includes([400, 404], error.response.status)) {
|
|
AppToaster.show({
|
|
message: 'The given item not found.',
|
|
intent: Intent.DANGER,
|
|
});
|
|
history.push('/items');
|
|
}
|
|
}, isError);
|
|
}
|