paging: paging groups, *80 intercom, auto-answer headers
/api/paging-groups CRUD (members as memberIds). The generator renders
sp-page-{id} per 03 §6.11 (desk phones only, auto-answer headers via
sp-sub-autoanswer) plus the number in sp-local-numbers. Added the `s`
option so phones already on a call aren't paged, which also keeps a
pager who is a member from being paged themselves. A group with no
members just hangs up.
*80<ext> intercom checks the target first: digits only and an endpoint
in sp-from-ext, else ss-noservice (the spec's one-liner passed
${EXTEN:3} straight into Page()). Both written back into 03.
Web: Paging page (list, drawer form with member checkboxes). Golden
case paging. e2e m8-t4 with baresip phones that honor the headers
(sip_autoanswer): an ordinary call rings, a page is answered by itself
and muted, the busy pager is skipped, *80 is two-way, *80999 refused.
The check on a real Yealink/Grandstream stays open (09).
Task: M8-T4
This commit is contained in:
1 parent
a6c423de97
commit
e95271e694
47 files changed
+1466
-22
No files matched your search
@@ -717,10 +717,14 @@ exten => s,1,Set(__SP_TARGET={number})
|
||||
same => n,Hangup()
|
||||
|
||||
[sp-page-{id}]
|
||||
exten => s,1,Page(PJSIP/101&PJSIP/102,{d if duplex}iqb(sp-sub-autoanswer^s^1),30)
|
||||
exten => s,1,Page(PJSIP/101&PJSIP/102,{d if duplex}iqsb(sp-sub-autoanswer^s^1),30)
|
||||
same => n,Hangup()
|
||||
```
|
||||
Paging only rings desk endpoints (`PJSIP/<ext>`), not `-web`.
|
||||
Paging only rings desk endpoints (`PJSIP/<ext>`), not `-web`. As built (M8-T4): `s` added, so phones
|
||||
already on a call aren't paged; that includes the pager when they're a member themselves. A group
|
||||
with no members is `exten => s,1,Hangup()`. Paging groups aren't call destinations. Golden case
|
||||
`paging`; `scripts/e2e/m8-t4.mjs` pages with real calls (baresip phones that honor the auto-answer
|
||||
headers, like Yealink/Grandstream do; a real desk phone is still to be checked).
|
||||
|
||||
`confbridge_selfphoneng.conf` always contains the admin profile, plus one bridge profile per room:
|
||||
```ini
|
||||
@@ -855,7 +859,13 @@ exten => _*45X.,1,Answer() ; *45<queue> toggle
|
||||
same => n,Hangup()
|
||||
same => n(deny),Playback(ss-noservice)
|
||||
same => n,Hangup()
|
||||
exten => _*80X.,1,Page(PJSIP/${EXTEN:3},db(sp-sub-autoanswer^s^1),30) ; intercom
|
||||
exten => _*80X.,1,Set(T=${FILTER(0-9,${EXTEN:3})}) ; *80<ext> intercom, both ways
|
||||
same => n,GotoIf($["${T}" != "${EXTEN:3}"]?deny)
|
||||
same => n,GotoIf($["${PJSIP_ENDPOINT(${T},context)}" != "sp-from-ext"]?deny) ; desk phones only
|
||||
same => n,Page(PJSIP/${T},db(sp-sub-autoanswer^s^1),30)
|
||||
same => n,Hangup()
|
||||
same => n(deny),Answer()
|
||||
same => n,Playback(ss-noservice)
|
||||
same => n,Hangup()
|
||||
; time condition overrides *31N open, *32N closed, *33N auto (admins only)
|
||||
exten => _*3[123]X,1,Answer()
|
||||
@@ -880,6 +890,8 @@ deletes the AstDB key, stores nothing, and logs an audit entry. Dialplan also
|
||||
limits forwards via `SP_CLASS_<ext>` in `sp-sub-forward`.
|
||||
|
||||
As built (M6-T7): everything above except `*45` (queues) and `*80` (intercom), which come with M8.
|
||||
`*80` (M8-T4) only pages a desk phone: digits only (no `&` sneaking in another channel), and the
|
||||
endpoint must exist with context `sp-from-ext`; anything else plays `ss-noservice`.
|
||||
`*45` (M8-T1) checks `PQMSTATUS`/`UPQMSTATUS`, so a code for a queue the caller isn't an agent of plays
|
||||
`ss-noservice` and stores nothing (the original snippet stored the key and said "logged off" anyway).
|
||||
`*8` also has a dialplan line (`Pickup()`): `pickupexten` only catches it straight from a phone's
|
||||
|
||||
@@ -381,7 +381,7 @@ Admin resources (all `requireAdmin`; standard CRUD = `GET /x`, `POST /x`, `GET /
|
||||
| `/api/holidays` | `POST /import-us-federal {year}` (generates the list in code, no network) |
|
||||
| `/api/announcements` | |
|
||||
| `/api/conferences` | |
|
||||
| `/api/paging-groups` | |
|
||||
| `/api/paging-groups` | members are set via `memberIds: [uuid]` in POST/PATCH (no order). Not a destination, so delete never returns 409 |
|
||||
| `/api/sounds` | upload is `POST /api/sounds?name=&filename=` with the raw file as the body (like greetings, no multipart), `GET /:id/audio`, `PATCH /:id {name}`, `DELETE /:id` (409 with `usedBy`: IVR greeting/invalid sound, announcements, the recording notice), `POST /tts` (M12). M6 lists prompts only; MOH classes and files come with M8 |
|
||||
| `/api/moh-classes` | |
|
||||
| `/api/devices` | `GET /:id/config-preview` (rendered provisioning file, passwords masked) |
|
||||
|
||||
@@ -38,7 +38,7 @@ Left sidebar navigation, in this order:
|
||||
| IVRs (Digital receptionist) | `/admin/ivrs` | Form: number, name, greeting (SoundPicker), keypad grid 0–9 * # where each key gets a DestinationPicker or "unused", timeout, retries, invalid sound, direct dial toggle, timeout and invalid destinations |
|
||||
| Office hours | `/admin/hours` | Time conditions: weekly grid editor (click-drag hours per day) that saves to `open_ranges`; timezone; holidays toggle; open/closed/holiday destinations; override digit; big status chip "Open now / Closed now" with Force open / Force closed / Automatic buttons. Holidays sub-tab: list + "Add US federal holidays for {year}" |
|
||||
| Conferences | `/admin/conferences` | number, name, PIN, admin PIN, max members, record. As built (M8-T3): admins see the PINs in the list (they hand them out); an admin PIN needs a different room PIN |
|
||||
| Paging | `/admin/paging` | number, name, members, duplex |
|
||||
| Paging | `/admin/paging` | number, name, members, duplex. As built (M8-T4): members are checkboxes (no order); the empty state explains `*80<ext>` |
|
||||
| Sounds & music | `/admin/sounds` | Prompts list with play buttons, upload (drag-drop), TTS (M12). MOH classes with their files (M8). An **Announcements** section (play a sound, then a destination) lives here too: no page of its own (M6-T5) |
|
||||
| Phones (devices) | `/admin/devices` | Table: MAC, vendor, model, user, last provisioned. Form: MAC (any format → normalized), vendor, model, extension. Shows the provisioning URL to type into the phone, and "Preview config" |
|
||||
| Contacts | `/admin/contacts` | Company phonebook, CSV import |
|
||||
|
||||
@@ -205,6 +205,7 @@ Legend: 📖 read · 🔨 build · ✅ done when
|
||||
**M8-T2** Parking (`res_parking.conf`, `sp-parkedcalls` include) + parked calls in the live UI + BLF hints for slots.
|
||||
**M8-T3** Conferences with PIN/admin PIN (03 §6.11).
|
||||
**M8-T4** Paging/intercom (`sp-page-*`, `*80`) + auto-answer test on a real Yealink or Grandstream.
|
||||
As built: tested with baresip phones that honor the auto-answer headers (`sip_autoanswer`). **Open:** the check on a real Yealink or Grandstream, when one is available.
|
||||
**M8-T5** MOH classes (03 §8).
|
||||
✅ Golden `queue` case passes. Scenario: 3 callers wait in a queue with 2 agents. One agent pauses with `*45550`. The caller who waits past `max_wait_seconds` goes to the timeout destination. A parked call on 701 can be picked up from another phone.
|
||||
|
||||
|
||||
Reference in new issue
Block a user