# Product Need Documentation

## Tuotetarpeen yleiskuvaus

Product Need -näkymä näyttää tuotteiden varastosaldojen kehityksen ja tulevaisuuden tarpeet perustuen myyntitilauksiin, tuotantotilauksiin ja ostotilauksiin.

## Ominaisuudet

### Progressiivinen lataus (Progressive Loading)

Ensimmäinen lataus palauttaa vain tuotelistan nopeasti. Sen jälkeen järjestelmä laskee viikoittaiset tarpeet taustalla.

- **Ensimmäinen kutsu**: Palauttaa tuotelistan (`load_mode: 'product_list'`)
- **Toinen kutsu**: Palauttaa täydet laskelmat viikoittaisine tarpeineen

### Inkrementaalinen päivitys (Incremental Update)

Järjestelmä lähettää vain muuttuneet tiedot, jos `rec.incremental_update` on päällä.

- **`incremental_update: true`**: Käytä inkrementaalisia päivityksiä (vähentää datan siirtoa)
- **`last_modify_id`**: Seuraa viimeisintä muutos-ID:tä jokaiselle taululle

### Vakiot (rec.json)

| Nimi | Oletus | Kuvaus |
|------|--------|--------|
| `incremental_update` | `true` | Käytä inkrementaalisia päivityksiä |
| `last_modify_id` | `{}` | Viimeisin muutos-ID per taulu |
| `weekly_need` | `false` | Näytä viikoittainen näkymä |
| `hide_empty` | `true` | Piilota tyhjät rivit |
| `only_need` | `true` | Näytä vain tarpeessa olevat tuotteet |
| `has_error` | `false` | Näytä vain virheelliset |
| `find_text` | `""` | Hakuteksti |
| `find_delay_seconds` | `0.4` | Haun viive sekunneissa |
| `find_min_characters` | `1` | Hakua varten vähimmäismäärä merkkejä |

### Näkymät (view)

| Arvo | Kuvaus |
|------|--------|
| `product-need` | Tuotetarve-näkymä |
| `graph` | Grafiikka-näkymä |
| `planned` | Suunniteltu |
| `actual` | Toteutunut |
| `checked` | Tarkistettu |
| `timecard` | Kellokortti |
| `capacity` | Kapasiteetit |
| `resource_efficiency` | Resurssien tehokkuus |
| `shift` | Vuorot |

### Tarpeen näkymät (need_view)

| Arvo | Kuvaus |
|------|--------|
| `balance` | Balanssi-näkymä (viikoittainen) |
| `need` | Tarve-näkymä (yksityiskohtainen) |

### Karttatyypit (chart_type)

| Arvo | Kuvaus |
|------|--------|
| `stock_balance` | Varastosaldo |
| `product_tree` | Tuotepuu |
| `work_phase` | Työvaiheet |
| `product-need` | Tuotetarve (poistettu käytöstä) |

### Laskentaparametrit

| Parametri | Kuvaus |
|-----------|--------|
| `reload_data` | Pakota täysi lataus |
| `create_schedule` | Luo aikataulu |
| `virtual_production_order` | Virtuaalinen tuotantotilaus |
| `estimate_order` | Arvioitu tilaus |
| `old_work_date` | Vanha työpäivä |
| `max_need_down_loop_count` | Maksimi tarpeen laskenta loop |
| `minimum_stock` | Minimivarasto |
| `action_limit` | Toimintaraja |
| `negative_start_balance` | Negatiivinen aloitussaldo |
| `negative_end_balance` | Negatiivinen loppusaldo |
| `critical_date` | Kriittinen päivämäärä |
| `only_sales_need` | Vain myyntitarve |
| `load_mode` | Lataustila (`'product_list'` tai ei määritelty) |

## Ruudukot (Grids)

### product

Tuotetietojen ruudukko sisältää perustiedot:

- `record_id` - Tietueen yksilöivä tunniste
- `product_id` - Tuotetunniste
- `name` - Tuotteen nimi
- `json_data` - JSON-data sisältää varastosaldon
- `stock_type` - Varastotyyppi
- `minimum_stock` - Minimivarasto
- `minimum_order_amount` - Minimitilausmäärä
- `default_supplier_id` - Oletustoimittaja
- `modify_id` - Muutos-ID inkrementaalisia päivityksiä varten

### product_need

Yksityiskohtainen tarve-ruudukko:

- `idx` - Rivinumero
- `record_id` - Tietueen yksilöivä tunniste
- `product_id` - Tuotetunniste
- `date` - Päivämäärä (Unix timestamp)
- `balance` - Saldo
- `coming_amount` - Tuleva määrä
- `going_amount` - Lähtevä määrä
- `free_amount` - Vapaa määrä
- `need_down` - Alaspäin tarve
- `first_row` - Ensimmäinen rivi
- `last_row` - Viimeinen rivi
- `from_row` - Ylätason rivi
- `error` - Virheilmoitus
- `is_empty` - Onko tyhjä

### product_need_weekly

Viikoittainen yhteenveto:

