Laskutus (myyntilaskut)#

ELT laskuttaa pääosin kahdesta lähteestä:

  1. Field Service tehtävät — kun työ on valmis, tehtävän tunnit + kulut + tuotteet siirtyvät laskulle
  2. Suorat laskut — esim. kausilasku sopimusasiakkaalle, ennakkomaksu, ei tehtäväpohjaista

Tyypillinen flow: tehtävästä laskuksi#

  1. Asentaja kuittaa tehtävän valmiiksi (state = “Valmis”).
  2. Työnjohtaja hyväksyy tunnit ja kulut viikoittain (Hyväksynnät).
  3. Toimisto luo laskun:
    • Avaa tehtävä → Action → “Create Invoice”.
    • Odoo luo account.move-rivin (Draft-tilassa).
    • Asentajan kirjaamat tunnit × asentajan tuntihinta, kulut ja tuoterivit siirtyvät automaattisesti.
  4. Tarkistus: avaa Draft-lasku.
    • Tarkista että rivit, hinnat, ALV-luokat ovat oikein.
    • Resolution-teksti (asentajan kirjoittama yhteenveto) näkyy laskun otsikossa / muistiossa — asiakas näkee tämän.
  5. Confirm: Action → Post.
  6. Lähetys asiakkaalle ja Netvisoriin:
    • Lähetys asiakkaalle: Action → Send & Print (PDF + sähköposti).
    • Netvisoriin: katso Netvisor-integraatio.

Laskun rakenne#

Odoon account.move:n osat:

OsaSisältö
CustomerAsiakas (asiakas, ei kohde)
Invoice DateLaskutuspäivä, oletuksena tänään
Due DateEräpäivä, oletuksena +30 päivää
Invoice LinesTunnit (palvelu), kulut (palvelu), tuotteet (varasto)
TotalYhteissumma ALV mukaan

Tehtävän kytkös#

account.move.line.fsm_order_ids on Many2many kenttä joka kertoo mistä tehtävistä rivi tulee. Yksi rivi voi (harvinaisesti) liittyä useaan tehtävään, ja yksi tehtävä voi (yleisesti) tuottaa useita rivejä.

**OCA:n kenttä on monikko: `fsm_order_ids`, ei `fsm_order_id`!** Domain-haut joissa käytetään väärää nimeä kaatuvat "Invalid field … in leaf" -virheellä. (200.x korjattu).

Hintojen tarkistus#

Asentajan PWA:han näkyy tukkuhinta. Mutta laskutushinta on myyntihinta = tukku + ELT:n marginaali. Marginaalin laskenta:

  • Tyypillinen marginaali asetetaan tuotteen list_price-kenttään Inventory:ssa.
  • Asiakaskohtaiset poikkeukset hoidetaan Pricelisteillä.
  • Tarkistus laskunteon yhteydessä ennen Post:ia.

Hour-for-hour vs. arvio#

Hour-for-hour -toggle on tehtäväformissa. Jos päällä: laskutetaan ne tunnit jotka asentaja oikeasti kirjasi. Jos pois: voidaan käyttää ennakkoarviota (esim. urakka-asiakkaalle).

ELT:llä useimmiten hour-for-hour päällä — tuntikalkulaatio on läpinäkyvämpää.

Credit notes (hyvityslaskut)#

Jos asiakas valittaa tai virhe huomataan jälkikäteen:

  1. Avaa Posted-tilan lasku.
  2. Action → “Reverse” → Reverse Entry.
  3. Odoo luo “credit note” -rivin samalla summalla, miinusmerkillä.
  4. Tarvittaessa luo uusi lasku korjatulla sisällöllä.

Älä yritä muokata postattua laskua — eheys rikkoutuu, audit- chain katoaa.

ALV-käytäntö#

  • Suomeen yleisesti: 25,5 % (alv-laki muutos 1.9.2024 jälkeen, poikkeuksellisia tuotekategorioita)
  • Lääkinnälliset: 14 %, 10 %
  • Vienti: 0 %
  • Ulkomaa EU: käännetty verovelvollisuus (laskutus 0 %, asiakas maksaa omassaan)

ALV-luokat määritetään Inventory → Configuration → Taxes. Tuotetasolla pakollinen tieto.

Vianetsintä#

Tehtävän ‘Create Invoice’ -nappi ei näy
- Onko tehtävä **state = Valmis**? Vain valmiit voidaan laskuttaa. - Onko **hyväksyntä tehty** kaikkiin tunteihin ja kuluihin? - Onko **`group_account_invoice`-ryhmä** käyttäjäsi oikeuksissa?
Laskutusrivi puuttuu vaikka asentaja kirjasi tunnit
Tarkistettavaa: - Rivi on **`is_billed=True` -tilassa** mutta laskua ei silti ole → kysele kehittäjältä, voi olla ristiriitatila. - Rivi on **hyväksymättä** vielä → näkyy "Submitted" eikä siirry laskulle. - Rivi on **eri tehtävällä** kuin luulit → tarkista `account.move.line.fsm_order_ids`.
Lasku ei lähde Netvisoriin
Katso [Netvisor-integraatio](../netvisor/) → "Myyntilaskut" -osio ja vianetsintä.