System Documentation ProLasku EasyCMS

How the price row is chosen

When you add a product to an order or invoice, or print its label, the system runs the same resolution in every module. Nothing is asked from the user — the barcode, the warehouse context and the schedules decide automatically.

The resolution steps

1. START     → product's own price + own discount
2. FILTER    → keep only multi-code rows that pass ALL of:
                 • barcode test    (what was scanned — see table below)
                 • schedule test   (row is inside its date/time/weekday window)
                 • warehouse test  (row warehouse empty OR qualifies — see below)
3. MERGE     → walk the surviving rows top to bottom;
               each row's price becomes the current price,
               each row's discount becomes the current discount
4. RESULT    → current price + current discount land on the line/label,
               and the WINNING ROW's checkbox flags steer how the discount
               competes next (see Discount priorities)

The barcode test

How the product was added Rows that pass the barcode test
Scanned — a multi-row's code That exact row, plus fully-generic rows (no code, no box code). The scanned row wins any field it sets.
Scanned — a multi-row's box code Same as above; quantity is also multiplied by the box quantity.
Scanned — the product's main barcode Only fully-generic rows. Barcode-specific prices do not apply.
Picked by name / reference Only fully-generic rows — a code-specific row needs its scan. Warehouse and schedule still filter them.

This is what guarantees the business rule "a specific barcode's price only applies when that barcode is scanned".

The warehouse test

  • Orders & invoices: a row with a warehouse participates when its own location has Is main warehouse checked — the line's stock location is never consulted. A shop-bound row prices only on that shop's POS register; a main-warehouse row prices in the editors regardless of where the stock physically sits.
  • Labels: the context is the warehouse chosen on the label sheet (see Location pricing on labels).
  • POS: a row with a warehouse participates only when its location matches the register's location.
  • Rows with an empty warehouse pass the test everywhere.

The schedule test

A scheduled row (date range, time window and/or weekday list) only participates while its schedule is active — outside the window the row contributes nothing at all, not even its flags. See Schedules (happy-hour pricing).

The winning row

After the merge, the winning row is the last participating row that supplied a value — the discount if any row carried one, otherwise the price. The winning row decides everything else on the line:

  • its price is the line's unit price (a lower row price still overrides the product's list price — an override, not a maximum),
  • its discount competes in the priority ladder (a row bound to a warehouse and/or its own barcode replaces the product's own discount, even when smaller; a fully-generic row's discount competes with it and the bigger one wins),
  • its three checkbox flags (Lock discount, Ignore quantity discounts, Ignore BXGX) apply — flags from non-winning rows are ignored.

The full discount competition is described in Discount priorities.

Worked examples

The sample product: base price 2.282 € net, main barcode 8000005045169.

Row Code Price Discount Warehouse
1 80000050451691 — 5 % V (location 9, main warehouse)
2 80000050451693 2.50 € 5 % all

Scan 80000050451691 (row 1's code)

  • Barcode test: row 1 matches; row 2 has a different code → excluded.
  • Result: row 1's 5 % discount on the product's base price.
  • The line gets price 2.282 € and 5 % discount — row 1 carries no price, so the product's own price stays.

Scan 80000050451693 (row 2's code)

  • Row 2 wins: price 2.50 € (net, as stored) and 5 % discount.

Scan 8000005045169 (the main barcode)

  • Only fully-generic rows pass — neither row qualifies (both carry codes).
  • Result: the product's own pricing, 2.282 € with no discount.

Add by name (no scan)

  • Only fully-generic rows pass the barcode test — neither row qualifies (both carry codes).
  • Result: the product's own pricing, 2.282 € with no discount.

Compare with a generic row 3 (no code, no warehouse, price 2.10 €): a name-add would now end at 2.10 € — the last generic row with a price wins. That is intended behaviour — row order is part of your pricing setup. If you want a row to win more often, place it lower in the list.

Where each context comes from

Module Warehouse context Barcode context
Order / invoice line The row's own Is main warehouse flag decides participation (the line's stock location is never a pricing input) The scanned code, when the line came from a scan
Product change on a line Same as above None (a picker selection — generic rows only)
Label sheet Warehouse selected on the sheet The scanned code, when the label came from a scan
POS register The register's configured location Always the scanned code

Frequently asked

Why didn't my warehouse-specific price apply? Either the row's schedule is currently inactive, or the selling surface is not the one the row is bound to: in orders and invoices a warehouse-bound row needs its location marked Is main warehouse; on the POS it needs to match the register's location. Check the row's warehouse and schedule, and the flag on the location itself.

Can several rows combine? Yes — that is the per-field merge. A generic discount row plus a barcode-specific price row combine: the scanned row sets the price, the generic row supplies the discount if the scanned row has none.

Does changing a row later change existing lines? Yes — lines are re-resolved from the current rows every time the order or invoice is opened or edited (quantity changes, customer changes, reloads). A schedule that has ended therefore stops applying on the next re-evaluation, and the winning row's ID is stamped on the line for reference. Two things are never touched: a manually typed line discount keeps its percentage, and a manually typed price is never overwritten. Cancelled documents are frozen.