SMOS / modules /SmOS_CC /smos-api.js
0001AMA's picture
Add Mollie card checkout for SmOS_CC delivery and collection, plus staff station screens.
ddd5681 verified
Raw History Blame Contribute Delete
4.36 kB
/** SmOS booking + payments API (same origin on uvicorn; falls back to :7860). */
window.SmOS_API = (function () {
const FALLBACK = "http://127.0.0.1:7860";
const MODULE_ID = (window.SmOS_Module && window.SmOS_Module.id) || "SmOS_CC";
function bases() {
const list = [];
if (location.origin && !location.origin.startsWith("file:")) list.push(location.origin);
if (!list.includes(FALLBACK)) list.push(FALLBACK);
return list;
}
async function postBooking(payload) {
const body = { module_id: MODULE_ID, ...payload };
let lastErr = null;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/bookings`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (res.ok) return await res.json();
const err = await res.json().catch(() => ({}));
const detail = err.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Booking API unavailable");
}
async function createMolliePayment(payload) {
const body = { module_id: MODULE_ID, ...payload };
let lastErr = null;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/SmOS_CC/mollie/create`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
if (res.status === 400 || res.status === 503) break;
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Mollie checkout unavailable");
}
async function mollieStatus(paymentId) {
let lastErr = null;
const q = `?payment_id=${encodeURIComponent(paymentId || "")}`;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/SmOS_CC/mollie/status${q}`, {
cache: "no-store",
});
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Mollie status unavailable");
}
async function occupiedTables(date) {
let lastErr = null;
const q = date ? `?date=${encodeURIComponent(date)}` : "";
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/${MODULE_ID}/tables/occupied${q}`);
if (res.ok) {
const data = await res.json();
return Array.isArray(data.occupied) ? data.occupied.map(String) : [];
}
lastErr = new Error(`HTTP ${res.status}`);
} catch (e) {
lastErr = e;
}
}
if (lastErr) console.warn("occupiedTables", lastErr);
return [];
}
async function lookupAddresses(postcode) {
let lastErr = null;
const q = `?postcode=${encodeURIComponent(postcode || "")}`;
for (const base of bases()) {
try {
const res = await fetch(`${base}/api/modules/${MODULE_ID}/addresses${q}`);
const data = await res.json().catch(() => ({}));
if (res.ok) return data;
const detail = data.detail;
const msg = Array.isArray(detail)
? detail.map((d) => d.msg || d).join("; ")
: detail || `HTTP ${res.status}`;
lastErr = new Error(msg);
if (res.status === 400 || res.status === 404 || res.status === 503) break;
} catch (e) {
lastErr = e;
}
}
throw lastErr || new Error("Address lookup unavailable");
}
return {
postBooking,
createMolliePayment,
mollieStatus,
occupiedTables,
lookupAddresses,
bases,
moduleId: MODULE_ID,
};
})();