55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
function requiredText(value, fieldName) {
|
|
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
throw new Error(`${fieldName} is required.`);
|
|
}
|
|
|
|
return value.trim();
|
|
}
|
|
|
|
function requirePositiveMinorUnit(value, fieldName) {
|
|
if (!Number.isInteger(value) || value <= 0) {
|
|
throw new Error(`${fieldName} must be a positive integer minor unit.`);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
export function createPricingObservation({
|
|
productId,
|
|
inventoryItemId,
|
|
providerId,
|
|
priceMinor,
|
|
currency = 'USD',
|
|
sourceIdentifier,
|
|
conditionId,
|
|
sourceUrl,
|
|
qualityScore,
|
|
}) {
|
|
return {
|
|
productId: requiredText(productId, 'Product ID'),
|
|
inventoryItemId: requiredText(inventoryItemId, 'Inventory item ID'),
|
|
providerId: requiredText(providerId, 'Provider ID'),
|
|
priceMinor: requirePositiveMinorUnit(priceMinor, 'Observed price'),
|
|
currency: requiredText(currency, 'Currency'),
|
|
sourceIdentifier: requiredText(sourceIdentifier, 'Source identifier'),
|
|
conditionId: requiredText(conditionId, 'Condition ID'),
|
|
...(typeof sourceUrl === 'string' && sourceUrl.trim().length > 0 ? { sourceUrl: sourceUrl.trim() } : {}),
|
|
...(typeof qualityScore === 'number' ? { qualityScore } : {}),
|
|
};
|
|
}
|
|
|
|
export function calculateMedianPriceMinor(prices) {
|
|
if (!Array.isArray(prices) || prices.length === 0) {
|
|
throw new Error('At least one price is required.');
|
|
}
|
|
|
|
const sorted = [...prices].sort((left, right) => left - right);
|
|
const middle = Math.floor(sorted.length / 2);
|
|
|
|
if (sorted.length % 2 === 0) {
|
|
return Math.round((sorted[middle - 1] + sorted[middle]) / 2);
|
|
}
|
|
|
|
return sorted[middle];
|
|
}
|