Aggregated Sales Report Generator with Jest Testing
This challenge focuses on building a function that aggregates sales data into a concise report format. Generating reports from raw data is a common task in data analysis and business intelligence, and writing robust tests for such functions is crucial for ensuring data integrity and reliability. You'll implement the aggregation logic and then write Jest tests to verify its correctness.
Problem Description
You are tasked with creating a TypeScript function called generateSalesReport that takes an array of sales records as input and returns an aggregated sales report. Each sales record is an object with the following properties: product: string, quantity: number, price: number. The report should summarize the total sales for each product.
The generateSalesReport function should:
- Accept an array of sales records: The input will be an array of objects, each representing a single sale.
- Aggregate sales by product: Calculate the total quantity and total revenue for each unique product.
- Return a report object: The function should return an object where keys are product names and values are objects containing
totalQuantityandtotalRevenue. - Handle empty input: If the input array is empty, return an empty object.
- Handle invalid input: If any sales record is missing a required property (product, quantity, or price), or if quantity or price are not numbers, skip that record and log an error to the console. Do not throw an error; continue processing valid records.
Expected Behavior: The function should accurately calculate the total quantity and total revenue for each product, even with potentially invalid or missing data in the input.
Examples
Example 1:
Input: [
{ product: 'Apple', quantity: 2, price: 1.0 },
{ product: 'Banana', quantity: 3, price: 0.5 },
{ product: 'Apple', quantity: 1, price: 1.0 },
]
Output: {
Apple: { totalQuantity: 3, totalRevenue: 3.0 },
Banana: { totalQuantity: 3, totalRevenue: 1.5 }
}
Explanation: The function aggregates sales for 'Apple' (3 quantity, $3 revenue) and 'Banana' (3 quantity, $1.5 revenue).
Example 2:
Input: []
Output: {}
Explanation: An empty input array results in an empty report object.
Example 3: (Edge Case - Invalid Data)
Input: [
{ product: 'Apple', quantity: 2, price: 1.0 },
{ product: 'Banana', quantity: 'abc', price: 0.5 }, // Invalid quantity
{ product: 'Orange', price: 0.75 }, // Missing product
{ product: 'Apple', quantity: 1, price: 1.0 },
]
Output: {
Apple: { totalQuantity: 3, totalRevenue: 3.0 }
}
Explanation: The function skips the invalid records ('Banana' and 'Orange') and logs errors to the console. Only valid 'Apple' sales are included in the report.
Constraints
- The input array can contain up to 1000 sales records.
- Product names are strings.
- Quantity and price must be numbers.
- The function must not throw errors; it should gracefully handle invalid input.
- Performance: The function should complete within 100ms for the maximum input size.
Notes
- Consider using a
Mapor a plain JavaScript object to efficiently aggregate the sales data. - Use
console.errorto log errors related to invalid input. - Focus on writing clear, concise, and well-documented code.
- You will need to write Jest tests to verify the correctness of your implementation, including tests for valid input, empty input, and invalid input scenarios. Think about edge cases and boundary conditions.
- The
priceandquantitycan be floating point numbers.