Přepočítávání a GUI faktury.
parent
3257006a02
commit
e1da2619a8
|
|
@ -69,7 +69,7 @@
|
|||
<th style="width: 90px;">Jedn.</th>
|
||||
<th style="width: 130px;">Cena/Jedn.</th>
|
||||
<th style="width: 100px;">Sleva %</th>
|
||||
<th style="width: 130px;" class="text-end">Celkem</th>
|
||||
<th style="width: 170px;" class="text-end">Celkem</th>
|
||||
<th style="width: 50px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -80,11 +80,11 @@
|
|||
<i class="bi bi-grip-vertical text-muted fs-5"></i>
|
||||
</td>
|
||||
<td data-label="Název"><input type="text" name="polozky[{$index}][NAZEV]" value="{$p->NAZEV}" class="form-control item-nazev" placeholder="Začněte psát název práce nebo zboží" required autocomplete="off"></td>
|
||||
<td data-label="Počet"><input type="number" step="0.01" name="polozky[{$index}][POCET]" value="{$p->POCET}" class="form-control item-pocet text-end" required></td>
|
||||
<td data-label="Počet"><input type="number" step="any" name="polozky[{$index}][POCET]" value="{$p->POCET}" class="form-control item-pocet text-end" required></td>
|
||||
<td data-label="Jedn."><input type="text" name="polozky[{$index}][JEDNOTKA]" value="{$p->JEDNOTKA}" class="form-control"></td>
|
||||
<td data-label="Cena/Jedn."><input type="number" step="0.01" name="polozky[{$index}][CENA_JEDNOTKA]" value="{$p->CENA_JEDNOTKA}" class="form-control item-cena text-end" required></td>
|
||||
<td data-label="Sleva %"><input type="number" step="0.1" name="polozky[{$index}][SLEVA]" value="{$p->SLEVA}" class="form-control item-sleva text-end"></td>
|
||||
<td data-label="Celkem" class="text-end fw-bold item-celkem-text">{$p->CENA|number:2, ',', ' '} CZK</td>
|
||||
<td data-label="Celkem"><input type="number" step="0.01" value="{$p->CENA}" class="form-control item-celkem text-end fw-bold" title="Úprava přepočítá počet"></td>
|
||||
<td class="text-center cell-actions">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm btn-remove-row"><i class="bi bi-trash"></i></button>
|
||||
</td>
|
||||
|
|
@ -94,8 +94,7 @@
|
|||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" class="text-end fw-bold fs-5 cell-span">Celková částka:</td>
|
||||
<td class="text-end fw-bold fs-5 text-primary" id="total-sum">0,00 CZK</td>
|
||||
<td class="cell-actions"></td>
|
||||
<td colspan="2" class="text-end fw-bold fs-5 text-primary text-nowrap" id="total-sum">0,00 CZK</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
|
@ -244,24 +243,66 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
});
|
||||
}
|
||||
|
||||
// 3. Výpočet součtů
|
||||
// 3. Výpočet součtů (celkem ← počet × cena × (1 − sleva))
|
||||
function roundMoney(value) {
|
||||
return Math.round((value + Number.EPSILON) * 100) / 100;
|
||||
}
|
||||
|
||||
function roundPocet(value) {
|
||||
return Math.round((value + Number.EPSILON) * 10000) / 10000;
|
||||
}
|
||||
|
||||
function rowCelkem(row) {
|
||||
const pocet = parseFloat(row.querySelector('.item-pocet').value) || 0;
|
||||
const cena = parseFloat(row.querySelector('.item-cena').value) || 0;
|
||||
const sleva = parseFloat(row.querySelector('.item-sleva').value) || 0;
|
||||
return (pocet * cena) * (1 - (sleva / 100));
|
||||
}
|
||||
|
||||
function calculateTotals() {
|
||||
let grandTotal = 0;
|
||||
|
||||
document.querySelectorAll('.item-row').forEach(row => {
|
||||
const pocet = parseFloat(row.querySelector('.item-pocet').value) || 0;
|
||||
const cena = parseFloat(row.querySelector('.item-cena').value) || 0;
|
||||
const sleva = parseFloat(row.querySelector('.item-sleva').value) || 0;
|
||||
|
||||
const celkem = (pocet * cena) * (1 - (sleva / 100));
|
||||
const celkem = rowCelkem(row);
|
||||
grandTotal += celkem;
|
||||
|
||||
row.querySelector('.item-celkem-text').textContent = celkem.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' CZK';
|
||||
const celkemInput = row.querySelector('.item-celkem');
|
||||
if (celkemInput && document.activeElement !== celkemInput) {
|
||||
celkemInput.value = roundMoney(celkem).toFixed(2);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('total-sum').textContent = grandTotal.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' CZK';
|
||||
}
|
||||
|
||||
// Úprava celkově: přepočítá počet, cena/jedn. a sleva zůstávají
|
||||
function recalculatePocetFromCelkem(row) {
|
||||
const celkem = parseFloat(row.querySelector('.item-celkem').value) || 0;
|
||||
const cena = parseFloat(row.querySelector('.item-cena').value) || 0;
|
||||
const sleva = parseFloat(row.querySelector('.item-sleva').value) || 0;
|
||||
const faktor = cena * (1 - (sleva / 100));
|
||||
const pocetInput = row.querySelector('.item-pocet');
|
||||
|
||||
if (!pocetInput || Math.abs(faktor) < 1e-9) {
|
||||
return;
|
||||
}
|
||||
|
||||
pocetInput.value = String(roundPocet(celkem / faktor));
|
||||
}
|
||||
|
||||
function updateGrandTotalFromInputs() {
|
||||
let grandTotal = 0;
|
||||
document.querySelectorAll('.item-row').forEach(row => {
|
||||
const celkemInput = row.querySelector('.item-celkem');
|
||||
if (celkemInput && document.activeElement === celkemInput) {
|
||||
grandTotal += parseFloat(celkemInput.value) || 0;
|
||||
} else {
|
||||
grandTotal += rowCelkem(row);
|
||||
}
|
||||
});
|
||||
document.getElementById('total-sum').textContent = grandTotal.toLocaleString('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' CZK';
|
||||
}
|
||||
|
||||
function fold(value) {
|
||||
return String(value).normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
|
||||
}
|
||||
|
|
@ -593,11 +634,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
<i class="bi bi-grip-vertical text-muted fs-5"></i>
|
||||
</td>
|
||||
<td data-label="Název"><input type="text" name="polozky[${rowIndex}][NAZEV]" class="form-control item-nazev" placeholder="Začněte psát název práce nebo zboží" required autocomplete="off"></td>
|
||||
<td data-label="Počet"><input type="number" step="0.01" name="polozky[${rowIndex}][POCET]" value="1" class="form-control item-pocet text-end" required></td>
|
||||
<td data-label="Počet"><input type="number" step="any" name="polozky[${rowIndex}][POCET]" value="1" class="form-control item-pocet text-end" required></td>
|
||||
<td data-label="Jedn."><input type="text" name="polozky[${rowIndex}][JEDNOTKA]" value="ks" class="form-control"></td>
|
||||
<td data-label="Cena/Jedn."><input type="number" step="0.01" name="polozky[${rowIndex}][CENA_JEDNOTKA]" value="0" class="form-control item-cena text-end" required></td>
|
||||
<td data-label="Sleva %"><input type="number" step="0.1" name="polozky[${rowIndex}][SLEVA]" value="0" class="form-control item-sleva text-end"></td>
|
||||
<td data-label="Celkem" class="text-end fw-bold item-celkem-text">0,00 CZK</td>
|
||||
<td data-label="Celkem"><input type="number" step="0.01" value="0" class="form-control item-celkem text-end fw-bold" title="Úprava přepočítá počet"></td>
|
||||
<td class="text-center cell-actions">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm btn-remove-row"><i class="bi bi-trash"></i></button>
|
||||
</td>
|
||||
|
|
@ -621,11 +662,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
});
|
||||
|
||||
tbody.addEventListener('input', (e) => {
|
||||
if (e.target.matches('.item-celkem')) {
|
||||
recalculatePocetFromCelkem(e.target.closest('.item-row'));
|
||||
updateGrandTotalFromInputs();
|
||||
return;
|
||||
}
|
||||
if (e.target.matches('.item-pocet, .item-cena, .item-sleva')) {
|
||||
calculateTotals();
|
||||
}
|
||||
});
|
||||
|
||||
tbody.addEventListener('focusout', (e) => {
|
||||
if (e.target.matches('.item-celkem')) {
|
||||
recalculatePocetFromCelkem(e.target.closest('.item-row'));
|
||||
calculateTotals();
|
||||
}
|
||||
});
|
||||
|
||||
if (document.querySelectorAll('.item-row').length === 0) {
|
||||
btnAdd.click();
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue