-
-
- ${payment.method_name}:
- ${payment.amount.toFixed(2)} руб.
-
+ // Редактируемая строка (без системы fixed/unfixed)
+ const methodsOptions = this.paymentMethods.map(m =>
+ `
`
+ ).join('');
+
+ return `
+
+
+
+
+
+
+
- `;
- } else {
- // Редактируемая строка
- const methodsOptions = this.paymentMethods.map(m =>
- `
`
- ).join('');
-
- return `
-
-
-
-
-
-
-
-
-
-
-
-
- `;
- }
+
+ `;
}).join('');
// Обновляем подсказку об остатке
@@ -254,14 +228,8 @@ export class PaymentWidget {
input.addEventListener('input', (e) => {
const index = parseInt(e.target.dataset.index);
this.payments[index].amount = parseFloat(e.target.value) || 0;
- });
- });
-
- // Обработчик подтверждения (галочка)
- document.querySelectorAll('.confirm-payment-row').forEach(btn => {
- btn.addEventListener('click', (e) => {
- const index = parseInt(e.target.closest('button').dataset.index);
- this.confirmPaymentRow(index);
+ // Real-time обновление остатка!
+ this.updateRemainingHint();
});
});
@@ -276,7 +244,10 @@ export class PaymentWidget {
// Обработчик кнопки "Добавить еще"
const addRowBtn = document.getElementById(`${this.containerId}-add-row-btn`);
if (addRowBtn) {
- addRowBtn.addEventListener('click', () => this.addPaymentRow());
+ // Используем replaceWith для пересоздания элемента и удаления всех обработчиков
+ const newBtn = addRowBtn.cloneNode(true);
+ addRowBtn.replaceWith(newBtn);
+ newBtn.addEventListener('click', () => this.addPaymentRow());
}
}
@@ -331,50 +302,6 @@ export class PaymentWidget {
// СТАРЫЕ МЕТОДЫ addPayment(), removePayment() и updatePaymentsList() УДАЛЕНЫ
// Теперь используются новые методы для построчного UI
- confirmPaymentRow(index) {
- const payment = this.payments[index];
- const errorEl = document.querySelector(`.payment-error[data-index="${index}"]`);
-
- // Валидация
- if (!payment.method_id) {
- errorEl.textContent = 'Выберите способ оплаты';
- errorEl.style.display = 'block';
- return;
- }
-
- if (!payment.amount || payment.amount <= 0) {
- errorEl.textContent = 'Введите сумму больше 0';
- errorEl.style.display = 'block';
- return;
- }
-
- // Проверка превышения остатка
- const totalOtherPayments = this.payments
- .filter((p, i) => i !== index && p.fixed)
- .reduce((sum, p) => sum + p.amount, 0);
-
- if (totalOtherPayments + payment.amount > this.order.amount_due) {
- const maxAmount = this.order.amount_due - totalOtherPayments;
- errorEl.textContent = `Максимум: ${maxAmount.toFixed(2)} руб.`;
- errorEl.style.display = 'block';
- return;
- }
-
- // Проверка кошелька
- if (payment.method_code === 'account_balance' && this.customer) {
- if (payment.amount > this.customer.wallet_balance) {
- errorEl.textContent = `Недостаточно средств (${this.customer.wallet_balance.toFixed(2)} руб.)`;
- errorEl.style.display = 'block';
- return;
- }
- }
-
- // Все ОК - фиксируем
- errorEl.style.display = 'none';
- payment.fixed = true;
- this.renderPaymentRows();
- }
-
removePaymentRow(index) {
this.payments.splice(index, 1);
@@ -394,21 +321,27 @@ export class PaymentWidget {
const totalPaid = this.getTotalPayments();
const remaining = this.order.amount_due - totalPaid;
- if (remaining <= 0) {
+ if (totalPaid > this.order.amount_due) {
+ // Превышение суммы
+ const excess = totalPaid - this.order.amount_due;
+ hintEl.innerHTML = '
⚠ Превышение: +' +
+ excess.toFixed(2) + ' руб.';
+ if (addRowBtn) addRowBtn.style.display = 'none';
+ } else if (remaining <= 0) {
+ // Точная оплата
hintEl.innerHTML = '
✅ Оплачено полностью: ' +
this.order.amount_due.toFixed(2) + ' руб.';
- // СКРЫТЬ кнопку добавления
if (addRowBtn) addRowBtn.style.display = 'none';
} else {
+ // Осталось оплатить
hintEl.textContent = 'Осталось оплатить: ' + remaining.toFixed(2) + ' руб.';
- // ПОКАЗАТЬ кнопку добавления
if (addRowBtn) addRowBtn.style.display = 'block';
}
}
getTotalPayments() {
return this.payments
- .filter(p => p.fixed) // Считаем только зафиксированные!
+ .filter(p => p.method_id) // Считать только если выбран способ оплаты
.reduce((sum, p) => sum + p.amount, 0);
}
@@ -439,21 +372,31 @@ export class PaymentWidget {
} else {
// Смешанная оплата
- const fixedPayments = this.payments.filter(p => p.fixed);
+ const validPayments = this.payments.filter(p => p.method_id && p.amount > 0);
- if (fixedPayments.length === 0) {
+ if (validPayments.length === 0) {
throw new Error('Добавьте хотя бы один платеж');
}
+ // Проверить незавершенные платежи
+ const incompletePayments = this.payments.filter(p =>
+ (p.method_id && !p.amount) || (!p.method_id && p.amount)
+ );
+
+ if (incompletePayments.length > 0) {
+ throw new Error('Заполните все поля или удалите незавершенные строки');
+ }
+
const total = this.getTotalPayments();
if (total > this.order.amount_due) {
- throw new Error(`Сумма платежей превышает остаток к оплате (${this.order.amount_due.toFixed(2)} руб.)`);
+ const excess = total - this.order.amount_due;
+ throw new Error(`Сумма платежей превышает остаток к оплате на ${excess.toFixed(2)} руб.`);
}
// Проверка кошелька
if (this.customer) {
- const walletPayments = fixedPayments.filter(p => p.method_code === 'account_balance');
+ const walletPayments = validPayments.filter(p => p.method_code === 'account_balance');
const walletTotal = walletPayments.reduce((sum, p) => sum + p.amount, 0);
if (walletTotal > this.customer.wallet_balance) {
@@ -481,9 +424,9 @@ export class PaymentWidget {
notes: ''
}];
} else {
- // Смешанная оплата - берем только зафиксированные
+ // Смешанная оплата - берем только заполненные
paymentsData = this.payments
- .filter(p => p.fixed)
+ .filter(p => p.method_id && p.amount > 0)
.map(p => ({
payment_method: p.method_code,
amount: p.amount,