WellNuo/backend/docs/EQUIPMENT_STATUS.md
Sergei f69ddb7538 Add equipment status mapping documentation and tests
- Created comprehensive EQUIPMENT_STATUS.md documentation covering:
  - All valid status values (none, ordered, shipped, delivered, demo, active)
  - Database schema details
  - Navigation logic based on equipment status
  - hasDevices flag calculation
  - Code locations for reading/setting status

- Added unit tests for equipment status mapping:
  - Tests for all valid status values
  - Demo serial number detection (DEMO-00000, DEMO-1234-5678)
  - Real device activation
  - hasDevices calculation for each status
  - Default value handling (null → 'none')

- All tests passing (13/13)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-29 11:18:16 -08:00

150 lines
5.1 KiB
Markdown

# Equipment Status Mapping
## Overview
The `equipment_status` field tracks the state of IoT equipment for each beneficiary in the WellNuo system.
## Database Field
- **Table**: `beneficiaries`
- **Column**: `equipment_status` (VARCHAR)
- **Default**: `'none'`
- **Constraint**: No CHECK constraint defined in schema (any string value allowed)
## Valid Status Values
| Status | Description | When Set | User Flow |
|--------|-------------|----------|-----------|
| `none` | No equipment ordered or assigned | • Initial beneficiary creation<br>• Default state | User sees "Purchase Equipment" screen |
| `ordered` | Equipment ordered, payment completed | • After successful Stripe payment<br>• Order status: paid | User sees "Order Tracking" screen |
| `shipped` | Equipment in transit | • Order status changes to shipped<br>• Tracking number assigned | User sees "Delivery Status" screen |
| `delivered` | Equipment arrived at destination | • Order status changes to delivered | User sees "Activate Equipment" screen |
| `demo` | Demo mode activated (no real devices) | • User activates with serial `DEMO-00000` or `DEMO-1234-5678` | Full app access with simulated data |
| `active` | Real equipment activated and operational | • User activates with real device serial number | Full app access with real sensor data |
## Code Locations
### Setting Status
```javascript
// Initial creation (none)
POST /api/me/beneficiaries
equipment_status: 'none'
// Activation (demo or active)
POST /api/me/beneficiaries/:id/activate
isDemoMode = serialNumber === 'DEMO-00000' || serialNumber === 'DEMO-1234-5678'
equipment_status: isDemoMode ? 'demo' : 'active'
// Order status changes (ordered, shipped, delivered)
POST /api/webhook/stripe
Updates based on Stripe events
```
### Reading Status
```javascript
// List beneficiaries
GET /api/me/beneficiaries
equipmentStatus: beneficiary.equipment_status || 'none'
hasDevices: beneficiary.equipment_status === 'active' || beneficiary.equipment_status === 'demo'
// Get single beneficiary
GET /api/me/beneficiaries/:id
equipmentStatus: beneficiary.equipment_status || 'none'
hasDevices: beneficiary.equipment_status === 'active' || beneficiary.equipment_status === 'demo'
```
## Navigation Logic (NavigationController)
The `equipmentStatus` determines which screen to show after login/beneficiary creation:
```typescript
if (equipmentStatus === 'none') {
/(auth)/purchase - Buy equipment
}
if (equipmentStatus === 'ordered' || equipmentStatus === 'shipped') {
/(tabs)/beneficiaries/:id/equipment - Track delivery
}
if (equipmentStatus === 'delivered') {
/(auth)/activate - Activate equipment
}
if (equipmentStatus === 'active' || equipmentStatus === 'demo') {
/(tabs)/dashboard - Full app access
}
```
## hasDevices Flag
**Critical for navigation:** `hasDevices` is derived from `equipmentStatus`:
```javascript
hasDevices = (equipmentStatus === 'active' || equipmentStatus === 'demo')
```
This flag is used in:
- Navigation decisions (show dashboard vs purchase)
- Feature access control (sensors, alarms, etc.)
- UI conditional rendering
## Issues Found
1. **No Database Constraint**: The `equipment_status` column has no CHECK constraint, allowing any string value
- **Risk**: Typos, invalid values, inconsistent casing
- **Recommendation**: Add CHECK constraint in future migration
2. **Frontend Handling**: Frontend code should handle all possible statuses gracefully
- Current implementation uses fallback: `equipmentStatus || 'none'`
- UI should handle unexpected values with default behavior
3. **Order Status Sync**: Need to verify that order status changes properly update `equipment_status`
- Check Stripe webhook handlers
- Verify order table → beneficiaries sync
## Testing Requirements
### Unit Tests Needed
- ✅ Activation sets correct status (demo vs active)
- ✅ Beneficiary creation defaults to 'none'
- ✅ hasDevices calculation is correct
- ⚠️ Status transitions (none → ordered → shipped → delivered → active)
- ⚠️ Invalid status handling
### Integration Tests Needed
- ⚠️ Order webhook → equipment_status update
- ⚠️ Navigation flow for each status
- ⚠️ UI rendering for each status
## Recommendations
1. **Add Database Constraint** (Future Migration):
```sql
ALTER TABLE beneficiaries
ADD CONSTRAINT check_equipment_status
CHECK (equipment_status IN ('none', 'ordered', 'shipped', 'delivered', 'demo', 'active'));
```
2. **Create Constants File**:
```javascript
// constants/equipmentStatus.js
const EQUIPMENT_STATUS = {
NONE: 'none',
ORDERED: 'ordered',
SHIPPED: 'shipped',
DELIVERED: 'delivered',
DEMO: 'demo',
ACTIVE: 'active'
};
```
3. **Add Status Validation** in API endpoints:
```javascript
function isValidEquipmentStatus(status) {
return ['none', 'ordered', 'shipped', 'delivered', 'demo', 'active'].includes(status);
}
```
4. **Add Logging** for status changes:
```javascript
console.log(`[EQUIPMENT_STATUS] ${beneficiaryId}: ${oldStatus} → ${newStatus}`);
```