IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Lukáš Karban:18.11.2023 19:25

Posledních 8 hodin trávím čas nad problémem, který už nevím jak vyřešit.

<form id="invoiceForm" method="post">
<label for="customer_id">ID zákazníka:</la­bel><br>
<input type="text" id="customer_id" name="customer_id"><br>

<label for="payment_met­hod">Způsob platby:</label><br>
<select id="payment_method" name="payment_met­hod">
<option value="cash">Ho­tově</option>
<option value="card">Kar­tou</option>
<option value="transfer">Pře­vodem</option>
</select><br>

<div id="items">
<div class="item">
<label for="item_name">Ná­zev položky:</label><br>
<input type="text" class="item_name" name="items[][na­me]"><br>
<label for="item_quan­tity">Počet kusů:</label><br>
<input type="number" class="item_qu­antity" name="items[][qu­antity]"><br>
<label for="item_pri­ce">Cena za kus bez DPH:</label><br>
<input type="number" step="0.01" class="item_price" name="items[][pri­ce]"><br>
<label for="item_pri­ce_vat">Cena za kus s DPH:</label><br>
<input type="number" step="0.01" class="item_pri­ce_vat" name="items[][pri­ce_vat]"><br>
<label for="item_vat">DPH­:</label><br>
<select class="item_vat" name="items[][vat]">
<option value="0.21">21%</op­tion>
<option value="0.10">10%</op­tion>
<option value="0">0%</op­tion>
</select><br>
<label for="item_total">Cel­ková cena položky bez DPH:</label><br>
<input type="number" step="0.01" class="item_total" name="items[][to­tal]" readonly><br>
<label for="item_total_vat">Cel­ková cena položky s DPH:</label><br>
<input type="number" step="0.01" class="item_to­tal_vat" name="items[][to­tal_vat]" readonly><br>
<button type="button" class="remove­Item">Odebrat položku</button><br>
</div>
</div>

<button type="button" id="addItem">Přidat položku</button><br>

<label for="total">Celková cena bez DPH:</label><br>
<input type="number" id="total" name="total" readonly><br>
<label for="total_vat">Cel­ková cena s DPH:</label><br>
<input type="number" id="total_vat" name="total_vat" readonly><br>
<label for="rounding">Za­okrouhlení:</la­bel><br>
<input type="number" id="rounding" name="rounding" readonly><br>
<label for="vat_diffe­rence">Rozdíl mezi cenou bez DPH a s DPH:</label><br>
<input type="number" id="vat_difference" name="vat_dif­ference" readonly><br>

<input type="submit" value="Vytvořit fakturu">
</form>

<script>
document.getE­lementById('ad­dItem').addEven­tListener('clic­k', function() {
var item = document.query­Selector('.item')­.cloneNode(tru­e);
item.querySelec­tor('.item_na­me').value = '';
item.querySelec­tor('.item_qu­antity').value = '';
item.querySelec­tor('.item_pri­ce').value = '';
item.querySelec­tor('.item_pri­ce_vat').value = '';
item.querySelec­tor('.item_vat')­.value = '0.21';
item.querySelec­tor('.item_to­tal').value = '';
item.querySelec­tor('.item_to­tal_vat').value = '';
document.getE­lementById('i­tems').appendChil­d(item);
});

function updateInvoice­Total() {
var items = document.query­SelectorAll('­.item');
var total = 0;
var total_vat = 0;
items.forEach(fun­ction(item) {
total += parseFloat(item­.querySelector('­.item_total')­.value);
total_vat += parseFloat(item­.querySelector('­.item_total_vat')­.value);
});
var rounding = document.getE­lementById('pa­yment_method')­.value === 'cash' ? 0 : 2;
var rounded_total = Math.round(total);
var rounded_total_vat = Math.round(to­tal_vat);
var rounding_difference = rounded_total - total;
var rounding_diffe­rence_vat = rounded_total_vat - total_vat;

document.getE­lementById('to­tal').value = total.toFixed(rou­nding);
document.getE­lementById('to­tal_vat').value = total_vat.toFi­xed(rounding);
document.getE­lementById('vat_dif­ference').value = (total_vat - total).toFixed(rou­nding);
document.getE­lementById('rou­nding').value = rounding_diffe­rence.toFixed(2);
document.getE­lementById('rou­nding_vat').va­lue = rounding_diffe­rence_vat.toFi­xed(2);
}

