Lab21 — Curtain · Calculation rules

Summary of all rules used by the configurator. Always update both index.html (UI + JS) and gordijn_configurator.deluge (Zoho script) whenever one of these rules changes.

Table of contents

  1. Configuration order
  2. Pleat & pleat factors
  3. Number of parts
  4. Return-pleat margin (Lab21 guideline)
  5. Side hems (floor-to-ceiling only)
  6. Cut height (length per drop)
  7. Scenario A — Floor-to-ceiling
  8. Scenario B — Drop-width fabric
  9. Lining
  10. Price calculation
  11. Fabric dimensions normalisation
  12. Warnings
  13. Lead-tape & weight cord
  14. Article specifications (aside)
  15. Filter explanation
  16. Architecture — files
  17. Synchronisation rule
  18. Zoho CRM — field mapping
  19. Pleat suitability & Roman-blind flag

1. Configuration order

  1. Curtain type — Drapery or Inbetween (filter on the article list).
  2. Finished sizes — FinishedWidth + FinishedHeight (cm).
  3. Choose article — from the filtered list with feasibility badge.
  4. Colour — per article (5–16 fictitious colours via KLEUR_POOLS).
  5. Mounting — Ceiling face-fix / Wall face-fix / Recess (in-the-day).
  6. Pleat & division — pleat, number of parts, heading tape.
  7. Lining — type, colour, price.
  8. Finishing & surcharges — weight cord, lock, lead-tape.
  9. Operation — final step (Pull-up L/R, Tilt L/R, Centre-draw, Cordless).

2. Pleat & pleat factors

PleatFactor
Wave default2.00
Double return2.50
Single return2.10
Double2.35
Single1.80

Order in dropdown: Wave → Double return → Single return → Double → Single.

3. Number of parts

No effect on effective width: all three cover the full rail. Does affect the side-hem surcharge (§5) and the return margin (§4).

4. Return-pleat margin (Lab21 guideline)

For Single return or Double return the finished width is artificially adjusted — for both Pair and 1 part left/right:

finishedWidth ≥ 300 cm  → returnMargin = 10% × finishedWidth
finishedWidth <  300 cm  → returnMargin = 30 cm
effectiveWidth = finishedWidth + returnMargin

Reason — with a return / zigzag pleat the fabric protrudes towards the back; without slack the pleats are pulled flat when closing, causing gaps at the sides or in the middle (with a Pair).

Measuring tip: the rail must sit at least 7–10 cm off the wall to prevent the pleats from rubbing against it.

5. Side hems (floor-to-ceiling only)

Drop-width fabric receives no side-hem surcharge in width (per drop the side hem fits within the roll width).

requiredFabricWidth (floor-to-ceiling) = effectiveWidth × pleat + numberOfParts × 24
requiredFabricWidth (drop-width fabric) = effectiveWidth × pleat

6. Cut height (length per drop)

rawCutHeight = finishedHeight + headingTape + bottomHem

6a. Heading tape (top hem)

Choice: 8 / 10 / 12 / 15 cm. Default 10 cm.

6b. Bottom hem

ConditionBottom hem
Lock = Yes0 cm (overlocked)
Weight cord = Yes2 cm
otherwise15 cm (steamed bottom hem)

6c. Header (finishing choice — outside the calculation)

The header (Dutch: hoofdje) is the narrow strip of fabric above the pleat tape. It is a configurator choice in Step 6 — Pleat & split that documents the workshop finish. Does not affect the cut height — it does not appear in rawCutHeight or in the cut-loss calculation.

Pleat choiceAllowed header values
Wave0 (locked, field disabled)
Single return0 (locked, field disabled)
Double return0 (locked, field disabled)
Single0 or 2.5 mm
Double0 or 2.5 mm

The UI disables the field automatically as soon as the pleat is set to a return- or Wave-choice. After choosing 2.5 mm, the value resets to 0 if the pleat is later switched to Wave or a return-pleat.

6d. Pattern repeat (informational, outside the calculation)

patroonhoogte is an article attribute that documents the vertical pattern repeat in cm, but does not enter rawCutHeight. The configurator does not round cut height up to a whole repeat — the workshop handles repeat alignment at processing time and orders extra fabric if needed.

