- GsmGatewaySmsProvider: GoIP-style HTTP SMS API, per-tenant SIM line from phone_numbers.gateway_port; model-specific bits isolated for easy adaptation (§17.3); failure never breaks the calling flow (logged to sms_log) - Asterisk config generator now emits [gw-line-N] SIP trunk endpoints per assigned SIM, routed straight into the tenant's inbound context (1 SIM = 1 salon §5.1); deterministic per-SIM SIP secrets - docs/HARDWARE_TESTING.md: step-by-step live runbook for the joint session (gateway registration, inbound path, SMS via gateway, operator forwarding codes per m:tel/BH Telecom/HT Eronet, e2e acceptance, rollback) - 5 tests against a mocked gateway API (forwarding-code generator and SIM/port admin UI shipped in M3) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
77 lines
3.8 KiB
Markdown
77 lines
3.8 KiB
Markdown
# M5 — Live hardware test plan (joint session with the founder)
|
||
|
||
Everything below is already written and unit-tested against mocks; this runbook
|
||
verifies it against real hardware: GSM gateway + SIM + operator forwarding.
|
||
Estimated time: 2–3 hours with hardware on site.
|
||
|
||
## 0. Shopping/prep checklist (founder)
|
||
|
||
- [ ] GSM gateway, GoIP/Yeastar class, with **SIP registration** and an
|
||
**HTTP SMS API** (§17.3). 4/8 ports depending on pilot count.
|
||
- [ ] 1 SIM card per pilot salon (verify operator terms for gateway use, §17.4).
|
||
- [ ] Salon's own number reachable for forwarding tests.
|
||
- [ ] Server reachable from the gateway (LAN or VPN), ports 5060/UDP + RTP range.
|
||
|
||
## 1. Gateway → Asterisk registration
|
||
|
||
1. In the super-admin panel → *Brojevi/SIM*: add the SIM's number, set its
|
||
gateway port (line) and operator; assign it to the pilot salon.
|
||
2. Regenerate Asterisk config and reload:
|
||
```bash
|
||
python -m gogo.telephony.asterisk --out ./asterisk/conf \
|
||
--backend http://<backend>:8000 --voice <voice-host>:9092
|
||
docker compose --profile voice restart asterisk
|
||
```
|
||
The config now contains a `[gw-line-<port>]` endpoint. The SIP password is
|
||
deterministic; print it with:
|
||
```bash
|
||
python -c "from gogo.telephony.asterisk import gateway_line_password as p; print(p('<msisdn>'))"
|
||
```
|
||
3. On the gateway, configure line <port>: SIP server = Asterisk host,
|
||
username `gw-line-<port>`, the password from above, register.
|
||
4. Verify: `asterisk -rx 'pjsip show endpoints'` → `gw-line-<port>` **Avail**.
|
||
|
||
## 2. Inbound call path (§5.1)
|
||
|
||
- [ ] Call the SIM's number directly from a mobile → gateway → Asterisk →
|
||
ring group rings → no answer → agent answers. Full conversation books a
|
||
request; check dashboard (Zahtjevi, Pozivi + audio), email, metering.
|
||
- [ ] Answer on a worker softphone → outcome `javilo se osoblje`, no minutes.
|
||
- [ ] Hang up while ringing → missed-call SMS arrives on the caller's phone.
|
||
|
||
## 3. Outbound SMS via gateway HTTP API (§5.5)
|
||
|
||
1. Set in `.env`: `GOGO_SMS_PROVIDER=gsm_gateway`,
|
||
`GOGO_GSM_GATEWAY_URL=http://<gateway-ip>`, `GOGO_GSM_GATEWAY_USER/PASSWORD`.
|
||
2. Restart backend; from a request in the dashboard press *Potvrdi + SMS*.
|
||
- [ ] Confirmation SMS arrives on the client phone, `sms_log.status = sent`.
|
||
- [ ] Unplug the gateway → send again → `sms_log.status = failed` with error,
|
||
request flow otherwise unaffected (SMS failure never blocks §9).
|
||
- [ ] If the gateway is not GoIP-compatible, adapt `_build_request` /
|
||
`_check_response` in `gogo/sms/gateway.py` (isolated on purpose).
|
||
|
||
## 4. Operator conditional forwarding (§5.1, §17.4)
|
||
|
||
On the salon's own phone, per operator (codes shown in dashboard → Telefonija):
|
||
|
||
- [ ] m:tel: activate no-answer forwarding (`**61*<gogo-number>**<sec>#`), call
|
||
the salon number from a third phone, don't answer → call arrives on SIM.
|
||
- [ ] Repeat for busy (`**67*...`) and unreachable (`**62*...`).
|
||
- [ ] `##002#` deactivates everything; `*#61#` shows status.
|
||
- [ ] Verify the same set on BH Telecom and HT Eronet SIMs; note any operator
|
||
quirks in `gogo/telephony/forwarding.py` (per-operator function exists).
|
||
|
||
## 5. End-to-end acceptance (Definition of Done §16 + GSM leg)
|
||
|
||
- [ ] Client calls salon number → no answer → forwarded → agent conversation →
|
||
proposal email/partner push → owner clicks *Riješeno* → done, no SMS.
|
||
- [ ] Second run: owner clicks *Potvrdi termin N + SMS* → client receives SMS
|
||
via the salon's own SIM.
|
||
- [ ] Out-of-hours call → agent answers immediately with the closed-greeting.
|
||
|
||
## 6. Rollback
|
||
|
||
Forwarding off: `##002#` on the salon phone. Gateway line disable: super-admin
|
||
→ Brojevi/SIM → status `blocked` + config regen. The salon's own number keeps
|
||
working untouched throughout — Gogo only ever received forwarded calls.
|