document.getE­lementById('in­voiceForm').ad­dEventListener('in­put', function(event) {
var target = event.target;
if (target.classLis­t.contains('i­tem_price') || target.classLis­t.contains('i­tem_quantity') || target.classLis­t.contains('i­tem_vat')) {
var item = target.parentE­lement;
var price = parseFloat(item­.querySelector('­.item_price')­.value);
var quantity = parseInt(item­.querySelector('­.item_quantity')­.value);
var vat = parseFloat(item­.querySelector('­.item_vat').va­lue);
var price_vat = price * (1 + vat);
var total = price * quantity;
var total_vat = price_vat * quantity;
var rounding = 2;

item.querySelec­tor('.item_pri­ce_vat').value = price_vat.toFi­xed(rounding);
item.querySelec­tor('.item_to­tal').value = total.toFixed(rou­nding);
item.querySelec­tor('.item_to­tal_vat').value = total_vat.toFi­xed(rounding);

updateInvoice­Total();
} else if (target.classLis­t.contains('i­tem_price_vat')) {
var item = target.parentE­lement;
var price_vat = parseFloat(item­.querySelector('­.item_price_vat')­.value);
var quantity = parseInt(item­.querySelector('­.item_quantity')­.value);
var vat = parseFloat(item­.querySelector('­.item_vat').va­lue);
var price = price_vat / (1 + vat);
var total = price * quantity;
var total_vat = price_vat * quantity;
var rounding = 2;

item.querySelec­tor('.item_pri­ce').value = price.toFixed(rou­nding);
item.querySelec­tor('.item_to­tal').value = total.toFixed(rou­nding);
item.querySelec­tor('.item_to­tal_vat').value = total_vat.toFi­xed(rounding);

updateInvoice­Total();
}
});

document.getE­lementById('pa­yment_method')­.addEventListe­ner('change', function(event) {
var rounding = 2;
var items = document.query­SelectorAll('­.item');
items.forEach(fun­ction(item) {
var price = parseFloat(item­.querySelector('­.item_price')­.value);
var price_vat = parseFloat(item­.querySelector('­.item_price_vat')­.value);
var total = parseFloat(item­.querySelector('­.item_total')­.value);
var total_vat = parseFloat(item­.querySelector('­.item_total_vat')­.value);

item.querySelec­tor('.item_pri­ce').value = price.toFixed(rou­nding);
item.querySelec­tor('.item_pri­ce_vat').value = price_vat.toFi­xed(rounding);
item.querySelec­tor('.item_to­tal').value = total.toFixed(rou­nding);
item.querySelec­tor('.item_to­tal_vat').value = total_vat.toFi­xed(rounding);
});

updateInvoice­Total();
});

document.getE­lementById('in­voiceForm').ad­dEventListener('sub­mit', function(event) {
var items = document.query­SelectorAll('­.item');
for (var i = 0; i < items.length; i++) {
var name = items[i].query­Selector('.item_na­me');
var quantity = items[i].query­Selector('.item_qu­antity');
var price = items[i].query­Selector('.item_pri­ce');
var price_vat = items[i].query­Selector('.item_pri­ce_vat');
if (!name.value || !quantity.value || (!price.value && !price_vat.value)) {
alert('Prosím, vyplňte všechna pole.');
if (!name.value) {
name.focus();
} else if (!quantity.value) {
quantity.focus();
} else if (!price.value && !price_vat.value) {
price.focus();
}
event.preventDe­fault();
return;
}
}
});

document.getE­lementById('in­voiceForm').ad­dEventListener('clic­k', function(event) {
if (event.target­.classList.con­tains('remove­Item')) {
event.target.pa­rentElement.re­move();
updateInvoice­Total();
}
});
</script>

Zkusil jsem: Zkoušel jsem všechno možné.

Chci docílit: Učím se programování a tvořím si sám pro sebe fakturační systém. Mám zde formulář, kde napíšu položku, počet kusů, cenu za kus bez DPH a nebo za kus s DPH. Dále je tu políčko DPH (kde mám předvyplněná procenta a automaticky je vybráno 21%), celkovou cenu za položku bez DPH a celkovou cenu za položku s DPH. Když vyplním políčko počet kusů a cenu za kus bez DPH, automaticky se mi doplní políčka cenu za kus s DPH (kde se spočítá DPH dle počtu kusů a ceny za kus bez DPH) a také se automaticky doplní políčka cenu za kus bez DPH a nebo za kus s DPH. Opět spočítané dle DPH a kusů. Na konci faktury mám políčka Celková cena bez DPH, Celková cena s DPH, Rozdíl DPH a Zaokrouhlení. Zaokrouhlení vypíše hodnotu halířů, které bylo potřeba odebrat či přičíst, aby došlo k zaokrouhlení čísla celkových částek na celé číslo. To je potřeba v případě platby hotově. Čísla se jinak nezaokrouhlí, pokud bude platba převodem či kartou.

