# Exercise 7. A bulk-order discount An exercise for the [numbers and money](/tutorials/numbers/) page. The page's package computes copy fees and knows the bulk-order threshold: over a hundred pages. **Setup.** Introduce a ten-percent discount for bulk orders. An order of 101 pages must receive the discounted fee `13635.00 KZT`; an order of seven pages gets no discount at all: the discounted-fee question answers `NEITHER`, not "zero discount". **Hint.** A rate is not a number but a share: see how the researcher rate is declared on the page. Rounding must be explicit. Below is the solution. Try it yourself first. ## Solution The header, relations, and constants from the page, plus one relation and one constant: ```law language "law.core" version "0.2"; package tutorial.archive version "0.13.1"; namespace "urn:law:tutorial:archive"; entity Person; entity CopyOrder; relation copy_order(o: CopyOrder, p: Person, pages: Integer) kind empirical { key(o); } relation copy_fee(o: CopyOrder, amount: Money) kind institutional { key(o); } relation bulk_fee(o: CopyOrder, amount: Money) kind institutional { key(o); } const PAGE_RATE: Money = 150 KZT; const BULK_PAGES: Integer = 100; const BULK_RATE: Decimal = 90 percent; rule CopyFee strict { for o: CopyOrder; for p: Person; for n: Integer; when copy_order(o, p, n); then copy_fee(o, n * PAGE_RATE); } ``` The discount norm reads the already computed fee rather than computing it again: ```law rule BulkDiscount strict { for o: CopyOrder; for p: Person; for n: Integer; for a: Money; when copy_order(o, p, n) and n > BULK_PAGES and copy_fee(o, a); then bulk_fee(o, round(a * BULK_RATE, 2, "HALF_UP")); } ``` Why `NEITHER` on seven pages is more correct than a zero discount. The archive rules do not say "the small-order discount is zero"; they are silent about small orders. A norm deriving zero would be a statement the text lacks, and a consumer asking "what is the discount" would receive an answer instead of the honest "there is no discount". ## Check | Facts | Question | Answer | |---|---|---| | order of 101 pages | `bulk_fee(order1, 13635.00 KZT)` | `TRUE_ONLY` | | order of 101 pages | `bulk_fee(order1, 13635 KZT)` | `TRUE_ONLY` | | order of 7 pages | `bulk_fee(order1, 945.00 KZT)` | `NEITHER` | | 101 pages, without the `BulkDiscount` norm | `bulk_fee(order1, 13635.00 KZT)` | `NEITHER` | The second row checks one misconception: a rounded sum prints with two decimal places, but money compares as magnitudes, and `13635 KZT` is the same sum. This page's first version promised `NEITHER` here, and the check corrected it. What the exercise teaches. A derived-magnitude norm rests on another norm's head rather than repeating its computation: if the page rate changes, the discount recomputes itself. The rate is declared a share, rounding explicit, both decisions visible in the package text.