# RO Data Corruption Recovery

## Problem

Some Repair Orders in PocketBase have `services` as a plain text string instead of a valid JSON array. Examples found (2026-07-08):

- `"a13 hondacare"` — appears to be a PocketBase filter value mistakenly written to the field
- `"Oil change, tire rotation, and brake inspection"` — plain text notes
- `"[Tire Rotation] Rotating your tires..."` — formatted text with markdown-like syntax
- `"OIL CHANGE - TIRE ROTATION\\n[Engine Oil and Filter]..."` — multi-line text

These corrupt records cause `normalizeRO` to fail JSON parsing, which logs a console error but silently falls back to `services = []`.

## normalizeRO Graceful Handling

In `src/lib/repairOrders.ts` (lines 161-166):

```ts
export function normalizeRO(item: any): RepairOrder {
  let services = item.services || [];
  if (typeof services === 'string' && services.trim()) {
    try { services = JSON.parse(services); } catch (err) {
      logError(`Failed to parse normalizeRO services JSON for RO ${item.id}: ${services}`, err);
      services = [];
    }
  }
  if (!Array.isArray(services)) services = [];
  // ...
}
```

The function already handles non-JSON strings gracefully — it falls back to `[]`. The `logError` call surfaces the issue in the console so corrupt records can be identified and fixed.

## Finding Corrupt Records

Query PocketBase as superuser to find all ROs with non-JSON services:

```bash
SUPERTOKEN=$(curl -s -X POST http://127.0.0.1:8091/api/collections/_superusers/auth-with-password \
  -H 'Content-Type: application/json' \
  -d '{"identity":"admin@shop.com","password":"TtAU6aUEFSXrVR"}' | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('token',''))")

curl -s "http://127.0.0.1:8091/api/collections/repairOrders/records?perPage=200&skipTotal=1" \
  -H "Authorization: $SUPERTOKEN" | python3 -c "
import json, sys
data = json.load(sys.stdin)
for ro in data['items']:
    svcs = ro.get('services','')
    if svcs and isinstance(svcs, str) and svcs.strip():
        try: json.loads(svcs)
        except:
            print(f'{ro[\"id\"]} | {ro.get(\"roNumber\",\"\")} | {ro.get(\"customerName\",\"\")}')
"
```

## Fixing Corrupt Records

Reset the `services` field to an empty JSON array:

```bash
for RO_ID in <id1> <id2> ...; do
  curl -s -o /dev/null -w '%{http_code}' -X PATCH \
    "http://127.0.0.1:8091/api/collections/repairOrders/records/${RO_ID}" \
    -H "Authorization: $SUPERTOKEN" \
    -H 'Content-Type: application/json' \
    -d '{"services":"[]"}'
done
```

## Prevention

All write paths in the codebase write `JSON.stringify(array)` to `services`:
- `QuoteSummary.tsx` sync block (lines 179-181, 294-296)
- `RepairOrders.tsx` line 373
- `RODetailModal.tsx` line 878

The corrupt records predate these write paths and likely originate from early development or manual PocketBase admin edits. New corruption should not occur through the normal app flow.

## Already Fixed (2026-07-08)

The following 6 ROs were identified and fixed during investigation:

| RO # | Customer | Corrupt Value |
|------|----------|---------------|
| RO-2026-001 | John Smith | "Oil change, tire rotation, and brake inspection" |
| 905003 | GREG JONES | "[Tire Rotation] Rotating your tires..." |
| 905118 | Abbey Warbington | "OIL CHANGE - TIRE ROTATION..." |
| 905150 | DARRELL FUJIYOSHI | "RIGHT FRONT TIRE LOSING AIR" |
| 905156 | PAUL W GROTH | "[Oil and Filter Change] Your vehicle is due..." |
| 905188 | JACOB NABORS | "a13 hondacare" |
