Skip to content

Commit

Permalink
refactor: improve management of fetch for product indicators (#828)
Browse files Browse the repository at this point in the history
* RM#87894
  • Loading branch information
lme-axelor committed Dec 5, 2024
1 parent baaf000 commit 96d0672
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 147 deletions.
6 changes: 6 additions & 0 deletions changelogs/unreleased/87894.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"title": "Indicators: move logic to fetch available stock to card components",
"type": "refactor",
"packages": "stock",
"description": "There was a performance problem on the screens requiring the product indicators. To solve this slow performance problem, product indicators are now retrieved from the card component in the background. The old way of working retrieved the indicators for all the products in the list each time they were updated, before displaying them, which is rather cumbersome and shouldn't be used. The functions concerned have been removed. "
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,70 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React from 'react';
import React, {useEffect, useRef, useState} from 'react';
import {StyleSheet} from 'react-native';
import {ObjectCard, useThemeColor} from '@axelor/aos-mobile-ui';
import {useMetafileUri, useTranslator} from '@axelor/aos-mobile-core';
import {
useMetafileUri,
useSelector,
useTranslator,
} from '@axelor/aos-mobile-core';
import {getProductStockIndicators} from '../../../../api';

interface ProductCardProps {
style?: any;
productId: number;
productVersion: number;
name: string;
code: string;
picture: any;
availableStock: number | null | undefined;
onPress: () => void;
}

const ProductCard = ({
style,
productId,
productVersion,
name,
code,
picture,
availableStock,
onPress,
}: ProductCardProps) => {
const Colors = useThemeColor();
const I18n = useTranslator();
const formatMetaFile = useMetafileUri();
const isMounted = useRef(true);

const {activeCompany} = useSelector((state: any) => state.user.user);

const [availableStock, setAvailableStock] = useState(null);

useEffect(() => {
isMounted.current = true;

if (productId != null) {
getProductStockIndicators({
productId: productId,
version: productVersion,
companyId: activeCompany?.id,
stockLocationId: null,
})
.then((res: any) => {
if (isMounted.current) {
setAvailableStock(res?.data?.object?.availableStock);
}
})
.catch(() => {
if (isMounted.current) {
setAvailableStock(null);
}
});
}

return () => {
isMounted.current = false;
};
}, [activeCompany?.id, productId, productVersion]);

return (
<ObjectCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, {useCallback} from 'react';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {StyleSheet} from 'react-native';
import {ObjectCard, useDigitFormat, useThemeColor} from '@axelor/aos-mobile-ui';
import {useMetafileUri, useTranslator} from '@axelor/aos-mobile-core';
import Product from '../../../../types/product';
import {
getProductStockIndicators,
fetchVariantAttributes,
} from '../../../../api';

interface ProductAttribut {
attrName: string;
Expand All @@ -33,35 +37,90 @@ interface ProductVariantCardProps {
style?: any;
name: string;
code: string;
attributesList: {attributes: ProductAttribut[]};
productId: number;
productVersion: number;
availabiltyData: {stockLocationId: number; companyId: number};
picture?: any;
stockAvailability: number;
onPress: () => void;
}

const ProductVariantCard = ({
style,
name,
code,
attributesList,
productId,
productVersion,
availabiltyData,
picture,
stockAvailability,
onPress,
}: ProductVariantCardProps) => {
const Colors = useThemeColor();
const I18n = useTranslator();
const formatMetaFile = useMetafileUri();
const formatNumber = useDigitFormat();
const isMounted = useRef(true);

const [attributes, setAttributesList] = useState<
ProductAttribut[] | undefined
>();
const [availableStock, setAvailableStock] = useState(null);

useEffect(() => {
isMounted.current = true;

return () => {
isMounted.current = false;
};
}, []);

useEffect(() => {
if (productId != null) {
fetchVariantAttributes({
productVariantId: productId,
version: productVersion,
})
.then((res: any) => {
if (isMounted.current) {
setAttributesList(res?.data?.object?.attributes);
}
})
.catch(() => {
if (isMounted.current) {
setAttributesList(null);
}
});
}
}, [availabiltyData, productId, productVersion]);

useEffect(() => {
if (productId != null) {
getProductStockIndicators({
productId: productId,
version: productVersion,
...availabiltyData,
})
.then((res: any) => {
if (isMounted.current) {
setAvailableStock(res?.data?.object?.availableStock);
}
})
.catch(() => {
if (isMounted.current) {
setAvailableStock(null);
}
});
}
}, [availabiltyData, productId, productVersion]);

const renderAttrItems = useCallback(() => {
if (!Array.isArray(attributesList?.attributes)) {
if (!Array.isArray(attributes)) {
return null;
}

let items = [];

for (let index = 0; index < attributesList?.attributes.length; index++) {
const attr = attributesList?.attributes[index];
for (let index = 0; index < attributes.length; index++) {
const attr = attributes[index];

if (attr != null) {
items.push({
Expand All @@ -80,7 +139,7 @@ const ProductVariantCard = ({
}

return items?.length > 0 ? {items} : null;
}, [I18n, attributesList?.attributes, formatNumber]);
}, [I18n, attributes, formatNumber]);

return (
<ObjectCard
Expand All @@ -104,11 +163,10 @@ const ProductVariantCard = ({
items: [
{
displayText:
stockAvailability > 0
availableStock > 0
? I18n.t('Stock_Available')
: I18n.t('Stock_Unavailable'),
color:
stockAvailability > 0 ? Colors.primaryColor : Colors.errorColor,
color: availableStock > 0 ? Colors.successColor : Colors.errorColor,
},
],
}}
Expand Down
6 changes: 1 addition & 5 deletions packages/apps/stock/src/features/asyncFunctions-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export {
} from './inventorySlice';
export {filterClients, filterSuppliers} from './partnerSlice';
export {
fetchProductsAvailability,
fetchProductDistribution,
fetchProductIndicators,
} from './productIndicatorsSlice';
Expand All @@ -65,10 +64,7 @@ export {
updateProductLocker,
} from './productSlice';
export {searchProductTrackingNumber} from './productTrackingNumberSlice';
export {
fetchProductsAttributes,
fetchProductVariants,
} from './productVariantSlice';
export {fetchProductVariants} from './productVariantSlice';
export {getRacks} from './racksListSlice';
export {
fetchStockConfig,
Expand Down
29 changes: 0 additions & 29 deletions packages/apps/stock/src/features/productIndicatorsSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,6 @@ async function fetchData(data, {getState}) {
return await getProductAvailabilty(data, {getState});
}

export const fetchProductsAvailability = createAsyncThunk(
'product/fetchProductsAvailability',
async function (data, {getState}) {
let promises = [];
data.productList.forEach(product => {
promises.push(
fetchData(
{
productId: product.id,
companyId: data.companyId,
stockLocationId: data.stockLocationId,
version: product.version,
},
{getState},
),
);
});
return Promise.all(promises);
},
);

export const fetchProductDistribution = createAsyncThunk(
'product/fetchProductDistribution',
async function (data, {getState}) {
Expand All @@ -93,7 +72,6 @@ const initialState = {
loading: false,
loadingProductIndicators: false,
productIndicators: {},
listAvailabilty: [],
listAvailabiltyDistribution: [],
};

Expand All @@ -108,13 +86,6 @@ const productIndicators = createSlice({
state.loadingProductIndicators = false;
state.productIndicators = action.payload;
});
builder.addCase(fetchProductsAvailability.pending, state => {
state.loading = true;
});
builder.addCase(fetchProductsAvailability.fulfilled, (state, action) => {
state.loading = false;
state.listAvailabilty = action.payload;
});
builder.addCase(fetchProductDistribution.pending, state => {
state.loading = true;
});
Expand Down
42 changes: 1 addition & 41 deletions packages/apps/stock/src/features/productVariantSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
generateInifiniteScrollCases,
handlerApiCall,
} from '@axelor/aos-mobile-core';
import {fetchVariantAttributes, fetchVariants} from '../api/product-api';
import {fetchVariants} from '../api/product-api';

export const fetchProductVariants = createAsyncThunk(
'product/fetchProductVariant',
Expand All @@ -36,44 +36,11 @@ export const fetchProductVariants = createAsyncThunk(
},
);

var getProductAttributes = async (data, {getState}) => {
return handlerApiCall({
fetchFunction: fetchVariantAttributes,
data,
action: 'Stock_SliceAction_FetchProductVariantAttributes',
getState,
responseOptions: {isArrayResponse: true},
});
};

async function fetchData(data, {getState}) {
return await getProductAttributes(data, {getState});
}

export const fetchProductsAttributes = createAsyncThunk(
'product/fetchProductsAttributes',
async function (data, {getState}) {
let promises = [];
data.productList.forEach(product => {
promises.push(
fetchData(
{productVariantId: product.id, version: product.version},
{getState},
),
);
});
return Promise.all(promises);
},
);

const initialState = {
loadingProductList: false,
moreLoading: false,
isListEnd: false,
productListVariables: [],

loading: false,
listProductsAttributes: [],
};

const productSlice = createSlice({
Expand All @@ -86,13 +53,6 @@ const productSlice = createSlice({
isListEnd: 'isListEnd',
list: 'productListVariables',
});
builder.addCase(fetchProductsAttributes.pending, (state, action) => {
state.loading = true;
});
builder.addCase(fetchProductsAttributes.fulfilled, (state, action) => {
state.loading = false;
state.listProductsAttributes = action.payload;
});
},
});

Expand Down
Loading

0 comments on commit 96d0672

Please sign in to comment.