/**
* Billing UI — Spec 023 (conta cliente modal + overview badge)
*/
const DeskBilling = (() => {
const API = '/api';
function esc(s) {
return String(s ?? '').replace(/&/g, '&').replace(//g, '>');
}
async function api(path, options = {}) {
const res = await fetch(`${API}${path}`, {
...options,
headers: { ...authHeaders(), 'Content-Type': 'application/json', ...(options.headers || {}) },
});
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).detail || res.statusText);
return res.json();
}
function closeModal() {
document.querySelector('.billing-modal-backdrop')?.remove();
}
async function openAccountModal(domain) {
closeModal();
const acc = await api(`/v1/billing/accounts/by-domain/${encodeURIComponent(domain)}`);
const backdrop = document.createElement('div');
backdrop.className = 'billing-modal-backdrop';
backdrop.innerHTML = `
Conta do cliente — ${esc(domain)}
- Estado
- ${esc(acc.billing_state)}
- Razão social
- ${esc(acc.legal_name || acc.trade_name || '—')}
- Email cobrança
- ${esc(acc.email_billing || '—')}
- CNPJ/CPF
- ${esc(acc.tax_id || '—')}
- Recorrência
- ${acc.recurrence_active ? '✅ ativa' : '—'}
FOSSBilling 💳
· Odoo
${canManageVm112Domains?.() ? `` : ''}
`;
document.body.appendChild(backdrop);
backdrop.addEventListener('click', (e) => { if (e.target === backdrop) closeModal(); });
backdrop.querySelector('[data-billing-close]')?.addEventListener('click', closeModal);
backdrop.querySelector('[data-billing-ativate]')?.addEventListener('click', async () => {
await api(`/v1/billing/accounts/${acc.id}`, {
method: 'PATCH',
body: JSON.stringify({ recurrence_active: true, billing_state: 'billing_active' }),
});
closeModal();
if (state.view === 'overview-home') await renderOverviewHome();
});
}
return { openAccountModal, closeModal };
})();
window.DeskBilling = DeskBilling;