Patterned fabric is never rotated: rotatable is forced to No (rotation would turn the pattern 90°). This rule depends on the Pattern = Patterned field, not on the value of patroonhoogte. In feasibility and compute() the rotatable fallback is therefore disabled for patterned articles, regardless of the repeat value.

7. Scenario A — Floor-to-ceiling

Fabric rolls vertically: roll height = hoogte_stof (max ~300 cm); the roll-length direction (originally "breedte_stof") is unrestricted → stored as 10000 cm.

7a. Upright (default)

Fits when rawCutHeight ≤ hoogte_stof.

numberOfDrops = 1
totalMetres   = requiredFabricWidth ÷ 100

7b. Rotated (only if rotatable = Yes, not for patterned)

When rawCutHeight > hoogte_stof with rotatable plain fabric, the fabric is turned 90°; the original height becomes the drop width.

cordLoss        = (weightCord = Yes) ? 2 cm : 0
dropWidthEff    = hoogte_stof − cordLoss
numberOfDrops   = ⌈requiredFabricWidth ÷ dropWidthEff⌉
totalMetres     = numberOfDrops × rawCutHeight ÷ 100

Weight cord with rotation: the cord is cut away (−2 cm in drop width).

7c. Not possible

rawCutHeight > hoogte_stof and (rotatable = No or pattern = Patterned) → the article is marked "Not possible".

8. Scenario B — Drop-width fabric

Fabric rolls horizontally: roll width = breedte_stof (typically 140 cm), length (originally "hoogte_stof") is unrestricted → stored as 10000 cm.

numberOfDrops    = ⌈requiredFabricWidth ÷ breedte_stof⌉
lengthPerDrop    = rawCutHeight
totalCm          = numberOfDrops × lengthPerDrop
totalMetres_m    = totalCm ÷ 100

No height limit, no rotation.

9. Lining

Options: No lining / Semi-transparent / Blackout. Lining price and colour appear only when lining ≠ No lining.

liningPrice/m¹ = (voering_prijs_per_m1 > 0)
                  ? voering_prijs_per_m1
                  : prijs_per_m1 × 0.60       (60% fallback)
liningCost     = totalMetres × liningPrice/m¹

Lining colours (5 fictitious): White, Beige, Taupe, Grey, Anthracite.

10. Price calculation

Fabric price is based on sales price incl. VAT, not on cost:

fabricPrice = totalMetres × salesPrice/m¹
totalPrice  = fabricPrice (+ liningCost where applicable)

Sales price/m¹ — source priority

  1. Manual (verkoopprijs_per_m1 field) — entered by Victor in production. This field always takes precedence.
  2. Auto formula — only for test articles where verkoopprijs_per_m1 is empty or 0:
    salesPrice/m¹ = cost × 3, rounded up to xx.95
    Auto example: cost € 12.34 → sales € 37.95.

Implementation: verkoopPrijs95(inkoop) + getVerkoopPrijs(article) in db.js. The breakdown explicitly states whether the price is manual or auto.

Lining still calculates on a cost basis (custom price or 60% fallback of cost).

11. Fabric dimensions normalisation

On every load, via seedAfmetingenPlaceholders():

TypeFieldValue
Floor-to-ceiling (Yes)breedte_stof10000 (= unlimited roll length)
Drop-width fabric (No)hoogte_stof10000 (= unlimited roll length)

In the aside (Article specifications) we display "Not relevant" instead of the number for the unlimited direction.

12. Warnings

MAX_STUK_BREEDTE_CM = 600

if effectiveWidth > 600 cm → warning:
  "split the curtain into 1 part left + 1 part right"

Height exceeded

13. Lead-tape & weight cord

14. Article specifications (aside)

Fixed, read-only display per chosen article:

Cost price is not visible (only sales price incl. VAT). Selects in the aside no longer show a dropdown arrow (pure value display).

15. Filter explanation (above article list)

3 active filters:

  1. Curtain type (chosen in step 1).
  2. Height limit for floor-to-ceiling: klaarhoogte + vliesband + onderzoom ≤ hoogte_stof.
  3. W.cord (weight cord) determines bottom hem: 2 cm or 15 cm; with Lock = 0.