Vše funguje, jen políčko Zaokrouhlení nefunguje správně. Pokud vyplním počet kusů a políčko cenu za kus s DPH, dojde k přepočtu všech políček a zapíše se hodnota s dvěma desetinnými čísly, políčko Zaokrouhlení správně vypíše, kolik haléřů bylo potřeba přidat, nebo odebrat při zaokrouhlení. Nicméně problém nastane, pokud vypíšu hodnotu Celková cena bez DPH. Všechna políčka se spočítají správně a všude jsou správně desetinná čísla i konečné ceny jsou zaokrouhlené, jen políčko Zaokrouhlení ukazuje hodnotu 0,00 i když je daná desetinná hodnota, například 256,76, dojde tak k zaokrouhlení konečné částky o +0,24, ale políčko zaokrouhlení zůstane s hodnotou 0,00. Už nevím co mám dělat. Procházím to od začátku do konce a ž nevím, kde hledat chybu. Poradí mi prosím někdo?

 
Odpovědět
18.11.2023 19:25
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:15. ledna 11:03

Zkus pouzit tlacitko pro vlozeni kodu </>.
Zkus to napsat prehledne, kod i html.
A zkus to udelat tak, aby bylo mozne kliknout na jedno tlacitko (predvyplnit hodnoty)

Ja jsem to ve firefoxu spustil a nic to neudelalo.
Zkusil jsem vyplnit nejake hodnoty a nic to nepocitalo.
Zkusil jsem pak kliknout pridat a nic to nedelalo.
Zkusil jsem kliknout na generovat fakturu a cele se to smazalo.
Takze, po techto testech musim rici, ze to absolutne nic nedela. A nedokazu rici, co mas spatne.

Takze to zkus predelat tak, aby stacilo kliknout na 2-3 tlacitka a bud to neco spocita nebo nespocita, jak pises, ze je tam zaokrouhleni 0.

Jinak, s DPH se to ma tak, ze se pocita jen pro celkovou castku. Pokud aspon trochu rozumis matematice zakladni skoly, kde se probiralo scitani a zaokrouhlovani, tak je ti jasne, ze rozpocitavat dph a zaokrouhlovat pro jednotlive polozky a pak tato zaokrouhlena cisla secist da uplne jinou hodnotu nez, nez dph, ktere se dela z nezaokrouhlenych hodnot.

suma1 = zaokr(a + b + c)
suma2 = zaokr(a) + zaokr(b) + zaokr(c)    !!! to je uplne jina rovnice
suma1 = zaokr(1.1 + 1.4 + 1.5) = zaokr (3.0) = ___ 3 ___
suma2 = zaokr(1.1) + zaokr(1.4) + zaokr(1.5) = 1 + 1 + 2 = ___ 4 ___
Pak ti soucty samozrejme nebudou sedet :)
 
Nahoru Odpovědět
15. ledna 11:03
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:15. ledna 11:05

hm, a koukam, ze to je proto, ze tam forko doplnila minuska, protoze to nemas vlozene jako code. takze vsechny js selzou. Zkusim to trochu upravit.

 
Nahoru Odpovědět
15. ledna 11:05
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:15. ledna 11:34

Ne, ztrata casu. Cely ten kod je nesmysl. Nejspis vytahly z chatGPT.

addItem - preci, kdyz naklonujes node, tak ti vytvori inputy se stejnym name jako je puvodni node. A v tom pripade se dopoustis html zlocinu, inputy nesmi mit stejne name v jednom formulari, pokud to nejsou input-radio. Vysledkem by melo byt to, ze uvazuje pouze prvni nebo posledni html tag, ktery ma stejne name. (jinak by se to chovalo v pripade dvou formularu)

Zajimave je, ze ty to dal pak scitas pres querySelector a className. Pak se to chova samozrejme spravne. Class muzes mit duplicitne. Ale zhlediska formulare, to stejne name je furt spatny napad.

No, jeste na to mrknu, ale ani trosku se mi to nelibi, co jsem zatim zjistil :)

 
Nahoru Odpovědět
15. ledna 11:34
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:15. ledna 12:32

ok, mam dalsi podivnosti :)

  • itemy je nutne vytvaret do neceho jako cart (nakupni kosik - addItem)
  • document.getElementById('rounding_vat').value = rounding_difference_vat.toFixed(2); takove id tam vubec neexistuje
  • a nebal bych se pouzit html validator, aby nasel aspon zakladni html chyby :) Mne to prijde jako jakysi prepis z jineho frameworku do js. Nebo, nevim, proc je to samy zmatek...