- `idx` - Rivinumero
- `record_id` - Tietueen yksilöivä tunniste
- `product_id` - Tuotetunniste
- `calc_idx` - Linkki product_need-ruudukkoon
- `amount` - Määrä
- `date` - Päivämäärä
- `company_id` - Yhtiötunnus (toimittaja)
- `order_amount` - Tilattava määrä
- `error` - Virheilmoitus

## Tekninen toteutus

### Backend (product-need.lua)

```lua
-- Progressiivinen lataus
local loadMode = rec.load_mode
if loadMode == "product_list" then
    -- Palauta vain tuotelista
    return { grid = { product = {...} } }
end

-- Inkrementaalinen päivitys
if rec.incremental_update and next(lastModifyId) then
    changeArr = changeData.setIncrementalChange(data, lastModifyId, deleted)
    return { change_idx = changeArr, rec = { last_modify_id = ... } }
else
    return { grid = {...}, rec = { last_modify_id = ... } }
end
```

### Frontend (change-data.js)

```javascript
// Inkrementaalinen päivitys
export function incrementalUpdate(state, response) {
    const wasIncremental = response.change_idx
    if (wasIncremental) {
        applyIncrementalChanges(state, response.change_idx)
    } else if (response.grid) {
        state.grid.product_need = response.grid.product_need
        state.grid.product_need_weekly = response.grid.product_need_weekly
        state.grid.product = response.grid.product
    }
    state.rec.last_modify_id = response.rec.last_modify_id
    return wasIncremental
}
```

### Käyttö (nc-production.js)

```javascript
// Progressiivinen lataus
nc.callServer(state, 'calc/product-need', {
    parameter: { load_mode: 'product_list' }
}, ret => {
    incrementalUpdate(state, ret)
    // Näytä tuotteet heti
    if (ret.grid?.product) {
        state.grid.product = ret.grid.product
    }
    // Hae täysi laskelma
    loadFullCalculation()
})

// Inkrementaalinen päivitys
const wasIncremental = incrementalUpdate(state, ret)
if (!wasIncremental && ret.grid?.product_need) {
    updateData(ret)
}
```

## Database requirements

Taulujen täytyy sisältää `modify_id`-kenttä inkrementaalisia päivityksiä varten:

```sql
ALTER TABLE product ADD COLUMN modify_id TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
```

## Rivien korostus (Row Highlighting)

Järjestelmä korostaa ruudukon rivejä eri väreillä riippuen rivin tilasta:

### Koristustyypit

| Luokka | Väri | Kuvaus |
|--------|------|--------|
| (ei luokkaa) | Ruudukon oletus | Käyttäjän valitsema rivi |
| `highlight-upper` | Kultainen keltainen | Ylätason tuote (parent) |
| `highlight-lower` | Vaalea vihreä | Alatason tuote (child) |
| `highlight-found` | Purppura | Haun löytämä rivi |
| `highlight-error` | Punainen | Virheellinen rivi (ei riittävästi tietoa) |

### Scope-sarake

**Scope**-sarake näyttää kunkin rivin hierarkkisen valikoiman:

- **↑N ↓M**: Rivi(t), jota klikkasit (N=ylätason määrä, M=alatason määrä)
- **upper**: Ylätason osat/komponentit
- **lower**: Alätason osat/komponentit
- **found**: Haun löytämät rivit
- **no-info**: Puuttuvat tilaustiedot (ostotilauksen validointia varten)

### Ylätason ja alätason valinta

Kun valitset rivin ruudukosta:

- **Select upper** -korostus: Näyttää kaikki ylätason tuotteet (parent products), jotka johtavat tähän tuotteeseen
- **Select lower** -korostus: Näyttää kaikki alatasoiset tuotteet (child products), jotka johtuvat tästä tuotteesta

Korostus perustuu CSS-luokkiin riveillä, joten se ei häiritse varsinaista valintaa.

## Lisää tilaus (Add Order)

Balance-näkymässä voit lisätä ostotilauksia valituille riveille.

### Käyttö

1. Valitse yksi tai useampia riviä ruudukosta
2. Aseta tilattava määrä (`order_amount`) kuhunkin valittuun riviin
3. Aseta toimittaja (`company_id`) kuhunkin valittuun riviin
4. Klikkaa "Add order" -painiketta

### Validointi

Jos jokin valituista riveistä puuttuu tarvittavat tiedot:

- Järjestelmä näyttää virheilmoituksen: "Please set order amount and supplier company id to all selected rows before adding a new purchase order"
- Puutteelliset rivit korostetaan punaisella (`highlight-error`-luokka)
- Sinun täytyy korjata tiedot ennen tilauksen lisäämistä

### Vaaditut kentät

Jokaisella valitulla rivillä täytyy olla:

- `order_amount` - Suurempi kuin 0
- `company_id` - Toimittajan tunniste asetettu

## Virheiden käsittely

- Jos inkrementaalinen päivitys epäonnistuu, järjestelmä putoaa takaisin täyteen lataukseen
- Puuttuvat `modify_id`-kentät käsitellään suosiolla
- Väärin muotoillut vastaukset laukaisevat täyden latauksen
- Ostotilausta lisättäessä tarkistetaan, että kaikilla valituilla riveillä on tarvittavat tiedot
