# Bug 2 Exploration Test Results

## Test Execution Summary

**Date**: 2024-01-XX  
**Test File**: `api/src/inventory.service.bug2.test.ts`  
**Status**: ✅ Test written and executed on UNFIXED code  
**Outcome**: ❌ Tests FAILED as expected (confirms bug exists)

## Bug Condition

**Bug Condition Function**: `isBugCondition2(input)`
- `input.warehouseId IS NOT NULL`
- `input.itemId IS NOT NULL`

## Counterexamples Found

### Counterexample 1: Multi-Warehouse Distribution
**Test**: "should return warehouse-specific MT (1,900) not total across all warehouses (18,000)"

**Setup**:
- Item: Rice 25kg (bagWeightKg = 25)
- Batch: BATCH-001
- Distribution:
  - Warehouse A: 76,000 bags = 1,900 MT
  - Warehouse B: 324,000 bags = 8,100 MT
  - Warehouse C: 320,000 bags = 8,000 MT
  - **Total**: 720,000 bags = 18,000 MT

**Query**: `getBatches(itemId, warehouseAId)`

**Expected Behavior**:
- `batch.availableMt = 1,900` (warehouse-specific)
- `batch.availableMt <= 18,000` (total across all warehouses)

**Actual Behavior (Buggy)**:
- `batch.availableMt = 18,000` ❌
- Returns total across all warehouses instead of warehouse-specific

**Test Result**: ❌ FAILED
```
AssertionError: expected 18000 to be 1900 // Object.is equality
- Expected: 1900
+ Received: 18000
```

### Counterexample 2: Partial Stock-Out Scenario
**Test**: "should return correct remaining MT after partial stock-out from one warehouse"

**Setup**:
- Item: Rice 25kg (bagWeightKg = 25)
- Batch: BATCH-003
- Original Distribution:
  - Warehouse A: 2,000 MT
  - Warehouse B: 3,000 MT
- After partial stock-out from Warehouse A (500 MT):
  - Warehouse A: 1,500 MT (remaining)
  - Warehouse B: 3,000 MT (unchanged)
  - **Total**: 4,500 MT

**Query**: `getBatches(itemId, warehouseAId)`

**Expected Behavior**:
- `batch.availableMt = 1,500` (warehouse-specific remaining)
- `batch.availableMt <= 4,500` (total remaining)

**Actual Behavior (Buggy)**:
- `batch.availableMt = 4,500` ❌
- Returns total remaining across all warehouses

**Test Result**: ❌ FAILED
```
AssertionError: expected 4500 to be 1500 // Object.is equality
- Expected: 1500
+ Received: 4500
```

### Counterexample 3: Zero Stock in Queried Warehouse
**Test**: "should return 0 MT or empty array when warehouse has no stock for the batch"

**Setup**:
- Item: Rice 25kg (bagWeightKg = 25)
- Batch: BATCH-004
- Distribution:
  - Warehouse A: 0 bags = 0 MT
  - Warehouse B: 200,000 bags = 5,000 MT
  - Warehouse C: 200,000 bags = 5,000 MT
  - **Total**: 400,000 bags = 10,000 MT

**Query**: `getBatches(itemId, warehouseAId)`

**Expected Behavior**:
- `batch.availableMt = 0` OR empty array (no batches with stock)

**Actual Behavior (Buggy)**:
- `batch.availableMt = 10,000` ❌
- Returns total across warehouses B and C, even though Warehouse A has 0

**Test Result**: ❌ FAILED
```
AssertionError: expected 10000 to be +0 // Object.is equality
- Expected: 0
+ Received: 10000
```

### Counterexample 4: Single Warehouse (Edge Case)
**Test**: "should return correct MT when item exists in only one warehouse"

**Setup**:
- Item: Wheat 50kg (bagWeightKg = 50)
- Batch: BATCH-002
- Distribution:
  - Warehouse A: 60,000 bags = 3,000 MT
  - **Total**: 60,000 bags = 3,000 MT

**Query**: `getBatches(itemId, warehouseAId)`

**Expected Behavior**:
- `batch.availableMt = 3,000` (warehouse-specific, equals total)

**Actual Behavior**:
- `batch.availableMt = 3,000` ✅
- Correct by coincidence (warehouse-specific equals total)

**Test Result**: ✅ PASSED (by coincidence)

## Root Cause Analysis

The bug is confirmed to exist in the `getBatches` method in `api/src/inventory.service.ts`:

1. **Incorrect Data Source**: The method queries `inventory_balance.currentQuantityMt`, which stores the batch-level total across all warehouses, not warehouse-specific quantities.

2. **Missing Warehouse Filter**: Even though `getBatches` receives `warehouseId` as a parameter, it only uses it to filter batches, but the `availableMt` comes from `inventory_balance`, which has a unique index on `batchId` (one record per batch, not per warehouse+batch).

3. **Correct Data Source Exists**: The `stock_movement_sheets` collection contains the correct warehouse-specific data in `lineItems[].warehouseBags[warehouseId]`, which maps warehouse IDs to bag counts. This is the source of truth for warehouse-specific quantities.

## Expected Behavior Properties

From the design document, the fix should satisfy:

**Property 1**: For any request to `getBatches` with a specific `warehouseId` and `itemId`, the fixed method SHALL return batches with `availableMt` calculated from warehouse-specific quantities in approved stock movement sheets.

**Property 2**: `batch.availableMt = sum(sheet.lineItems[].warehouseBags[warehouseId] * bagWeightKg / 1000)` for matching item and batch combinations.

**Property 3**: `batch.availableMt <= totalMtForBatchAcrossAllWarehouses`

## Next Steps

1. ✅ Bug condition exploration test written and executed
2. ✅ Counterexamples documented
3. ⏭️ Write preservation property tests (Task 5)
4. ⏭️ Implement fix in `getBatches` method (Task 6.1)
5. ⏭️ Verify bug condition test passes after fix (Task 6.2)
6. ⏭️ Verify preservation tests still pass (Task 6.3)

## Test Execution Command

```bash
cd api
npm test inventory.service.bug2.test.ts
```

## Test Statistics

- **Total Tests**: 4
- **Passed**: 1 (edge case - correct by coincidence)
- **Failed**: 3 (confirms bug exists)
- **Duration**: 23ms

## Conclusion

✅ **Task 4 Complete**: Bug condition exploration test successfully demonstrates that Bug 2 exists in the unfixed code. The test will serve as validation when the fix is implemented - it should pass after the fix is applied.

The counterexamples clearly show that `getBatches` returns batch-level totals from `inventory_balance` instead of warehouse-specific quantities from `stock_movement_sheets`, confirming the root cause analysis in the design document.