Editováno 15. ledna 12:33
 
Nahoru Odpovědět
15. ledna 12:32
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:15. ledna 13:23

ok, mozna jsem si tim ztizil praci, kdyz jsem to malinko prepsal, ale mam jakousi funkcni verzi. A ted kdybys napsal nejaky priklad hodnot, ktere, kdyz tam napisi, tak se spocitaji spatne a jake by tam meli byt cisla?
Seznam zmen je teda hodne...

  • udelal jsem si extra cart, do ktereho davam pridane polozky
  • nastavil jsem tlacitko odebrat jako skryte a objevi se po pridani
  • zakomentoval jsem to nefunkcni id, nevedel jsem, co tam ma byt spravne
  • zrusil jsem ve formulari odradkovani
  • prepsal jsem si js-id zvlast, aby se to dalo zmenit na jedinem miste (ale tim jsem si mozna pridelal praci, kdy jsem pak pred kazde id musel pridat form_, a pod :) ... protoze jsem si to tak blbe navrhl pres globalni promene :) Ale, podobne bych to resil pres js-class, ze bych to mel na jednom miste a dal pouzival jen aliasy.)
  • pridal jsem tam prepocitani ceny pri kazdem kliknuti na AddItem

... no, a vysledek je, ze mi to konecne prepocitava vsechna cisla na obrazovce. A ted bych potreboval jen upresnit ty hodnoty, ktere tam mam zadat a jaky by mel byt vysledek. Coz neni problem si zpetne vypsat do console.log kazdou tu polozku a zkontrolovat, jake mela davat cislo.
online: https://jsfiddle.net/jno5wgdv/

<form id="invoiceForm" method="post">
<label for="customer_id">ID zákazníka:</label><br>
<input type="text" id="customer_id" name="customer_id"><br>

<label for="payment_method">Způsob platby:</label><br>
<select id="payment_method" name="payment_method">
<option value="cash">Hotově</option>
<option value="card">Kartou</option>
<option value="transfer">Převodem</option>
</select><br>

<hr>

<div id="new_item">
<div class="item">
<label for="item_name">Název položky:</label>
<input type="text" class="item_name" name="items[][name]"><br>
<label for="item_quantity">Počet kusů:</label>
<input type="number" class="item_quantity" name="items[][quantity]"><br>
<label for="item_price">Cena za kus bez DPH:</label>
<input type="number" step="0.01" class="item_price" name="items[][price]"><br>
<label for="item_price_vat">Cena za kus s DPH:</label>
<input type="number" step="0.01" class="item_price_vat" name="items[][price_vat]"><br>
<label for="item_vat">DPH:</label>
<select class="item_vat" name="items[][vat]">
<option value="0.21">21%</option>
<option value="0.10">10%</option>
<option value="0">0%</option>
</select><br>
<label for="item_total">Celková cena položky bez DPH:</label>
<input type="number" step="0.01" class="item_total" name="items[][total]" readonly><br>
<label for="item_total_vat">Celková cena položky s DPH:</label>
<input type="number" step="0.01" class="item_total_vat" name="items[][total_vat]" readonly><br>
<input type="hidden" class="removeItem" value="Odebrat položku"><br>
</div>
</div>

<input type="button" id="addItem" value="Přidat položku">

<hr>

polozky pro fakturu
<div id="cart">
</div>

<hr>

<label for="total">Celková cena bez DPH:</label><br>
<input type="number" id="total" name="total" readonly><br>
<label for="total_vat">Celková cena s DPH:</label><br>
<input type="number" id="total_vat" name="total_vat" readonly><br>
<label for="rounding">Zaokrouhlení:</label><br>
<input type="number" id="rounding" name="rounding" readonly><br>
<label for="vat_difference">Rozdíl mezi cenou bez DPH a s DPH:</label><br>
<input type="number" id="vat_difference" name="vat_difference" readonly><br>

<hr>

<input type="submit" value="Vytvořit fakturu">
</form>

<script>
var item_cols = {
'item_name': 0,
'item_quantity': 0,
'item_price': 0,
'item_price_vat': 0,
'item_vat': 0,
'item_total': 0,
'item_total_vat': 0,
'removeItem': 0
};
var ids = {
'customer_id': 0,
'new_item': 0,
'addItem': 0,
'cart': 0,
'payment_method': 0,
'total': 0,
'total_vat': 0,
'vat_difference': 0,
'rounding': 0,
//'rounding_vat': 0,
'invoiceForm': 0
};
for (i in ids) window['form_'+i] = document.getElementById(i);
for (i in item_cols) window['form_'+i] = new_item.querySelector('.'+i);// console.log(window[i])}

