Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -656,10 +656,17 @@ TEMPLATE = """
|
|
| 656 |
const totalSection = document.getElementById('invoiceTotalSection');
|
| 657 |
const totalAmount = parseFloat(invoiceData.total_amount);
|
| 658 |
const bonusesDeducted = parseFloat(invoiceData.bonuses_deducted || 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 659 |
|
| 660 |
let html = `<div class="total-row"><span>Сумма</span> <span>${totalAmount.toFixed(2)}</span></div>`;
|
| 661 |
if (bonusesDeducted > 0) {
|
| 662 |
-
html += `<div class="total-row"><span>Списано бонусов</span> <span class="deduction">- ${bonusesDeducted.toFixed(2)}</span></div>`;
|
| 663 |
html += `<div class="total-row final"><span>К оплате</span> <span>${(totalAmount - bonusesDeducted).toFixed(2)}</span></div>`;
|
| 664 |
} else {
|
| 665 |
html += `<div class="total-row final"><span>К оплате</span> <span>${totalAmount.toFixed(2)}</span></div>`;
|
|
@@ -1405,20 +1412,22 @@ ADMIN_TEMPLATE = """
|
|
| 1405 |
}
|
| 1406 |
|
| 1407 |
function addNewInvoiceItemRow() {
|
| 1408 |
-
const tableBody = document.getElementById('newInvoiceItemsTable').getElementsByTagName('tbody')[0];
|
| 1409 |
-
const rowIndex = tableBody.rows.length;
|
| 1410 |
newInvoiceItems.push({ product_name: '', quantity: 1, unit_price: 0, item_total: 0 });
|
| 1411 |
renderNewInvoiceItems();
|
| 1412 |
}
|
| 1413 |
|
| 1414 |
function updateInvoiceItem(index, field, value) {
|
| 1415 |
-
if (newInvoiceItems[index])
|
| 1416 |
-
|
| 1417 |
-
|
| 1418 |
-
|
| 1419 |
-
|
| 1420 |
-
|
|
|
|
|
|
|
|
|
|
| 1421 |
}
|
|
|
|
| 1422 |
}
|
| 1423 |
|
| 1424 |
function removeInvoiceItemRow(index) {
|
|
@@ -1431,7 +1440,8 @@ ADMIN_TEMPLATE = """
|
|
| 1431 |
tableBody.innerHTML = '';
|
| 1432 |
newInvoiceItems.forEach((item, index) => {
|
| 1433 |
const newRow = tableBody.insertRow();
|
| 1434 |
-
|
|
|
|
| 1435 |
});
|
| 1436 |
updateNewInvoiceTotal();
|
| 1437 |
}
|
|
@@ -1449,8 +1459,9 @@ ADMIN_TEMPLATE = """
|
|
| 1449 |
let deductAmount = parseFloat(deductBonusesInput.value) || 0;
|
| 1450 |
|
| 1451 |
let cappedDeductAmount = Math.max(0, Math.min(deductAmount, availableBonuses, total));
|
| 1452 |
-
|
| 1453 |
-
|
|
|
|
| 1454 |
}
|
| 1455 |
|
| 1456 |
let finalAmount = total - cappedDeductAmount;
|
|
@@ -1466,7 +1477,7 @@ ADMIN_TEMPLATE = """
|
|
| 1466 |
statusEl.textContent = 'Пользователь не выбран.';
|
| 1467 |
return;
|
| 1468 |
}
|
| 1469 |
-
const itemsToAdd = newInvoiceItems.filter(item => item.product_name && (item.quantity > 0 || item.unit_price > 0));
|
| 1470 |
if (itemsToAdd.length === 0) {
|
| 1471 |
statusEl.style.color = 'var(--admin-danger)';
|
| 1472 |
statusEl.textContent = 'Добавьте хотя бы один товар.';
|
|
|
|
| 656 |
const totalSection = document.getElementById('invoiceTotalSection');
|
| 657 |
const totalAmount = parseFloat(invoiceData.total_amount);
|
| 658 |
const bonusesDeducted = parseFloat(invoiceData.bonuses_deducted || 0);
|
| 659 |
+
const bonusSource = invoiceData.bonus_source_used;
|
| 660 |
+
let bonusSourceText = '';
|
| 661 |
+
if (bonusSource === 'referral') {
|
| 662 |
+
bonusSourceText = ' (от друзей)';
|
| 663 |
+
} else if (bonusSource === 'main') {
|
| 664 |
+
bonusSourceText = ' (основных)';
|
| 665 |
+
}
|
| 666 |
|
| 667 |
let html = `<div class="total-row"><span>Сумма</span> <span>${totalAmount.toFixed(2)}</span></div>`;
|
| 668 |
if (bonusesDeducted > 0) {
|
| 669 |
+
html += `<div class="total-row"><span>Списано бонусов${bonusSourceText}</span> <span class="deduction">- ${bonusesDeducted.toFixed(2)}</span></div>`;
|
| 670 |
html += `<div class="total-row final"><span>К оплате</span> <span>${(totalAmount - bonusesDeducted).toFixed(2)}</span></div>`;
|
| 671 |
} else {
|
| 672 |
html += `<div class="total-row final"><span>К оплате</span> <span>${totalAmount.toFixed(2)}</span></div>`;
|
|
|
|
| 1412 |
}
|
| 1413 |
|
| 1414 |
function addNewInvoiceItemRow() {
|
|
|
|
|
|
|
| 1415 |
newInvoiceItems.push({ product_name: '', quantity: 1, unit_price: 0, item_total: 0 });
|
| 1416 |
renderNewInvoiceItems();
|
| 1417 |
}
|
| 1418 |
|
| 1419 |
function updateInvoiceItem(index, field, value) {
|
| 1420 |
+
if (!newInvoiceItems[index]) return;
|
| 1421 |
+
newInvoiceItems[index][field] = value;
|
| 1422 |
+
const qty = parseFloat(newInvoiceItems[index].quantity) || 0;
|
| 1423 |
+
const price = parseFloat(newInvoiceItems[index].unit_price) || 0;
|
| 1424 |
+
const itemTotal = qty * price;
|
| 1425 |
+
newInvoiceItems[index].item_total = itemTotal;
|
| 1426 |
+
const tableBody = document.getElementById('newInvoiceItemsTable').getElementsByTagName('tbody')[0];
|
| 1427 |
+
if (tableBody.rows[index]) {
|
| 1428 |
+
tableBody.rows[index].querySelector('.item-total-display').textContent = itemTotal.toFixed(2);
|
| 1429 |
}
|
| 1430 |
+
updateNewInvoiceTotal();
|
| 1431 |
}
|
| 1432 |
|
| 1433 |
function removeInvoiceItemRow(index) {
|
|
|
|
| 1440 |
tableBody.innerHTML = '';
|
| 1441 |
newInvoiceItems.forEach((item, index) => {
|
| 1442 |
const newRow = tableBody.insertRow();
|
| 1443 |
+
const productName = item.product_name ? String(item.product_name).replace(/"/g, '"') : '';
|
| 1444 |
+
newRow.innerHTML = `<td><input type="text" placeholder="Название товара" value="${productName}" oninput="updateInvoiceItem(${index}, 'product_name', this.value)"></td><td><input type="number" step="1" min="1" placeholder="1" value="${item.quantity || '1'}" oninput="updateInvoiceItem(${index}, 'quantity', this.value)"></td><td><input type="number" step="0.01" min="0" placeholder="0.00" value="${item.unit_price || ''}" oninput="updateInvoiceItem(${index}, 'unit_price', this.value)"></td><td class="item-total-display">${(item.item_total || 0).toFixed(2)}</td><td><button class="action-btn" onclick="removeInvoiceItemRow(${index})">🗑️</button></td>`;
|
| 1445 |
});
|
| 1446 |
updateNewInvoiceTotal();
|
| 1447 |
}
|
|
|
|
| 1459 |
let deductAmount = parseFloat(deductBonusesInput.value) || 0;
|
| 1460 |
|
| 1461 |
let cappedDeductAmount = Math.max(0, Math.min(deductAmount, availableBonuses, total));
|
| 1462 |
+
|
| 1463 |
+
if (deductAmount > cappedDeductAmount) {
|
| 1464 |
+
deductBonusesInput.value = cappedDeductAmount > 0 ? cappedDeductAmount.toFixed(2) : '';
|
| 1465 |
}
|
| 1466 |
|
| 1467 |
let finalAmount = total - cappedDeductAmount;
|
|
|
|
| 1477 |
statusEl.textContent = 'Пользователь не выбран.';
|
| 1478 |
return;
|
| 1479 |
}
|
| 1480 |
+
const itemsToAdd = newInvoiceItems.filter(item => item.product_name && item.product_name.trim() !== '' && (item.quantity > 0 || item.unit_price > 0));
|
| 1481 |
if (itemsToAdd.length === 0) {
|
| 1482 |
statusEl.style.color = 'var(--admin-danger)';
|
| 1483 |
statusEl.textContent = 'Добавьте хотя бы один товар.';
|