/**
* np-ttn.js — Оформлення ТТН Нової Пошти для CarpetUA
* Підключити:
*/
window.NovaPoshta = (() => {
'use strict';
// Мапа ФОПів із їхніми унікальними "Ref" відправника
const FOP_MAP = {
'БІЛА': { SenderRef: '1501a6cd-f741-11ea-8513-b88303659df5', EDRPOU: '3250916726' },
'ПРИЩЕНКО': { SenderRef: '14fa7192-f741-11ea-8513-b88303659df5', EDRPOU: '3142312442' },
'ЗВАРИЧ': { SenderRef: '14f42298-f741-11ea-8513-b88303659df5', EDRPOU: '2818821181' },
};
// Місто відправника — Хмельницький
const SENDER_CITY_REF = 'db5c88ac-391c-11dd-90d9-001a92567626';
// Ваше 1-ше відділення у Хмельницькому
const SENDER_BRANCH_REF = '511fd008-e1c2-11e3-8c4a-0050568002cf';
let _order = null; // поточне замовлення
function _getOrders() {
try { if (typeof orders !== 'undefined' && Array.isArray(orders)) return orders; } catch(e){}
return [];
}
function openModal(orderId) {
const list = _getOrders();
const o = list.find(x => x.id === orderId);
if (!o) {
try {
const cid = typeof currentOrderId !== 'undefined' ? currentOrderId : null;
if (cid) {
const o2 = list.find(x => x.id === cid);
if (o2) { _open(o2); return; }
}
} catch(e){}
alert('Замовлення не знайдено. Збережіть замовлення і спробуйте знову.');
return;
}
_open(o);
}
function _open(order) {
if (!FOP_MAP[order.fop]) {
alert('Оберіть ФОП перед оформленням ТТН');
return;
}
_order = order;
_ensureModal();
_renderForm(order);
document.getElementById('np-ttn-modal').classList.add('open');
}
function closeModal() {
const m = document.getElementById('np-ttn-modal');
if (m) m.classList.remove('open');
}
function _renderForm(order) {
const total = (order.products || []).reduce((s, p) => s + ((+p.qty) * (+p.price)), 0);
const prepay = order.paymentType === 'partial' ? (parseFloat(order.prepay) || 0) : 0;
const cod = order.paymentType === 'partial' ? Math.max(0, total - prepay) : 0;
const canCOD = order.fop === 'БІЛА' && order.paymentType === 'partial' && cod > 0;
const fop = FOP_MAP[order.fop];
const addInfo = (order.products || [])
.filter(p => p.name)
.map(p => `${p.name}${+p.qty > 1 ? ' x' + p.qty : ''}`)
.join(', ');
const recipientName = [order.lastName, order.firstName].filter(Boolean).join(' ');
const today = new Date().toISOString().split('T')[0];
const fmtU = n => Math.round(n).toLocaleString('uk-UA') + ' ₴';
document.getElementById('np-ttn-modal-body').innerHTML = `
`;
}
let _ct;
function _cs(q) {
clearTimeout(_ct);
const drop = document.getElementById('npt-city-drop');
if (!drop) return;
if (q.length < 2) { drop.style.display = 'none'; return; }
_ct = setTimeout(async () => {
try {
const res = await _post('np_search_city', { query: q });
const items = res?.data?.[0]?.Addresses || [];
drop.innerHTML = items.length
? items.slice(0,10).map(it => `${_e(it.Present || it.MainDescription)}
`).join('')
: 'Нічого не знайдено
';
drop.style.display = 'block';
} catch(e) { console.error('NP city search', e); }
}, 350);
}
function _sc(name, ref) {
_val('npt-city', name);
_val('npt-city-ref', ref);
_hide('npt-city-drop');
const b = document.getElementById('npt-branch');
if (b) { b.disabled = false; b.placeholder = 'Пошук відділення...'; b.value = ''; }
_val('npt-branch-ref', '');
}
let _bt;
function _bs(q) {
clearTimeout(_bt);
const cityRef = document.getElementById('npt-city-ref')?.value;
const drop = document.getElementById('npt-branch-drop');
if (!cityRef || !drop) return;
_bt = setTimeout(async () => {
try {
const res = await _post('np_search_warehouse', { cityRef, query: q });
const items = res?.data || [];
drop.innerHTML = items.length
? items.slice(0,20).map(it => `${_e(it.Description)}
`).join('')
: 'Нічого не знайдено
';
drop.style.display = 'block';
} catch(e) { console.error('NP branch search', e); }
}, 350);
}
function _sb(name, ref) {
_val('npt-branch', name);
_val('npt-branch-ref', ref);
_hide('npt-branch-drop');
}
async function createTTN() {
const order = _order;
if (!order) return;
const btn = document.getElementById('npt-btn');
if (btn) { btn.disabled = true; btn.textContent = '⏳ Створення...'; }
try {
const fop = FOP_MAP[order.fop];
const phone = document.getElementById('npt-phone')?.value.replace(/\D/g,'') || '';
const name = document.getElementById('npt-name')?.value.trim() || '';
const cref = document.getElementById('npt-city-ref')?.value.trim() || '';
const bref = document.getElementById('npt-branch-ref')?.value.trim() || '';
if (!phone || phone.length < 9) throw new Error('Введіть коректний телефон отримувача');
if (!name) throw new Error('Введіть ПІБ отримувача');
if (!cref) throw new Error('Оберіть місто');
if (!bref) throw new Error('Оберіть відділення');
const result = await _post('np_create_ttn', {
fopKey: order.fop,
orgRef: fop.SenderRef, // Передаємо ID ФОПа
senderCityRef: SENDER_CITY_REF,
senderBranchRef: SENDER_BRANCH_REF,
cityRef: cref,
branchRef: bref,
recipientName: name,
recipientPhone: '380' + phone.slice(-9),
description: document.getElementById('npt-desc')?.value.trim() || 'Килим',
cost: parseFloat(document.getElementById('npt-cost')?.value) || 0,
weight: parseFloat(document.getElementById('npt-weight')?.value) || 1,
seats: parseInt(document.getElementById('npt-seats')?.value) || 1,
orderNum: document.getElementById('npt-onum')?.value.trim() || '',
addInfo: document.getElementById('npt-info')?.value.trim() || '',
sendDate: document.getElementById('npt-date')?.value || '',
codValue: parseFloat(document.getElementById('npt-cod')?.value) || 0,
});
if (result?.success && result?.data?.[0]) {
const num = result.data[0].IntDocNumber || result.data[0].Ref || '—';
_result(`
✅ ТТН успішно створено!
${_e(num)}
Вартість: ${result.data[0].CostOnSite || '—'} ₴
`);
try {
const list = _getOrders();
const o = list.find(x => x.id === order.id);
if (o) {
o.npTTN = num;
if (typeof saveOrderServer === 'function') saveOrderServer();
}
} catch(e) {}
if (btn) btn.textContent = '✅ Готово';
} else {
throw new Error(result?.errors?.[0] || result?.error || JSON.stringify(result));
}
} catch(e) {
_result(`❌ ${_e(e.message)}
`);
if (btn) { btn.disabled = false; btn.textContent = '📋 Створити ТТН'; }
}
}
function _val(id, v) { const el = document.getElementById(id); if (el) el.value = v; }
function _hide(id) { const el = document.getElementById(id); if (el) el.style.display = 'none'; }
function _result(html) {
const el = document.getElementById('npt-result');
if (el) { el.innerHTML = html; el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }
}
function _e(s) { return String(s ?? '').replace(/&/g,'&').replace(/"/g,'"').replace(//g,'>'); }
function _eq(s) { return String(s ?? '').replace(/\\/g,'\\\\').replace(/'/g,"\\'"); }
async function _post(action, data) {
const r = await fetch(`api.php?action=${action}`, {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data),
});
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
}
function _ensureModal() {
if (document.getElementById('np-ttn-modal')) return;
const style = document.createElement('style');
style.textContent = `
._npt-drop { position:absolute;top:100%;left:0;right:0;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);max-height:200px;overflow-y:auto;z-index:99999;box-shadow:var(--shadow); }
._npt-item { padding:8px 12px;cursor:pointer;font-size:12px;border-bottom:1px solid var(--border); }
._npt-item:hover { background:var(--accent-glow);color:var(--accent); }
`;
document.head.appendChild(style);
const el = document.createElement('div');
el.id = 'np-ttn-modal';
el.className = 'modal-overlay';
el.innerHTML = `
`;
document.body.appendChild(el);
el.addEventListener('click', e => { if (e.target === el) closeModal(); });
document.addEventListener('click', e => {
if (!e.target.closest('#npt-city,#npt-city-drop')) _hide('npt-city-drop');
if (!e.target.closest('#npt-branch,#npt-branch-drop')) _hide('npt-branch-drop');
}, true);
}
return { openModal, closeModal, createTTN, _cs, _sc, _bs, _sb };
})();