447 lines
16 KiB
HTML
447 lines
16 KiB
HTML
<html>
|
|
<head>
|
|
<TITLE>Banqqo</TITLE>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="theme-color" content="lightcyan">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<STYLE type="text/css">
|
|
BODY {
|
|
font-family: sans-serif;
|
|
background-color: lightcyan;
|
|
}
|
|
TEXTAREA { font-family: sans-serif; width: 100%;
|
|
-webkit-border-radius: 5px;
|
|
-moz-border-radius: 5px;
|
|
border-radius: 5px;
|
|
padding: 5px;
|
|
background: transparent;
|
|
}
|
|
#block {
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
width: 69%;
|
|
min-width: 69%;
|
|
max-width: 100%; }
|
|
LABEL {
|
|
width: 10ex;
|
|
display: inline-block;
|
|
}
|
|
.error {
|
|
color: salmon;
|
|
}
|
|
#barcode {
|
|
margin-top: 0em;
|
|
margin-bottom: 0em;
|
|
width: 80%;
|
|
opacity: 1;
|
|
transition: opacity 0.2s;
|
|
}
|
|
#barcodePNG {
|
|
margin-top: 1em;
|
|
margin-bottom: 1em;
|
|
width: 25%;
|
|
opacity: 1;
|
|
transition: opacity 0.2s;
|
|
display:block;
|
|
margin-left:auto;
|
|
margin-right:auto;
|
|
}
|
|
#barcodeBW {
|
|
display: none;
|
|
}
|
|
#barcodes {
|
|
margin: 1em;
|
|
opacity: 1;
|
|
transition: opacity 0.2s;
|
|
}
|
|
#barcodes.fade {
|
|
opacity: 0;
|
|
}
|
|
|
|
/* Lasku */
|
|
|
|
#lasku {
|
|
border: 1px solid;
|
|
border-collapse: collapse;
|
|
}
|
|
#lasku th, #lasku td {
|
|
border: 1px solid;
|
|
padding: 1ex;
|
|
vertical-align: top;
|
|
}
|
|
#lasku .col1 { width: 10%; }
|
|
#lasku .col2 { width: 40%; }
|
|
#lasku .col3 { width: 10%; }
|
|
#lasku .col4 { width: 20%; }
|
|
#lasku .col5 { width: 20%; }
|
|
#lasku_summa {
|
|
text-align: right;
|
|
|
|
}
|
|
#lasku_summa::after {
|
|
content: " €";
|
|
padding-right: 8px;
|
|
}
|
|
#lasku_barcode {
|
|
text-align:center;
|
|
}
|
|
.print_help {
|
|
display: none;
|
|
}
|
|
.kayttaja_pdf {
|
|
display: none;
|
|
}
|
|
.print_help_pdf {
|
|
display: block;
|
|
overflow: visible;
|
|
white-space: pre;
|
|
white-space: pre-wrap;
|
|
}
|
|
@media print {
|
|
.no-print, .no-print * {
|
|
display: none !important;
|
|
}
|
|
#block {
|
|
width: 90vw;
|
|
min-width: 90vw;
|
|
max-width: 90vw;
|
|
}
|
|
.kayttaja {
|
|
display: none;
|
|
}
|
|
.print_help {
|
|
display: block;
|
|
overflow: visible;
|
|
white-space: pre;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
</STYLE>
|
|
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/barcodes/JsBarcode.code128.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
|
|
|
|
<script>
|
|
let state = {
|
|
'iban': null,
|
|
'paiva': null,
|
|
'summa': null,
|
|
'viite': null
|
|
}
|
|
|
|
function clear_barcode() {
|
|
document.getElementById('barcodes').classList.add("fade");
|
|
setTimeout(function() {
|
|
document.getElementById('barcode').innerHTML = "";
|
|
}, 200);
|
|
}
|
|
function flash_generate() {
|
|
clear_barcode();
|
|
setTimeout(function() { generate() }, 200);
|
|
}
|
|
function generate(final = true) {
|
|
|
|
let code = validate(final = final);
|
|
if (!code) {
|
|
clear_barcode();
|
|
clear_lasku();
|
|
return
|
|
}
|
|
document.getElementById('virtuaali').value = code;
|
|
JsBarcode("#barcode", code, {
|
|
format: "CODE128",
|
|
lineColor: "#404",
|
|
background: "transparent",
|
|
width: 2,
|
|
height: 80,
|
|
displayValue: true
|
|
});
|
|
JsBarcode("#barcodeBW", code, {
|
|
format: "CODE128",
|
|
lineColor: "black",
|
|
background: "transparent",
|
|
width: 2,
|
|
height: 80,
|
|
displayValue: true
|
|
});
|
|
document.getElementById('barcodes').classList.remove("fade");
|
|
convertSVGAsPNG(true);
|
|
modify_lasku();
|
|
return;
|
|
}
|
|
function make_error(id, text) {
|
|
document.getElementById(id).innerHTML = text;
|
|
return false
|
|
}
|
|
function clear_error() {
|
|
document.getElementById('iban_error').innerHTML = '';
|
|
document.getElementById('summa_error').innerHTML = '';
|
|
document.getElementById('viite_error').innerHTML = '';
|
|
document.getElementById('paiva_error').innerHTML = '';
|
|
}
|
|
function modify_request(iban,summa,viite,paiva) {
|
|
let URL = window.location.href.split('?')[0]
|
|
let saaja_s = encodeURIComponent(document.getElementById('saaja').value);
|
|
let maksaja_s = encodeURIComponent(document.getElementById('maksaja').value);
|
|
let lasku_s = encodeURIComponent(document.getElementById('laskun_tiedot').value);
|
|
const nextURL = `${URL}?FI${state['iban']},${state['summa']},${state['viite']},${state['paiva']},${saaja_s},${maksaja_s},${lasku_s}`;
|
|
window.history.replaceState({}, document.title, nextURL);
|
|
}
|
|
function calculate_viite_tarkiste(ilman_tarkiste) {
|
|
let kertoimet = Array(7, 3, 1);
|
|
let tulosumma = 0;
|
|
for (const [index, element] of ilman_tarkiste.entries()) {
|
|
tulosumma += kertoimet[index % 3] * parseInt(element);
|
|
}
|
|
let tarkiste = (10 - (tulosumma % 10)) % 10;
|
|
return tarkiste
|
|
}
|
|
function validate_viite(viite) {
|
|
if (! /^\d+$/.test(viite)) {
|
|
return Array(false, "Joukossa muutakin kun numeroita!");
|
|
}
|
|
let nurin = reversed(viite);
|
|
if (nurin.length < 3) return Array(false, "Liian lyhyt")
|
|
let ilman_tarkiste = nurin.substring(1).split('');
|
|
let tarkiste = calculate_viite_tarkiste(ilman_tarkiste);
|
|
if (tarkiste != parseInt(nurin.substring(0,1))) return Array(false, "Tarkiste ei täsmää, viite väärin, tai jos olet luomassa omaa, lisää tarkiste: " + calculate_viite_tarkiste(nurin.split('')).toString());
|
|
return Array(true, String(viite).padStart(20,'0'));
|
|
}
|
|
|
|
function validate(final = true) {
|
|
|
|
clear_error();
|
|
// IBAN
|
|
let iban = document.getElementById('iban').value.replaceAll(' ','').replace(/^FI/,"");
|
|
if (iban.length != 16) return make_error('iban_error',"Vaatii 16 numeroa ja pitää alkaa FI!");
|
|
if (! /^\d+$/.test(iban)) return make_error('iban_error',"Joukossa muutakin kun numeroita!");
|
|
|
|
// SUMMA
|
|
let summa = parseFloat(
|
|
document.getElementById('summa').value.replaceAll(' ','').replace(',','.')
|
|
);
|
|
if (isNaN(summa)) {
|
|
return make_error('summa_error', "Ei numero");
|
|
}
|
|
if ( summa <= 0 ) {
|
|
return make_error('summa_error', "Summan pitää olla positiivinen");
|
|
}
|
|
|
|
let sumsplit = summa.toFixed(2).split(".");
|
|
let euro = String(sumsplit[0]).padStart(6,'0');
|
|
let cents = String(sumsplit[1]).padStart(2,'0');
|
|
// VIITE
|
|
let viite = document.getElementById('viite').value.replaceAll(/[^\d]/g,'').replace(/^0+/,"");
|
|
let viite_valid = validate_viite(viite);
|
|
if (! viite_valid[0]) return make_error("viite_error", viite_valid[1]);
|
|
|
|
// PAIVA
|
|
if (! /^[\d-]+$/.test(document.getElementById('paiva').value)) {
|
|
return make_error('paiva_error',"Joukossa muutakin kun numeroita ja - !");
|
|
}
|
|
let paiva_obj = new Date(Date.parse(document.getElementById('paiva').value));
|
|
if (isNaN(paiva_obj)) return make_error('paiva_error', "Eräpäivä muotoa VVVV-KK-PP");
|
|
let lyhyt_paiva = paiva_obj.getFullYear().toString().slice(-2) + String(paiva_obj.getMonth() + 1).padStart(2,'0') + String(paiva_obj.getDate()).padStart(2,'0');
|
|
let oikea_paiva = Array(
|
|
paiva_obj.getFullYear().toString(),
|
|
String(paiva_obj.getMonth() + 1).padStart(2,'0'),
|
|
String(paiva_obj.getDate()).padStart(2,'0')
|
|
).join("-");
|
|
|
|
// Modify form values when validation is final
|
|
if (final) {
|
|
document.getElementById('iban').value = (('FI' + iban).match(/.{1,4}/g)).join(" ");
|
|
document.getElementById('summa').value = summa.toFixed(2);
|
|
document.getElementById('viite').value = reversed(reversed(viite).match(/.{1,5}/g).join(" "));
|
|
document.getElementById('paiva').value = oikea_paiva;
|
|
state['iban'] = iban;
|
|
state['summa'] = document.getElementById('summa').value;
|
|
state['viite'] = viite;
|
|
state['paiva'] = oikea_paiva;
|
|
modify_request();
|
|
}
|
|
|
|
|
|
// Yhdistely
|
|
let fin = '4';
|
|
let spare = '000';
|
|
let code = fin + iban + euro + cents + spare + viite_valid[1] + lyhyt_paiva;
|
|
return code;
|
|
}
|
|
function parse_virtual() {
|
|
document.getElementById('virtuaali_error').innerHTML = "";
|
|
let vkoodi = document.getElementById('virtuaali').value.replaceAll(" ","");
|
|
if (vkoodi.length != 54) return make_error('virtuaali_error', 'Koodi väärän mittainen');
|
|
if (! /^\d+$/.test(vkoodi)) {
|
|
return make_error('virtuaali_error',"Joukossa muutakin kun numeroita!");
|
|
}
|
|
if (vkoodi.substring(0,1) != '4') {
|
|
return make_error('virtuaali_error',"Ei kotimainen maksukoodi!");
|
|
}
|
|
let iban = "FI" + vkoodi.substring(1,17);
|
|
let summa = (parseFloat(vkoodi.substring(17,25))/100).toFixed(2);
|
|
let viite = vkoodi.substring(28,48).replace(/^0+/,'');
|
|
let vuosisata = (new Date()).getFullYear().toString().substring(0,2);
|
|
let vuosi = vkoodi.substring(48,50);
|
|
let kuu = vkoodi.substring(50,52);
|
|
let paiva = vkoodi.substring(52,54);
|
|
let paivays = `${vuosisata}${vuosi}-${kuu}-${paiva}`;
|
|
document.getElementById('iban').value = iban;
|
|
document.getElementById('summa').value = summa;
|
|
document.getElementById('viite').value = viite;
|
|
document.getElementById('paiva').value = paivays;
|
|
flash_generate();
|
|
}
|
|
|
|
function convertSVGAsPNG(e){
|
|
const svg = document.getElementById('barcodeBW');
|
|
const base64doc = btoa(unescape(encodeURIComponent(svg.outerHTML)));
|
|
const w = parseInt(svg.getAttribute('width'));
|
|
const h = parseInt(svg.getAttribute('height'));
|
|
const img_to_download = document.getElementById('barcodePNG');
|
|
img_to_download.src = 'data:image/svg+xml;base64,' + base64doc;
|
|
}
|
|
|
|
function print_help() {
|
|
let fields = ['saaja','maksaja','laskun_tiedot'];
|
|
for (let i = 0; i < fields.length; i++) {
|
|
let source = document.getElementById(fields[i]);
|
|
let target = document.getElementById('print_' + fields[i]);
|
|
target.innerHTML = source.value;
|
|
}
|
|
modify_request();
|
|
}
|
|
function modify_lasku() {
|
|
let fields = ['iban','summa','viite','paiva'];
|
|
for (let i = 0; i < fields.length; i++) {
|
|
try {
|
|
document.getElementById('lasku_' + fields[i]).innerHTML = document.getElementById(fields[i]).value;
|
|
} catch {}
|
|
}
|
|
print_help();
|
|
}
|
|
function clear_lasku() {
|
|
let fields = ['iban','summa','viite','paiva'];
|
|
for (let i = 0; i < fields.length; i++) {
|
|
try {
|
|
document.getElementById('lasku_' + fields[i]).innerHTML = "";
|
|
} catch {}
|
|
}
|
|
}
|
|
|
|
function lasku_pdf() {
|
|
var element = document.getElementById('barcodes');
|
|
const editables = document.getElementsByClassName("kayttaja");
|
|
const printables = document.getElementsByClassName("print_help");
|
|
|
|
for (let i = 0; i < editables.length; i++) {
|
|
editables[i].classList.add("kayttaja_pdf");
|
|
}
|
|
for (let i = 0; i < printables.length; i++) {
|
|
printables[i].classList.add("print_help_pdf");
|
|
}
|
|
var opt = {
|
|
margin: 10,
|
|
filename: `lasku-${state['paiva']}-${state['viite']}.pdf`,
|
|
html2canvas: { scale: 2 },
|
|
jsPDF: { unit: 'mm', format: 'A4', orientation: 'portrait' }
|
|
};
|
|
html2pdf().set(opt).from(element).save().then(function(results){
|
|
for (let i = 0; i < editables.length; i++) {
|
|
editables[i].classList.remove("kayttaja_pdf");
|
|
}
|
|
for (let i = 0; i < printables.length; i++) {
|
|
printables[i].classList.remove("print_help_pdf");
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
function init() {
|
|
const date = new Date();
|
|
document.getElementById('paiva').value = date.toISOString().substring(0,10);
|
|
|
|
let request = window.location.search.substring(1);
|
|
let vars = request.split(',');
|
|
for (let i = 0; i < vars.length; i++) {
|
|
if (vars[i].length == 0) continue
|
|
if (i==0) document.getElementById('iban').value = vars[i];
|
|
if (i==1) document.getElementById('summa').value = vars[i];
|
|
if (i==2) document.getElementById('viite').value = vars[i];
|
|
if (i==3) document.getElementById('paiva').value = vars[i];
|
|
if (i==4) document.getElementById('saaja').value = decodeURIComponent(vars[i]);
|
|
if (i==5) document.getElementById('maksaja').value = decodeURIComponent(vars[i]);
|
|
if (i==6) document.getElementById('laskun_tiedot').value = decodeURIComponent(vars[i]);
|
|
}
|
|
flash_generate();
|
|
}
|
|
|
|
function reversed(str) {
|
|
return str.split("").reverse().join("");
|
|
}
|
|
</script>
|
|
|
|
</head>
|
|
<body onload="init()">
|
|
<div id=block>
|
|
<div class="no-print">
|
|
<p>Maksun virtuaali viivakoodi / viivakoodi <small>Nothing ever leaves this page.</small></p>
|
|
|
|
<label>IBAN: </label><br><input id="iban" size=18 value="FI12 3456 7890 1234 56" onblur="generate()" onkeyup="generate(false)" /><br>
|
|
<label> </label><span id="iban_error" class="error" ></span><br>
|
|
<label>Summa: </label><br><input type="number" id="summa" size=10 value=10 onblur="generate()" onkeyup="generate(false)" />€<br>
|
|
<label> </label><span id="summa_error" class="error" ></span><br>
|
|
<label>Viite: </label><br><input pattern="[0-9 ]+" id="viite" size=20 value=1054 onblur="generate()" onkeyup="generate(false)" /> Viite pakollinen, esim 1054 jos et keksi<br>
|
|
<label> </label><span id="viite_error" class="error" ></span><br>
|
|
<label>Eräpäivä: </label><br><input type="text" pattern="[0-9\-]+" id="paiva" size=10 onblur="generate()" onkeyup="generate(false)" placeholder="VVVV-KK-PP"/><br>
|
|
<label> </label><span id="paiva_error" class="error" ></span><br>
|
|
<input type="submit" onclick="flash_generate()" value="Generoi"/>
|
|
<br>
|
|
</div>
|
|
<div id="barcodes">
|
|
<table id="lasku">
|
|
<tbody>
|
|
<tr>
|
|
<td class=col1>Saajan tilinumero</td><td class=col2 id="lasku_iban">[tilinro]</td><td colspan=3 rowspan=2><textarea class=kayttaja rows=10 id=laskun_tiedot placeholder="Laskun tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_laskun_tiedot"></div></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class=col1>Saaja</td><td class=col2><textarea id=saaja class=kayttaja rows=3 placeholder="Saajan tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_saaja"></div></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class=col1 rowspan=2>Maksaja</td><td class=col2 rowspan=2><textarea id=maksaja class=kayttaja rows=3 placeholder="Maksajan tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_maksaja"></div></td>
|
|
<td class=col3>Viite</td><td colspan=2 id="lasku_viite">[viite]</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class=col3>Eräpäivä</td><td class=col4 id="lasku_paiva">[paiva]</td><td class=col5 id="lasku_summa">[summa]</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan=5 id=lasku_barcode><svg id="barcode"></svg></td>
|
|
</tr>
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<br>
|
|
<div class="no-print">
|
|
|
|
<input type="submit" onclick="lasku_pdf()" value="Tallenna lasku PDF"/>
|
|
<br><br>
|
|
<label>Virtuaaliviivakoodi:</label><br>
|
|
<input id="virtuaali" size=54 /><br>
|
|
<label> </label><span id="virtuaali_error" class="error" ></span><br>
|
|
<input type="submit" onclick="parse_virtual()" value="Muunna virtuaalikoodi kenttiin"/>
|
|
<br>
|
|
<svg id="barcodeBW"></svg>
|
|
<p>Talleta kuvamuodossa:</p>
|
|
<img id="barcodePNG" alt="Talleta kuvana" title="Talleta kuvana"></img>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|