# 🔧 Tekninen dokumentaatio - Rifmoke Laskutusohjelma

## Yleiskuvaus

Rifmoke Laskutusohjelma on moderni, HTML5/CSS3/JavaScript-pohjainen web-sovellus, joka mahdollistaa ammattimaisten laskujen luomisen ilman verkkoyhteyttä tai palvelinta.

## Tekniset vaatimukset

### Selain
- ✅ Chrome 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Edge 90+

### Tiedoston rakenne

```
lasku 2.0/
├── index.html                    # Pääohjelma
├── styles.css                    # Pääasettelut ja tyylitys
├── themes.css                    # Värit ja teemat
├── script.js                     # Päälogikka
├── reference-number-generator.js # Viitenumeron luonti
├── rifmoke-logo-kiinteistonhoito.webp  # Logo
├── README.md                     # Käyttöohje
├── QUICK-START.md               # Pikaopas
└── TECHNICAL.md                 # Tämä tiedosto
```

## Arkkitehtuuri

### Frontend-rakenne

```
HTML (index.html)
    ├── Container
    │   ├── Toolbar (Ohjausnappulat)
    │   ├── Main-wrapper (Pääsisältö)
    │   │   └── Invoice-container (Laskun näyttö)
    │   │       └── Invoice-page (A4-pohja)
    │   │           ├── Invoice-header (Logo + Laskun tiedot)
    │   │           ├── Invoice-customer (Asiakastiedot)
    │   │           ├── Invoice-tables (Palvelut-taulukot)
    │   │           ├── Invoice-summary (Yhteenveto)
    │   │           ├── Payment-info (Maksutiedot)
    │   │           └── Tilisiirtolomake-section (Tilisiirtolomake)
    │   └── Sidebar (Hallintapaneeli - piilossa)
    └── Scripts
        ├── reference-number-generator.js
        └── script.js
```

## JavaScript API

### Pääfunktiot

#### `generateReferenceNumber()`
Luo suomalaisen viitenumeron mod10-algoritmilla.
```javascript
generateReferenceNumber();
// Lukee laskun numeron ja muodostaa viitenumeron
```

#### `generateBankTransferForm()`
Rakentaa tilisiirtolomakkeen laskun tiedoista.
```javascript
generateBankTransferForm();
// Lukee laskun tiedot ja muodostaa pankkisiirtolomakkeen
```

#### `updateTableTotals()`
Päivittää kaikkien taulukoiden yhteensä-arvot ja lopullisen summan.
```javascript
updateTableTotals();
// Laskee rivien ja taulukoiden yhteensä-arvot
```

#### `addTable()`
Lisää uuden taulukon laskuun.
```javascript
addTable();
// Luo uuden palvelutaulukon
```

#### `addRow(button)`
Lisää rivin taulukkoon.
```javascript
addRow(buttonElement);
// Lisää rivin klikkautuneeseen taulukkoon
```

#### `removeRow(button)`
Poistaa rivin taulukosta.
```javascript
removeRow(buttonElement);
// Poistaa rivin, jos taulukon taulukossa on useampi kuin yksi rivi
```

#### `removeTable(button)`
Poistaa koko taulukon.
```javascript
removeTable(buttonElement);
// Poistaa taulukon, jos niitä on useampi kuin yksi
```

#### `downloadPDF()`
Lataa laskun PDF-tiedostoksi.
```javascript
downloadPDF();
// Käyttää html2pdf-kirjastoa laskun muuntamiseen PDF:ksi
```

#### `formatCurrency(value)`
Muotoilee numeron euroiksi.
```javascript
formatCurrency(620.5);
// Palauttaa: "620,50"
```

### Tilaemuuttujat

```javascript
window.selectedField    // Viimeksi valittu muokattava kenttä
window.invoiceData      // Laskun tiedot (localStorage)
```

## CSS Rakenteet

### Pää-luokat

```css
.container              /* Pääkontainer */
.toolbar               /* Ohjausnappulat yläosa */
.main-wrapper          /* Pääsisällön alue */
.invoice-container     /* Laskun ulkoisesti säilö */
.invoice-page          /* A4-pohja */
.invoice-header        /* Ylärivi: logo + tiedot */
.invoice-tables        /* Taulukot-alue */
.sidebar               /* Oikea sivupalkki (asetukset) */
```

### Muokattavat kentät

```css
.editable-field        /* Klikkaa ja muokkaa tekstit */
.invoice-number        /* Laskun numero */
.invoice-date          /* Laskun päiväys */
.due-date              /* Eräpäivä */
```

### Taulukko-luokat

```css
.invoice-table         /* Palvelutaulukko */
.invoice-row           /* Rivi taulukossa */
.row-total             /* Rivin yhteensä */
.table-section         /* Taulukon säilö */
```

## LocalStorage

### Tallennus

```javascript
// Tallenna vedos
const invoiceData = {
    timestamp: new Date().toISOString(),
    html: document.getElementById('invoiceContainer').innerHTML
};
let invoices = JSON.parse(localStorage.getItem('invoices')) || [];
invoices.push(invoiceData);
localStorage.setItem('invoices', JSON.stringify(invoices));
```

### Lataus

```javascript
// Lataa viimeksi tallennettu
const invoices = JSON.parse(localStorage.getItem('invoices')) || [];
if (invoices.length > 0) {
    const lastInvoice = invoices[invoices.length - 1];
    document.getElementById('invoiceContainer').innerHTML = lastInvoice.html;
}
```

## Laskentalogiikka

### Mod10 Viitenumero

