S3Q1 · Inventory Stock Analytics¶
⚡ Quick Reference
Four functions on inventory records (sku, quantity, warehouse, reorder_level):
def needs_reorder(records):
return [(r[0], r[2]) for r in records if r[1] <= r[3]]
def total_units(records, sku):
return sum(r[1] for r in records if r[0] == sku)
def stock_status(records):
skus = {r[0]: r[3] for r in records} # sku → reorder_level
result = {}
for sku, level in skus.items():
total = total_units(records, sku)
if total > 2 * level:
result[sku] = "overstocked"
elif total <= level:
result[sku] = "low"
else:
result[sku] = "normal"
return result
def transfer_simulation(records, sku, source, destination, units):
src = next((r for r in records if r[0]==sku and r[2]==source), None)
dst = next((r for r in records if r[0]==sku and r[2]==destination), None)
if not src or not dst:
return {}
if src[1] < units or (src[1] - units) < src[3]:
return {}
return {source: src[1] - units, destination: dst[1] + units}
Key rules:
- needs_reorder: quantity <= reorder_level
- stock_status: classify by total vs reorder_level (same for all warehouses of a SKU)
- Transfer allowed only if source has enough AND won't drop below reorder level after
Problem Statement¶
Problem
Implement four functions to analyse inventory records, each a tuple (sku, quantity, warehouse, reorder_level).
Sample data:
records = [
("SKU1", 40, "WH-A", 20),
("SKU1", 10, "WH-B", 20),
("SKU2", 15, "WH-A", 30),
("SKU3", 80, "WH-C", 25),
]
Function 1 - needs_reorder¶
Return (sku, warehouse) pairs where quantity <= reorder_level:
From sample:
- ("SKU1", 10, "WH-B", 20): 10 ≤ 20 ✅ → ("SKU1", "WH-B")
- ("SKU2", 15, "WH-A", 30): 15 ≤ 30 ✅ → ("SKU2", "WH-A")
Result: [("SKU1", "WH-B"), ("SKU2", "WH-A")]
Function 2 - total_units¶
Sum quantities for a given SKU across all warehouses:
From sample: total_units(records, "SKU1") = 40 + 10 = 50
Function 3 - stock_status¶
Classify each SKU by total quantity vs its reorder level:
| Condition | Status |
|---|---|
total > 2 × reorder_level |
"overstocked" |
reorder_level < total ≤ 2 × reorder_level |
"normal" |
total ≤ reorder_level |
"low" |
def stock_status(records: list) -> dict:
skus = {r[0]: r[3] for r in records} # sku → reorder_level (last wins, same value)
result = {}
for sku, level in skus.items():
total = total_units(records, sku)
if total > 2 * level:
result[sku] = "overstocked"
elif total <= level:
result[sku] = "low"
else:
result[sku] = "normal"
return result
From sample: - SKU1: total=50, level=20 → 50 > 40 → overstocked - SKU2: total=15, level=30 → 15 ≤ 30 → low - SKU3: total=80, level=25 → 80 > 50 → overstocked
Function 4 - transfer_simulation¶
Simulate moving units from source to destination for a given SKU. Three conditions must all pass:
- Both
sourceanddestinationhold the SKU - Source has at least
unitsavailable - After transfer, source quantity stays ≥ reorder level
def transfer_simulation(records: list, sku: str, source: str,
destination: str, units: int) -> dict:
src = next((r for r in records if r[0] == sku and r[2] == source), None)
dst = next((r for r in records if r[0] == sku and r[2] == destination), None)
if not src or not dst:
return {} # SKU not in one of the warehouses
if src[1] < units:
return {} # not enough stock
if (src[1] - units) < src[3]:
return {} # would drop below reorder level
return {source: src[1] - units, destination: dst[1] + units}
Example: transfer 15 units of SKU1 from WH-A to WH-B
- src = ("SKU1", 40, "WH-A", 20), dst = ("SKU1", 10, "WH-B", 20)
- 40 ≥ 15 ✅, 40 - 15 = 25 ≥ 20 ✅
- Result: {"WH-A": 25, "WH-B": 25}
Complete solution approaches¶
def needs_reorder(records: list) -> list:
return [(r[0], r[2]) for r in records if r[1] <= r[3]]
def total_units(records: list, sku: str) -> int:
return sum(r[1] for r in records if r[0] == sku)
def stock_status(records: list) -> dict:
skus = {r[0]: r[3] for r in records}
result = {}
for sku, level in skus.items():
total = total_units(records, sku)
result[sku] = ("overstocked" if total > 2 * level
else "low" if total <= level
else "normal")
return result
def transfer_simulation(records: list, sku: str, source: str,
destination: str, units: int) -> dict:
src = next((r for r in records if r[0]==sku and r[2]==source), None)
dst = next((r for r in records if r[0]==sku and r[2]==destination), None)
if not src or not dst:
return {}
if src[1] < units or (src[1] - units) < src[3]:
return {}
return {source: src[1] - units, destination: dst[1] + units}
def needs_reorder(records: list) -> list:
result = []
for r in records:
if r[1] <= r[3]:
result.append((r[0], r[2]))
return result
def total_units(records: list, sku: str) -> int:
total = 0
for r in records:
if r[0] == sku:
total += r[1]
return total
def stock_status(records: list) -> dict:
skus = {}
for r in records:
skus[r[0]] = r[3]
result = {}
for sku, level in skus.items():
total = total_units(records, sku)
if total > 2 * level:
result[sku] = "overstocked"
elif total <= level:
result[sku] = "low"
else:
result[sku] = "normal"
return result
def transfer_simulation(records: list, sku: str, source: str,
destination: str, units: int) -> dict:
src, dst = None, None
for r in records:
if r[0] == sku and r[2] == source:
src = r
if r[0] == sku and r[2] == destination:
dst = r
if not src or not dst:
return {}
if src[1] < units or (src[1] - units) < src[3]:
return {}
return {source: src[1] - units, destination: dst[1] + units}
def needs_reorder(records: list) -> list:
return list(map(lambda r: (r[0], r[2]),
filter(lambda r: r[1] <= r[3], records)))
def total_units(records: list, sku: str) -> int:
return sum(map(lambda r: r[1],
filter(lambda r: r[0] == sku, records)))
def stock_status(records: list) -> dict:
skus = {r[0]: r[3] for r in records}
classify = lambda sku, level: (
"overstocked" if total_units(records, sku) > 2 * level
else "low" if total_units(records, sku) <= level
else "normal"
)
return {sku: classify(sku, level) for sku, level in skus.items()}
def transfer_simulation(records: list, sku: str, source: str,
destination: str, units: int) -> dict:
find = lambda wh: next((r for r in records if r[0]==sku and r[2]==wh), None)
src, dst = find(source), find(destination)
if not src or not dst or src[1] < units or (src[1]-units) < src[3]:
return {}
return {source: src[1]-units, destination: dst[1]+units}
Key takeaways¶
next(..., None) for safe record lookup
next((r for r in records if condition), None) finds the first matching record or returns None if none exists. Avoids index errors and handles missing SKU/warehouse cleanly.
Reuse total_units inside stock_status
Building on your own functions keeps logic in one place. stock_status calls total_units rather than recomputing the sum - any fix to one function automatically fixes the other.
Transfer: check both conditions before returning
Two separate failure conditions exist: not enough stock (src[1] < units) and would drop below reorder level (src[1] - units < src[3]). Both must pass. Combine with or to reject if either fails.