149 lines
6.4 KiB
PHP
149 lines
6.4 KiB
PHP
// Edit Invoice Logic
|
|
const parseInvoiceButtonPayload = (btn) => {
|
|
if (!btn || !btn.dataset || !btn.dataset.json) return {};
|
|
try {
|
|
return JSON.parse(btn.dataset.json);
|
|
} catch (error) {
|
|
console.warn('Failed to parse invoice payload from button data.', error);
|
|
return {};
|
|
}
|
|
};
|
|
|
|
const syncSelect2Value = (select) => {
|
|
if (!select) return;
|
|
if (select.classList.contains('select2') && window.jQuery && jQuery.fn && jQuery.fn.select2) {
|
|
jQuery(select).trigger('change');
|
|
}
|
|
};
|
|
|
|
const ensureSelectOption = (selectId, value, label = '') => {
|
|
const select = document.getElementById(selectId);
|
|
if (!select || value === null || value === undefined || String(value) === '') return;
|
|
|
|
const alreadyExists = Array.from(select.options || []).some(option => option.value == String(value));
|
|
if (!alreadyExists) {
|
|
const option = document.createElement('option');
|
|
option.value = String(value);
|
|
option.textContent = label || String(value);
|
|
select.appendChild(option);
|
|
}
|
|
};
|
|
|
|
const setBlankSelectOptionLabel = (select, label = '---') => {
|
|
if (!select) return;
|
|
const emptyOption = Array.from(select.options || []).find(option => option.value === '');
|
|
if (emptyOption) {
|
|
emptyOption.textContent = label;
|
|
}
|
|
};
|
|
|
|
const normalizeEditPaymentType = (paymentType) => {
|
|
let normalized = String(paymentType || 'cash').toLowerCase().replace(/[\s-]+/g, '_');
|
|
if (normalized === 'pos') normalized = 'cash';
|
|
if (!['cash', 'card', 'bank_transfer', 'credit'].includes(normalized)) {
|
|
normalized = 'cash';
|
|
}
|
|
return normalized;
|
|
};
|
|
|
|
const renderEditInvoiceItems = (items) => {
|
|
const tableBody = document.getElementById('editInvoiceItemsTableBody');
|
|
const grandTotalEl = document.getElementById('edit_grandTotal');
|
|
const subtotalEl = document.getElementById('edit_subtotal');
|
|
const totalVatEl = document.getElementById('edit_totalVat');
|
|
|
|
if (!tableBody) return;
|
|
tableBody.innerHTML = '';
|
|
|
|
if (!Array.isArray(items) || items.length === 0) {
|
|
if (typeof recalculate === 'function') {
|
|
recalculate(tableBody, grandTotalEl, subtotalEl, totalVatEl);
|
|
}
|
|
return;
|
|
}
|
|
|
|
items.forEach(item => {
|
|
addItemToTable({
|
|
id: item.item_id || item.id,
|
|
name_en: item.name_en || item.item_name_en || 'Item',
|
|
name_ar: item.name_ar || item.item_name_ar || '',
|
|
sku: item.sku || '',
|
|
vat_rate: item.vat_rate || 0,
|
|
stock_quantity: item.stock_quantity || 0
|
|
}, tableBody, null, null, grandTotalEl, subtotalEl, totalVatEl, {
|
|
quantity: item.quantity,
|
|
unit_price: item.unit_price
|
|
});
|
|
});
|
|
};
|
|
|
|
const populateEditInvoiceModal = (data) => {
|
|
if (!data) return;
|
|
|
|
const invoiceIdInput = document.getElementById('edit_invoice_id');
|
|
const partySelect = document.getElementById('edit_customer_id');
|
|
const invoiceDateInput = document.getElementById('edit_invoice_date');
|
|
const dueDateInput = document.getElementById('edit_due_date');
|
|
const paymentTypeSelect = document.getElementById('edit_payment_type');
|
|
const statusSelect = document.getElementById('edit_status');
|
|
const paidAmountInput = document.getElementById('edit_paid_amount');
|
|
const paidAmountContainer = document.getElementById('editPaidAmountContainer');
|
|
|
|
const partyId = data.customer_id ?? data.supplier_id ?? '';
|
|
const partyLabel = data.party_name || data.customer_name || data.supplier_name || '';
|
|
|
|
ensureSelectOption('edit_customer_id', partyId, partyLabel);
|
|
|
|
if (invoiceIdInput) invoiceIdInput.value = data.id || '';
|
|
if (partySelect) {
|
|
setBlankSelectOptionLabel(partySelect, (partyId === '' && partyLabel) ? partyLabel : '---');
|
|
partySelect.value = partyId;
|
|
syncSelect2Value(partySelect);
|
|
}
|
|
if (invoiceDateInput) invoiceDateInput.value = data.invoice_date || '';
|
|
if (dueDateInput) dueDateInput.value = data.due_date || '';
|
|
if (paymentTypeSelect) paymentTypeSelect.value = normalizeEditPaymentType(data.payment_type);
|
|
if (statusSelect) statusSelect.value = data.status || 'unpaid';
|
|
if (paidAmountInput) paidAmountInput.value = parseFloat(data.paid_amount || 0).toFixed(3);
|
|
if (paidAmountContainer) {
|
|
paidAmountContainer.style.display = data.status === 'partially_paid' ? 'block' : 'none';
|
|
}
|
|
|
|
renderEditInvoiceItems(data.items || []);
|
|
};
|
|
|
|
document.querySelectorAll('.edit-invoice-btn').forEach(btn => {
|
|
btn.addEventListener('click', async function() {
|
|
const fallbackData = parseInvoiceButtonPayload(this);
|
|
const invoiceId = this.dataset.id || fallbackData.id || '';
|
|
const type = this.dataset.type || fallbackData.type || invoiceType || 'sale';
|
|
const tableBody = document.getElementById('editInvoiceItemsTableBody');
|
|
|
|
if (Object.keys(fallbackData).length > 0) {
|
|
populateEditInvoiceModal(fallbackData);
|
|
} else if (tableBody) {
|
|
tableBody.innerHTML = '<tr><td colspan="6" class="text-center"><div class="spinner-border spinner-border-sm text-primary"></div> <span data-en="Loading invoice..." data-ar="جاري تحميل الفاتورة...">Loading invoice...</span></td></tr>';
|
|
}
|
|
|
|
if (!invoiceId) return;
|
|
|
|
try {
|
|
const resp = await fetch(`index.php?action=get_invoice_details&invoice_id=${encodeURIComponent(invoiceId)}&type=${encodeURIComponent(type)}`);
|
|
const data = await resp.json();
|
|
|
|
if (data && data.id) {
|
|
populateEditInvoiceModal(data);
|
|
} else if (data && data.error) {
|
|
throw new Error(data.error);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load invoice details for edit modal.', error);
|
|
if (window.Swal) {
|
|
Swal.fire('Error', 'Failed to load invoice details', 'error');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// View and Print Invoice Logic
|