16. Architecture — files

FileRole
index.htmlConfigurator (steps 1–9, calculation, article aside).
import.htmlCSV/Excel import + saved-articles overview.
db.jsRead layer on the article source (build-time data/artikelen.json) + localStorage cache, colour pools, seed migrations, esc(), verkoopPrijs95().
gordijn_configurator.delugeZoho Creator script — mirrored on index.html logic.
start.shLocal server (Python http.server or Node fallback).
berekeningsregels.htmlThis page — summary of all rules.

Saved-articles table (import.html) shows per article: Article no., Type, Description, Fabric H, Fabric W (= 10000 for floor-to-ceiling), Pattern, Pattern height (= 0 for Plain), Cost/m¹, Sales/m¹ incl. VAT, Shrink%, FtC, Light, Lining, Lining price, Rotatable, D.face, FR, Acoust., W.cord, Composition, Colours.

17. Synchronisation rule

index.html is authoritative for the business logic. With every change in:

→ also update gordijn_configurator.deluge in the same commit.

18. Zoho CRM — field mapping

The configurator is connected to Zoho CRM (module: Products). The table below maps our internal field keys to the Zoho API names and the Zoho field type that must be created in CRM. The master overview lives in db.js (ARTIKEL_FIELDS) and is automatically shown in import.html next to every field explanation.

Internal keyLabelZoho API (Products)Zoho field type
artikelnummerArticle numberProduct_CodeSingle Line
gordijn_typeCurtain typeGordijn_TypePicklist
omschrijvingDescriptionProduct_NameSingle Line
hoogte_stofFabric height (cm)Hoogte_StofNumber
breedte_stofFabric width (cm)Breedte_StofNumber
patroonPatternPatroonPicklist
patroonhoogtePattern height (cm)PatroonhoogteDecimal
patroonbreedtePattern width (cm)PatroonbreedteDecimal
prijs_per_m1Cost price (€) + UnitInkoopprijsCurrency
verkoopprijs_per_m1Sales price incl. VAT (€) + UnitVerkoopprijsCurrency
krimpercentageShrinkage percentage (%)KrimpercentagePercent
kamerhoogFloor-to-ceilingKamerhoogCheckbox
lichtdoorlatenheidLight transmissionLichtdoorlatenheidPicklist
voerenLining (default)Voering_DefaultPicklist
voering_prijs_per_m1Lining price per m¹Voering_Prijs_M1Currency
kantelbaarRotatableKantelbaarCheckbox
doublefaceDoublefaceDoublefaceCheckbox
brandvertragendFlame-retardantBrandvertragendCheckbox
akoestiekAcoustics classAkoestiekPicklist
verzwaaringskoordWeight cord (legacy)VerzwaaringskoordCheckbox
geschikt_voor_verzwaringskoordSuitable with weight cordGeschikt_Met_VerzwaringskoordCheckbox
eenheidUnit (default m¹)EenheidPicklist
samenstellingCompositionSamenstellingSingle Line
geschikte_plooiSuitable pleatGeschikte_PlooiMulti-Select Picklist
geschikt_vouwgordijnSuitable as Roman blindGeschikt_VouwgordijnPicklist
kleurenColourslocal-only

Geschikte_Plooi and Geschikt_Vouwgordijn are local-only (localStorage only); they have no column in the central articles source.

Zoho Creator (Deluge) form fields

The Zoho Creator script gordijn_configurator.deluge expects the same API names on the input form (input.Inkoopprijs, input.Verkoopprijs, input.Hoogte_Stof, …). Configuration choices (KlaarBreedte, KlaarHoogte, Plooi, Stuk, Voering, Verzwaringskoord, Band) are form fields, not Products fields.

19. Pleat suitability & Roman-blind flag

Two article fields determine which processing options are allowed for a fabric; they are not used in the metres or price calculation, but they do drive UI warnings.

Suitable pleat

Suitable as Roman blind

The pleat dropdown order matches PLOOI_OPTIES in db.js; this is shared by index.html and the seed helpers. Keep in sync with gordijn_configurator.deluge (constants plooi_*).

↑ Back to top