```javascript
// Algoritmi:
1. Täytä laskun numero 7 merkillä nollilla (vasemmalta)
2. Kerro jokainen sijainti omalla painolla (7, 3, 1)
3. Summaa kaikki tulokset
4. Tarkistussiffer = (10 - (summa % 10)) % 10
5. Liitä tarkistussiffer numeron perään
6. Muotoile välilyönnein (ryhmittelemällä viiden merkkin väleissä)
```

### ALV Laskenta

```javascript
// 1. Laske kaikkien rivien summa
let grandTotal = 0;
table.querySelectorAll('tbody tr').forEach(row => {
    const quantity = parseFloat(row.querySelector('.input-quantity').value) || 0;
    const price = parseFloat(row.querySelector('.input-price').value) || 0;
    grandTotal += quantity * price;
});

// 2. Laske ALV
const vatPercentage = parseFloat(document.getElementById('vatPercentage').value);
const vat = grandTotal * (vatPercentage / 100);

// 3. Laske yhteensä
const total = grandTotal + vat;
```

## PDF-tuonti

### Kirjasto
- **html2pdf.js** (CDN: jsDelivr)
- Versio: 0.10.1

### Käyttö

```javascript
function downloadPDF() {
    const element = document.getElementById('invoiceContainer');
    const opt = {
        margin: 0,
        filename: 'lasku.pdf',
        image: { type: 'jpeg', quality: 0.98 },
        html2canvas: { scale: 2 },
        jsPDF: { format: 'a4', orientation: 'portrait' },
        pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
    };
    
    html2pdf().set(opt).from(element).save();
}
```

## Tulostus optimointi

### A4 Koko
```css
@page {
    size: A4;
    margin: 0;
    padding: 0;
}

.invoice-page {
    width: 210mm;
    height: 297mm;
    padding: 15mm;
}
```

### Print Media Query
```css
@media print {
    .toolbar { display: none !important; }
    .sidebar { display: none !important; }
    .editable-field { border: none !important; }
}
```

## Turvallisuus

### XSS Suojaus
- ✅ Käyttää `textContent` eikä `innerHTML` käyttäjän syötteelle
- ✅ Validoidaan numeroita `parseInt()` ja `parseFloat()` kanssa

### CORS
- ✅ Ei tarvitse CORS:ia - kaikki on lokaalisti

### Tietosuoja
- ✅ Kaikki data tallennetaan selaimeen (localStorage)
- ✅ Ei lähetetä tietoja verkossa

## Performanssi

### Optimoinnit
- ✅ Minimaalinen DOM-käsittely
- ✅ Event delegation painikkeille
- ✅ CSS-animaatiot GPU:lla
- ✅ Lazy loading kuvat

### Lataamisaika
- HTML: ~50KB
- CSS: ~25KB
- JavaScript: ~30KB
- Logo: ~10-100KB (riippuu logosta)
- **Yhteensä:** ~115-205KB (pienempi kuin keskimääräinen kuva!)

## Lisensoidut kirjastot

1. **html2pdf.js** - MIT License
   - CDN: jsDelivr
   - GitHub: eKoopmans/html2pdf

2. **Font Awesome** - CC BY 4.0
   - Kuvake kirjasto
   - CDN: cdnjs.cloudflare.com

## Selainyhteensopivuus

| Selain | Versio | Tuki |
|--------|--------|------|
| Chrome | 90+ | ✅ Täystuella |
| Firefox | 88+ | ✅ Täystuella |
| Safari | 14+ | ✅ Täystuella |
| Edge | 90+ | ✅ Täystuella |
| IE 11 | - | ❌ Ei tuella |

## Kehittäjän opas

### Omien funktioiden lisääminen

```javascript
// 1. Avaa script.js
// 2. Lisää uusi funktio:
function myCustomFunction() {
    // Sinun koodi tähän
}

// 3. Kutsu funktiota HTML:sta:
<button onclick="myCustomFunction()">Klikkaa</button>
```

### Värien mukauttaminen

```css
/* Avaa styles.css */
/* Etsi :root { } */
:root {
    --primary-color: #2c3e50;    /* Muuta tämä */
    --secondary-color: #3498db;  /* Muuta tämä */
}
```

### Uuden taulukon sarakkeen lisääminen

```javascript
// script.js -> addTable() funktio
// Muuta <th> rivejä:
<th class="col-custom">Uusi sarake</th>

// Lisää data-kenttä:
<td><input type="text" class="input-custom"></td>
```

## Vianetsintä

### Konsoliin tulostettavat virheilmoitukset
```javascript
// F12 -> Console välilehti
// Näet virheilmoitukset tässä
console.error("Virhe!");
console.log("Debug-tieto");
console.warn("Varoitus");
```

### Yleisiä ongelmia

**Ongelma:** Taulukko ei päivity
- Ratkaisu: Tarkista `updateTableTotals()` kutsutaan `onchange`-tapahtumissa

**Ongelma:** PDF ei lataudu
- Ratkaisu: Tarkista että html2pdf-CDN on saatavilla

**Ongelma:** Logo ei näy
- Ratkaisu: Tarkista tiedoston polku index.html:ssa

## Tulevaisuus

### Suunnitellut ominaisuudet
- [ ] Excel-vienti
- [ ] Tilaushistoria (Cloud sync)
- [ ] Asiakasrekisteri
- [ ] Automaattinen numerointijärjestelmä
- [ ] Email-lähetys
- [ ] Maksumuistutukset
- [ ] Integraatio kirjanpitojärjestelmiin

### Teknologia päivitykset
- Progressive Web App (PWA) tuki
- Offline-ensimmäinen arkkitehtuuri
- Service Worker -cache
- WebSQL tuki suuremmille tietomäärille

---

**Versio:** 1.0  
**Viimeksi päivitetty:** 2026-03-05  
**Tekijä:** Rifmoke Development Team
