18 lines
3.6 KiB
JavaScript
18 lines
3.6 KiB
JavaScript
/* portal/commerce/public/order-detail.js — 주문 상세: 상태·금액·입금 안내·다음 단계·취소 가능 단계·남는 서비스. 처리 중이면 주기 갱신. */
|
|||
|
|
(() => {
|
||
|
|
const el = document.getElementById('order'); const esc = aw.esc; const money = (n, c) => Number(n).toLocaleString('ko-KR') + (c === 'KRW' ? '원' : ' ' + c);
|
||
|
|
async function load() {
|
||
|
|
try { const { order: o } = await aw.api('GET', `/api/commerce/orders/${el.dataset.id}`); const pi = o.payment_instructions || {}; const kind = o.status === 'approved' ? 'done' : ['rejected', 'expired', 'cancelled'].includes(o.status) ? 'failed' : 'waiting';
|
||
|
|
el.innerHTML = `<div class="card"><div class="ph-row"><span class="badge ${kind}">${kind === 'done' ? '✔' : kind === 'failed' ? '✘' : '◔'} ${esc(o.statusLabel)}</span><span class="sub">마지막 갱신 ${aw.fmt(o.updated_at)}</span></div><p>${esc(o.nextStep)}</p>${o.remaining ? `<p class="sub">${esc(o.remaining)}</p>` : ''}
|
||
|
|
<dl class="kv"><dt>주문 번호</dt><dd class="mono">${esc(o.order_no)}</dd><dt>종류</dt><dd>${esc({ new: '신규', renewal: '갱신', downsize: '축소' }[o.kind] || o.kind)}</dd><dt>금액</dt><dd>${money(o.amount, o.currency)} + 세금 ${money(o.tax, o.currency)} = <b>${money(o.total, o.currency)}</b></dd><dt>결제 방식</dt><dd>계좌 이체(수동 결제 확인)</dd>${o.due_at ? `<dt>입금 기한</dt><dd>${aw.fmt(o.due_at)}</dd>` : ''}${o.paid_at ? `<dt>입금 확인</dt><dd>${aw.fmt(o.paid_at)}</dd>` : ''}${o.approved_at ? `<dt>승인</dt><dd>${aw.fmt(o.approved_at)}</dd>` : ''}<dt>취소 가능 단계</dt><dd>${esc(o.lastCancellableStep)}</dd></dl>
|
||
|
|
${o.status === 'awaiting_payment' ? `<h3>입금 안내</h3><p>${esc(pi.bank || '')} <span class="copy" data-action="copy" data-copy="${esc(pi.account || '')}">${esc(pi.account || '')}</span> (예금주 ${esc(pi.holder || '')})</p><p class="sub">${esc(pi.note || '')}</p>` : ''}
|
||
|
|
<table class="r"><thead><tr><th>항목</th><th>수량</th><th>적용 대상</th><th>단가</th><th>세금</th><th>합계</th></tr></thead><tbody>${o.items.map((i) => `<tr><td data-l="항목">${esc(i.name)}</td><td data-l="수량">${i.qty}</td><td data-l="대상">${i.target_type === 'site' ? '사이트 ' + esc(i.target_id || '') : '사용자 그룹'}</td><td data-l="단가">${money(i.unit_price, o.currency)}</td><td data-l="세금">${money(i.tax, o.currency)}</td><td data-l="합계">${money(i.amount + i.tax, o.currency)}</td></tr>`).join('')}</tbody></table>
|
||
|
|
${o.policyNotes ? `<p class="sub">입금 기한 ${o.policyNotes.paymentDeadlineDays}일 · 미납 ${o.policyNotes.restrictionAfterUnpaidDays}일 후 ${esc(o.policyNotes.restrictionEffect || '')}</p>` : ''}
|
||
|
|
<div class="actions"><a class="btn" href="/billing/invoice/${esc(o.id)}" target="_blank">${o.status === 'approved' ? '영수증' : '청구서'} 보기</a>${o.canCancel ? '<button class="btn danger" id="cancel">주문 취소</button>' : ''}${['rejected', 'expired'].includes(o.status) ? '<a class="btn primary" href="/products">다시 주문</a><a class="btn" href="/help">문의</a>' : ''}</div></div>`;
|
||
|
|
const c = el.querySelector('#cancel'); if (c) c.onclick = async () => { if (!(await aw.confirmDanger({ title: '주문 취소', target: o.order_no, impacts: ['권리 변화 없음', '입금한 경우 운영자에게 환불을 문의하세요'], confirmLabel: '취소' }))) return; try { await aw.api('POST', `/api/commerce/orders/${o.id}/cancel`); load(); } catch (e) { aw.toast(e.message); } };
|
||
|
|
return kind === 'waiting';
|
||
|
|
} catch (e) { aw.state(el, e.status === 404 ? 'empty' : 'failed', e.message, { retry: load }); return false; }
|
||
|
|
}
|
||
|
|
aw.poll(load, 10000);
|
||
|
|
})();
|