Add batch price retrieval for products in region
- Implemented a new endpoint to fetch prices for multiple products in a specified region in a single request, improving efficiency. - Added validation for input parameters to ensure proper data handling. - Updated the FalukantService to calculate prices based on knowledge factors and worth percentages for each product. - Modified the frontend to utilize the new batch endpoint, optimizing the loading of product prices.
This commit is contained in:
@@ -162,6 +162,18 @@ class FalukantController {
|
|||||||
}
|
}
|
||||||
return this.service.getProductPriceInRegion(userId, productId, regionId);
|
return this.service.getProductPriceInRegion(userId, productId, regionId);
|
||||||
});
|
});
|
||||||
|
this.getProductPricesInRegionBatch = this._wrapWithUser((userId, req) => {
|
||||||
|
const productIds = req.query.productIds;
|
||||||
|
const regionId = parseInt(req.query.regionId, 10);
|
||||||
|
if (!productIds || Number.isNaN(regionId)) {
|
||||||
|
throw new Error('productIds (comma-separated) and regionId are required');
|
||||||
|
}
|
||||||
|
const productIdArray = productIds.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !Number.isNaN(id));
|
||||||
|
if (productIdArray.length === 0) {
|
||||||
|
throw new Error('At least one valid productId is required');
|
||||||
|
}
|
||||||
|
return this.service.getProductPricesInRegionBatch(userId, productIdArray, regionId);
|
||||||
|
});
|
||||||
this.getProductPricesInCities = this._wrapWithUser((userId, req) => {
|
this.getProductPricesInCities = this._wrapWithUser((userId, req) => {
|
||||||
const productId = parseInt(req.query.productId, 10);
|
const productId = parseInt(req.query.productId, 10);
|
||||||
const currentPrice = parseFloat(req.query.currentPrice);
|
const currentPrice = parseFloat(req.query.currentPrice);
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ router.get('/politics/open', falukantController.getOpenPolitics);
|
|||||||
router.post('/politics/open', falukantController.applyForElections);
|
router.post('/politics/open', falukantController.applyForElections);
|
||||||
router.get('/cities', falukantController.getRegions);
|
router.get('/cities', falukantController.getRegions);
|
||||||
router.get('/products/price-in-region', falukantController.getProductPriceInRegion);
|
router.get('/products/price-in-region', falukantController.getProductPriceInRegion);
|
||||||
|
router.get('/products/prices-in-region-batch', falukantController.getProductPricesInRegionBatch);
|
||||||
router.get('/products/prices-in-cities', falukantController.getProductPricesInCities);
|
router.get('/products/prices-in-cities', falukantController.getProductPricesInCities);
|
||||||
router.get('/branches/:branchId/taxes', falukantController.getBranchTaxes);
|
router.get('/branches/:branchId/taxes', falukantController.getBranchTaxes);
|
||||||
router.get('/vehicles/types', falukantController.getVehicleTypes);
|
router.get('/vehicles/types', falukantController.getVehicleTypes);
|
||||||
|
|||||||
@@ -5133,6 +5133,57 @@ class FalukantService extends BaseService {
|
|||||||
return regions;
|
return regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getProductPricesInRegionBatch(hashedUserId, productIds, regionId) {
|
||||||
|
const user = await this.getFalukantUserByHashedId(hashedUserId);
|
||||||
|
const character = await FalukantCharacter.findOne({ where: { userId: user.id } });
|
||||||
|
if (!character) {
|
||||||
|
throw new Error(`No FalukantCharacter found for user with id ${user.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(productIds) || productIds.length === 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hole alle Produkte auf einmal
|
||||||
|
const products = await ProductType.findAll({
|
||||||
|
where: { id: { [Op.in]: productIds } }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hole alle Knowledge-Werte auf einmal
|
||||||
|
const knowledges = await Knowledge.findAll({
|
||||||
|
where: {
|
||||||
|
characterId: character.id,
|
||||||
|
productId: { [Op.in]: productIds }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const knowledgeMap = new Map(knowledges.map(k => [k.productId, k.knowledge]));
|
||||||
|
|
||||||
|
// Hole alle TownProductWorth-Werte auf einmal
|
||||||
|
const townWorths = await TownProductWorth.findAll({
|
||||||
|
where: {
|
||||||
|
productId: { [Op.in]: productIds },
|
||||||
|
regionId: regionId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const worthMap = new Map(townWorths.map(tw => [tw.productId, tw.worthPercent]));
|
||||||
|
|
||||||
|
// Berechne Preise für alle Produkte
|
||||||
|
const prices = {};
|
||||||
|
for (const product of products) {
|
||||||
|
const knowledgeFactor = knowledgeMap.get(product.id) || 0;
|
||||||
|
const worthPercent = worthMap.get(product.id) || 50;
|
||||||
|
|
||||||
|
const basePrice = product.sellCost * (worthPercent / 100);
|
||||||
|
const min = basePrice * 0.6;
|
||||||
|
const max = basePrice;
|
||||||
|
const price = min + (max - min) * (knowledgeFactor / 100);
|
||||||
|
|
||||||
|
prices[product.id] = Math.round(price * 100) / 100; // Auf 2 Dezimalstellen runden
|
||||||
|
}
|
||||||
|
|
||||||
|
return prices;
|
||||||
|
}
|
||||||
|
|
||||||
async getProductPriceInRegion(hashedUserId, productId, regionId) {
|
async getProductPriceInRegion(hashedUserId, productId, regionId) {
|
||||||
const user = await this.getFalukantUserByHashedId(hashedUserId);
|
const user = await this.getFalukantUserByHashedId(hashedUserId);
|
||||||
const character = await FalukantCharacter.findOne({ where: { userId: user.id } });
|
const character = await FalukantCharacter.findOne({ where: { userId: user.id } });
|
||||||
|
|||||||
@@ -572,27 +572,49 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lade Preise für alle Produkte in der aktuellen Region
|
if (!this.products || this.products.length === 0) {
|
||||||
const prices = {};
|
this.productPricesCache = {};
|
||||||
for (const product of this.products) {
|
return;
|
||||||
try {
|
}
|
||||||
const { data } = await apiClient.get('/api/falukant/products/price-in-region', {
|
|
||||||
params: {
|
// OPTIMIERUNG: Lade alle Preise in einem Batch-Request
|
||||||
productId: product.id,
|
try {
|
||||||
regionId: this.selectedBranch.regionId
|
const productIds = this.products.map(p => p.id).join(',');
|
||||||
}
|
const { data } = await apiClient.get('/api/falukant/products/prices-in-region-batch', {
|
||||||
});
|
params: {
|
||||||
prices[product.id] = data.price;
|
productIds: productIds,
|
||||||
} catch (error) {
|
regionId: this.selectedBranch.regionId
|
||||||
console.error(`Error loading price for product ${product.id}:`, error);
|
}
|
||||||
// Fallback auf Standard-Berechnung
|
});
|
||||||
const knowledgeFactor = product.knowledges?.[0]?.knowledge || 0;
|
this.productPricesCache = data || {};
|
||||||
const maxPrice = product.sellCost;
|
} catch (error) {
|
||||||
const minPrice = maxPrice * 0.6;
|
console.error('Error loading prices in batch:', error);
|
||||||
prices[product.id] = minPrice + (maxPrice - minPrice) * (knowledgeFactor / 100);
|
// Fallback: Lade Preise einzeln (aber parallel)
|
||||||
}
|
const pricePromises = this.products.map(async (product) => {
|
||||||
|
try {
|
||||||
|
const { data } = await apiClient.get('/api/falukant/products/price-in-region', {
|
||||||
|
params: {
|
||||||
|
productId: product.id,
|
||||||
|
regionId: this.selectedBranch.regionId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { productId: product.id, price: data.price };
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading price for product ${product.id}:`, err);
|
||||||
|
// Fallback auf Standard-Berechnung
|
||||||
|
const knowledgeFactor = product.knowledges?.[0]?.knowledge || 0;
|
||||||
|
const maxPrice = product.sellCost;
|
||||||
|
const minPrice = maxPrice * 0.6;
|
||||||
|
return { productId: product.id, price: minPrice + (maxPrice - minPrice) * (knowledgeFactor / 100) };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = await Promise.all(pricePromises);
|
||||||
|
this.productPricesCache = {};
|
||||||
|
results.forEach(({ productId, price }) => {
|
||||||
|
this.productPricesCache[productId] = price;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.productPricesCache = prices;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
formatPercent(value) {
|
formatPercent(value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user