Skip to content

Commit 88f63aa

Browse files
authored
Merge pull request #191 from AAdewunmi/feat/write-Sprint-6-surface-verification-runbook
Feat/write sprint 6 surface verification runbook
2 parents f1adf5d + 726d29c commit 88f63aa

10 files changed

Lines changed: 286 additions & 35 deletions

File tree

README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Current committed active model:
155155
cp .env.example .env
156156
docker compose up --build -d
157157
docker compose exec -T web python manage.py migrate --noinput
158-
docker compose exec -T web python manage.py seed_demo_data
158+
docker compose exec -T web python manage.py seed_returnhub_demo
159159
```
160160

161161
Application URL:
@@ -164,16 +164,18 @@ Application URL:
164164
http://127.0.0.1:8000/
165165
```
166166

167-
Demo users created by `seed_demo_data`:
167+
Demo users created by `seed_returnhub_demo`:
168168

169-
- `admin`
170-
- `ops`
171-
- `customer`
172-
- `merchant`
169+
- `admin.demo`
170+
- `ops.demo`
171+
- `customer.one`
172+
- `customer.two`
173+
- `merchant.one`
174+
- `merchant.two`
173175

174176
Shared local password:
175177

176-
- `password123`
178+
- `ChangeMe123!`
177179

178180
## Useful commands
179181

@@ -195,17 +197,23 @@ docker compose exec -T web python manage.py retrain_baseline_model --seed 7 --ro
195197

196198
```text
197199
.
200+
├── .github/
198201
├── accounts/
199202
├── analytics/
200203
├── api/
204+
├── artifacts/
201205
├── common/
202206
├── config/
203207
├── console/
208+
├── core/
204209
├── docs/
205210
│ ├── api/
206211
│ ├── ml/
212+
│ ├── sprint-runbook/
207213
│ └── ui/
208214
├── ml/
215+
├── ml_artifacts/
216+
├── requirements/
209217
├── returns/
210218
├── static/
211219
├── templates/
@@ -214,7 +222,13 @@ docker compose exec -T web python manage.py retrain_baseline_model --seed 7 --ro
214222
├── Dockerfile
215223
├── Makefile
216224
├── README.md
217-
└── RUNBOOK.md
225+
├── RUNBOOK.md
226+
├── codecov.yml
227+
├── docker-compose.yml
228+
├── manage.py
229+
├── pyproject.toml
230+
├── pytest.ini
231+
└── web/
218232
```
219233

220234
## Documentation map
@@ -228,3 +242,4 @@ docker compose exec -T web python manage.py retrain_baseline_model --seed 7 --ro
228242
- `docs/ui/product-ui-brief.md`: product-surface intent and route map
229243
- `docs/ui/design-system.md`: tokens, layout patterns, and component rules
230244
- `docs/ui/evidence-states.md`: case detail and document-upload state handling
245+
- `docs/sprint-runbook/sprint-6/sprint-6-multi-surface-verification.md`: current multi-surface verification flow

RUNBOOK.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ docker compose exec -T web python manage.py migrate --noinput
5959
Seed demo data.
6060

6161
```bash
62-
docker compose exec -T web python manage.py seed_demo_data
62+
docker compose exec -T web python manage.py seed_returnhub_demo
6363
```
6464

6565
Expected result:
6666

6767
```text
68-
Seed complete. Stable return case count: 32
68+
ReturnHub demo seed complete.
6969
```
7070

7171
Run it again to confirm idempotency.
7272

7373
```bash
74-
docker compose exec -T web python manage.py seed_demo_data
74+
docker compose exec -T web python manage.py seed_returnhub_demo
7575
```
7676

7777
## Verify seeded roles and users
@@ -97,13 +97,13 @@ docker compose exec -T web python manage.py shell -c "from django.contrib.auth i
9797
Expected:
9898

9999
```text
100-
['admin', 'customer', 'merchant', 'ops']
100+
['admin.demo', 'customer.one', 'customer.two', 'merchant.one', 'merchant.two', 'ops.demo']
101101
```
102102

103103
Shared local password for the seeded users:
104104

105105
```text
106-
password123
106+
ChangeMe123!
107107
```
108108

109109
Check return-case count.
@@ -261,7 +261,7 @@ Document visibility checks:
261261

262262
Authenticate with one of the seeded users and verify the live routes.
263263

264-
Create a case as `customer`:
264+
Create a case as a seeded customer user such as `customer.one`:
265265

