const state = { companyId: null, propertyGroupId: null, rooms: [], }; function escapeHtml(s) { return String(s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } function formatPrice(n) { if (n == null) return '—'; return `${Number(n).toLocaleString('ko-KR')}원`; } function formatStatus(open) { if (open == null) return '—'; return open ? '예약가능' : '마감'; } function formatDt(iso) { return formatUtcDateTime(iso); } function formatMarkupBadgeLabel(amount, { compact = false } = {}) { if (amount == null || amount === 0) return null; const abs = Math.abs(Number(amount)); const sign = Number(amount) >= 0 ? '+' : '-'; if (compact) { if (abs >= 10000) return `${sign}${Math.round(abs / 10000)}만`; if (abs >= 1000) return `${sign}${Math.round(abs / 1000)}천`; return `${sign}${abs.toLocaleString('ko-KR')}`; } return `${sign}${abs.toLocaleString('ko-KR')}`; } function markupBadgeLabel(row) { const amountLabel = formatMarkupBadgeLabel(row?.markup_amount); if (amountLabel) return amountLabel; if (row?.markup_type === 'percent' && row?.markup_value != null) { const v = Number(row.markup_value); return `${v >= 0 ? '+' : ''}${v}%`; } if (row?.markup_type === 'fixed' && row?.markup_value != null) { return formatMarkupBadgeLabel(Number(row.markup_value)) || 'M'; } return 'M'; } function renderRuleBadges(row) { if (!row?.rule_kind) return '—'; const badges = []; if (row.rule_kind === 'hardblock' || row.rule_kind === 'hardblock_markup') { badges.push('HB'); } if (row.rule_kind === 'markup' || row.rule_kind === 'hardblock_markup') { const label = markupBadgeLabel(row); badges.push(`${escapeHtml(label)}`); } return `${badges.join('')}`; } function defaultDateRange() { const end = new Date(); const start = new Date(); start.setDate(start.getDate() - 14); const fmt = (d) => { const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); return `${y}-${m}-${day}`; }; return { start: fmt(start), end: fmt(end) }; } function renderRooms() { const sel = document.getElementById('histRoomFilter'); const current = sel.value; sel.innerHTML = ''; state.rooms.forEach((r) => { const opt = document.createElement('option'); opt.value = r.id; opt.textContent = r.display_name; sel.appendChild(opt); }); if (current && state.rooms.some((r) => r.id === current)) { sel.value = current; } } function renderRows(items) { const body = document.getElementById('histTableBody'); const summary = document.getElementById('histSummary'); if (!items.length) { body.innerHTML = '