addItem.addEventListener('click', function() {
form_removeItem.type = 'button';
form_cart.appendChild(new_item.cloneNode(true));
form_removeItem.type = 'hidden';
form_item_name.value = '';
form_item_quantity.value = '';
form_item_price.value = '';
form_item_price_vat.value = '';
form_item_vat.value = '0.21'; // nevim, zda takhle je mozne nastavovat select-value
form_item_total.value = '';
form_item_total_vat.value = '';
updateInvoiceTotal();
});

function updateInvoiceTotal() {
var total = 0;
var total_vat = 0;
var items = form_cart.querySelectorAll('.item');
items.forEach(function(item) {
total += parseFloat(item.querySelector('.item_total').value);
total_vat += parseFloat(item.querySelector('.item_total_vat').value);
});

var rounding = form_payment_method.value === 'cash' ? 0 : 2;
var rounded_total = Math.round(total);
var rounded_total_vat = Math.round(total_vat);
var rounding_difference = rounded_total - total;
var rounding_difference_vat = rounded_total_vat - total_vat;

form_total.value = total.toFixed(rounding);
form_total_vat.value = total_vat.toFixed(rounding);
form_vat_difference.value = (total_vat - total).toFixed(rounding);
form_rounding.value = rounding_difference.toFixed(2);
//rounding_vat.value = rounding_difference_vat.toFixed(2); id=rounding_vat neexistuje
}

form_invoiceForm.addEventListener('input', function(event) {
var target = event.target;
if (target.classList.contains('item_price') || target.classList.contains('item_quantity') || target.classList.contains('item_vat')) {
var item = target.parentElement;
var price = parseFloat(item.querySelector('.item_price').value);
var quantity = parseInt(item.querySelector('.item_quantity').value);
var vat = parseFloat(item.querySelector('.item_vat').value);
var price_vat = price * (1 + vat);
var total = price * quantity;
var total_vat = price_vat * quantity;
var rounding = 2;
item.querySelector('.item_price_vat').value = price_vat.toFixed(rounding);
item.querySelector('.item_total').value = total.toFixed(rounding);
item.querySelector('.item_total_vat').value = total_vat.toFixed(rounding);
updateInvoiceTotal();
}
else if (target.classList.contains('item_price_vat')) {
var item = target.parentElement;
var price_vat = parseFloat(item.querySelector('.item_price_vat').value);
var quantity = parseInt(item.querySelector('.item_quantity').value);
var vat = parseFloat(item.querySelector('.item_vat').value);
var price = price_vat / (1 + vat);
var total = price * quantity;
var total_vat = price_vat * quantity;
var rounding = 2;
item.querySelector('.item_price').value = price.toFixed(rounding);
item.querySelector('.item_total').value = total.toFixed(rounding);
item.querySelector('.item_total_vat').value = total_vat.toFixed(rounding);
updateInvoiceTotal();
}
});

form_payment_method.addEventListener('change', function(event) {
var rounding = 2;
var items = form_cart.querySelectorAll('.item');
items.forEach(function(item) {
var price = parseFloat(item.querySelector('.item_price').value);
var price_vat = parseFloat(item.querySelector('.item_price_vat').value);
var total = parseFloat(item.querySelector('.item_total').value);
var total_vat = parseFloat(item.querySelector('.item_total_vat').value);
item.querySelector('.item_price').value = price.toFixed(rounding);
item.querySelector('.item_price_vat').value = price_vat.toFixed(rounding);
item.querySelector('.item_total').value = total.toFixed(rounding);
item.querySelector('.item_total_vat').value = total_vat.toFixed(rounding);
});
updateInvoiceTotal();
});

form_invoiceForm.addEventListener('submit', function(event) {
var items = form_cart.querySelectorAll('.item');
for (var i = 0; i < items.length; i++) {
var name = items[i].querySelector('.item_name');
var quantity = items[i].querySelector('.item_quantity');
var price = items[i].querySelector('.item_price');
var price_vat = items[i].querySelector('.item_price_vat');
if (!name.value || !quantity.value || (!price.value && !price_vat.value)) {
alert('Prosím, vyplňte všechna pole.');
if (!name.value) {
name.focus();
} else if (!quantity.value) {
quantity.focus();
} else if (!price.value && !price_vat.value) {
price.focus();
}
event.preventDefault();
return;
}
}
});

form_invoiceForm.addEventListener('click', function(event) {
if (event.target.classList.contains('removeItem')) {
event.target.parentElement.remove();
updateInvoiceTotal();
}
});
</script>
 
Nahoru Odpovědět
15. ledna 13:23
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 6 zpráv z 6.