266266
```http
267267
POST /api/returns/
@@ -338,8 +338,8 @@ Check risk:
338338

339339
Expected:
340340

341-
- `ops` and `admin` receive risk payloads
342-
- `customer` and `merchant` receive `403`
341+
- ops and admins receive risk payloads
342+
- customers and merchants receive `403`
343343

344344
Check audit export:
345345

@@ -486,7 +486,7 @@ docker compose exec web python manage.py shell -c "import logging; from django.t
486486
docker compose exec web python manage.py shell -c "import logging; from django.test import Client; from django.contrib.auth import get_user_model; from returns.models import ReturnCase, CaseNote; logging.getLogger('django.request').disabled = True; User = get_user_model(); client = Client(HTTP_HOST='localhost', raise_request_exception=False); user = User.objects.filter(groups__name__iexact='Ops').first() or User.objects.filter(is_superuser=True).first(); nav_case = ReturnCase.objects.order_by('id').first(); sparse_case = ReturnCase.objects.exclude(pk=nav_case.pk).order_by('id').first() or nav_case; CaseNote.objects.filter(return_case=nav_case).delete(); CaseNote.objects.filter(return_case=sparse_case).delete(); CaseNote.objects.create(return_case=nav_case, author=user, body='Older note for ordering check'); CaseNote.objects.create(return_case=nav_case, author=user, body='Newer note for ordering check'); client.force_login(user); response = client.get(f'/ops/{nav_case.pk}/'); sparse_response = client.get(f'/ops/{sparse_case.pk}/'); content = response.content.decode(); sparse_content = sparse_response.content.decode(); print(f'OPS_CASE_DETAIL_QUICK_NAVIGATION_CHECK={\"Quick navigation\" in content}'); print(f'OPS_ACTION_BAR_WORKFLOW_LINK_CHECK={\"#case-status-panel\" in content}'); print(f'OPS_ACTION_BAR_NOTES_LINK_CHECK={\"#case-notes-panel\" in content}'); print(f'OPS_ACTION_BAR_DOCUMENTS_LINK_CHECK={\"#case-document-table\" in content}'); print(f'OPS_ACTION_BAR_TIMELINE_LINK_CHECK={\"#case-timeline\" in content}'); print(f'OPS_CASE_DETAIL_NOTES_PLACEMENT_CHECK={content.index(\"Workflow state\") < content.index(\"Internal notes\") < content.index(\"Documents\")}'); print(f'OPS_NOTES_ORDERING_RENDER_CHECK={content.index(\"Newer note for ordering check\") < content.index(\"Older note for ordering check\")}'); print(f'OPS_EMPTY_NOTES_CHECK={\"No notes yet\" in sparse_content}')"
487487
```
488488

489-
### Day 5 ops surface proof
489+
### Ops surface proof
490490

491491
```bash
492492
docker compose exec web python manage.py shell -c "import logging; from django.test import Client; from django.contrib.auth import get_user_model; from returns.models import ReturnCase; logging.getLogger('django.request').disabled = True; User = get_user_model(); client = Client(HTTP_HOST='localhost', raise_request_exception=False); user = User.objects.filter(groups__name__iexact='Ops').first() or User.objects.filter(is_superuser=True).first(); first_case = ReturnCase.objects.order_by('id').first(); sparse_case = ReturnCase.objects.filter(order_reference='RH-RUNBOOK-SPARSE').first() or first_case; client.force_login(user); queue = client.get('/ops/'); detail = client.get(f'/ops/{first_case.pk}/'); page_two = client.get('/ops/?page=2'); empty = client.get('/ops/?status=closed&priority=high&search=unlikely_runbook_value'); sparse = client.get(f'/ops/{sparse_case.pk}/'); queue_content = queue.content.decode(); detail_content = detail.content.decode(); empty_content = empty.content.decode(); sparse_content = sparse.content.decode(); print(f'OPS_QUEUE_SMOKE_RENDER_CHECK={queue.status_code == 200 and \"Returns queue\" in queue_content}'); print(f'OPS_DETAIL_SMOKE_RENDER_CHECK={detail.status_code == 200 and first_case.order_reference in detail_content}'); print(f'OPS_QUEUE_PAGE_TWO_CHECK={page_two.status_code == 200 and \"Showing 16-\" in page_two.content.decode()}'); print(f'OPS_QUEUE_EMPTY_STATE_CHECK={\"No cases match these filters\" in empty_content}'); print(f'OPS_DETAIL_EMPTY_DOCUMENTS_CHECK={\"No documents yet\" in sparse_content}'); print(f'OPS_DETAIL_EMPTY_TIMELINE_CHECK={\"No timeline events yet\" in sparse_content}'); print(f'OPS_DETAIL_LOADING_LAYER_CHECK={(\"data-loading-label\" in detail_content) and (\"rh-fragment-panel__status\" in detail_content)}'); print(f'OPS_DETAIL_FRAGMENT_IDS_CHECK={(\"case-status-panel\" in detail_content) and (\"case-notes-panel\" in detail_content)}')"

console/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"title": "See your own cases",
3232
"body": (
3333
"Keep customer-linked returns visible in one place while later "
34-
"sprints add deeper case actions."
34+
"releases add deeper case actions."
3535
),
3636
},
3737
{
@@ -60,7 +60,7 @@
6060
{
6161
"title": "Stay in shared workflow context",
6262
"body": (
63-
"Case summaries remain visible while later sprints add merchant "
63+
"Case summaries remain visible while later product updates add merchant "
6464
"responses and supporting documents."
6565
),
6666
},

core/views/console.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"title": "See your own cases",
1616
"body": (
1717
"Keep customer-linked returns visible in one place while later "
18-
"sprints add deeper case actions."
18+
"releases add deeper case actions."
1919
),
2020
},
2121
{
@@ -44,7 +44,7 @@
4444
{
4545
"title": "Stay in shared workflow context",
4646
"body": (
47-
"Case summaries remain visible while later sprints add merchant "
47+
"Case summaries remain visible while later product updates add merchant "
4848
"responses and supporting documents."
4949
),
5050
},

0 commit comments

Comments
 (0)