Просмотр исходного кода

mcp: add patch_reservation tool; dev.html: closed range wf, drop dead sms GET

ZiB 4 месяцев назад
Родитель
Сommit
0ec89bfbd0
2 измененных файлов с 23 добавлено и 13 удалено
  1. 13 0
      room_cal/mcp/__init__.py
  2. 10 13
      room_cal/vue/dev.html

+ 13 - 0
room_cal/mcp/__init__.py

@@ -70,6 +70,19 @@ async def set_price(target_date: str, value: float) -> None:
 
 
 
+@mcp.tool()
+async def patch_reservation(uid: str, checkin_date: str, wifi_ssid: str | None = None, wifi_key: str | None = None, door_code: str | None = None) -> dict:
+  """Update guest access fields (wifi_ssid, wifi_key, door_code) on a stored reservation. checkin_date (YYYY-MM-DD) is required to locate the event. Only supplied fields are written. Returns updated ReservationData as a dict."""
+  from dataclasses import asdict
+  result = await Reservation(DEFAULT_CALENDAR_NAME).patch(
+    uid, date.fromisoformat(checkin_date),
+    wifi_ssid=wifi_ssid, wifi_key=wifi_key, door_code=door_code,
+  )
+  if result is None:
+    raise ValueError(f'reservation {uid!r} not found on {checkin_date}')
+  return asdict(result)
+
+
 @mcp.tool()
 async def get_reservation(target_date: str) -> dict | None:
   """Get the reservation covering a date (checkin ≤ date < checkout), or null."""

+ 10 - 13
room_cal/vue/dev.html

@@ -209,6 +209,8 @@
     <div class="cb-group" id="wf-closed-checks"></div>
     <button onclick="doWfSetClosed()">POST /closed</button>
     <button class="del" onclick="doWfDeleteClosed()">DELETE /closed</button>
+    <button onclick="doWfSetClosedRange()">POST /closed range</button>
+    <span class="section-note">range uses both dates</span>
   </div>
   <div class="row">
     <label class="lbl">sync range</label>
@@ -275,13 +277,7 @@
     <label class="lbl">code</label>
     <input id="sms-code" type="text" placeholder="e.g. 123456" style="width:120px">
     <button onclick="doSmsPost()">POST /sms/code</button>
-    <span class="section-note">deliver a code to whoever is polling</span>
-  </div>
-  <div class="row">
-    <label class="lbl">timeout (s)</label>
-    <input id="sms-timeout" type="number" value="30" style="width:60px">
-    <button onclick="doSmsPoll()">GET /sms/code</button>
-    <span class="section-note">long-poll — waits for a code to arrive</span>
+    <span class="section-note">deliver a code to whoever is polling sms_code.txt</span>
   </div>
   <div class="result" id="res-sms"></div>
 
@@ -591,6 +587,13 @@
       show('res-workflows', await api('DELETE', `/workflow/closed/${d}`));
     }
 
+    async function doWfSetClosedRange() {
+      const r = wfRange();
+      if (!r) return;
+      pending('res-workflows');
+      show('res-workflows', await api('POST', `/workflow/closed/${r.d1}/${r.d2}`, { services: getWfCheckedServices() }));
+    }
+
     function wfRange() {
       const d1 = document.getElementById('wf-d1').value;
       const d2 = document.getElementById('wf-d2').value || d1;
@@ -678,12 +681,6 @@
       show('res-sms', await api('POST', '/sms/code', { code }));
     }
 
-    async function doSmsPoll() {
-      const timeout = document.getElementById('sms-timeout').value || 30;
-      pending('res-sms');
-      show('res-sms', await api('GET', `/sms/code?timeout=${timeout}`));
-    }
-
     // ── credentials ──
     async function doCredRefreshAll() {
       pending('res-cred-refresh');