Status: proposal for approval (T-57, Q-57). Nothing changes on the site until it is approved.
Data: every code, finish, CCT and beam below comes from the master workbook, as parsed by the importer on 27 October 2026. Nothing is invented; where the workbook has a gap, the gap is shown.
1. In short
Today every product has a code like BU121213. It is unique (mostly), but it tells you nothing: you cannot see from it that it is a Lune R 10W downlight in matt black at 3000 K. The proposal adds a second, readable code to every product code.
RLCeiling Recessed trimLess
-
LNRseries: Lune R
01010 W
-
MBMatt Black
303000 K
Today's BU121213 becomes RL-LNR010-MB30. Three promises:
Today's codes stay.BU121213 remains the permanent identifier for quote history and the future ERP. Nothing that already points at it breaks.
One to one. Each new code belongs to exactly one of today's codes, and the other way round. The new code is a readable name for the same product, not a new product.
Readable and sortable. The new code always has the same blocks in the same order and width, so a list sorts by category, then product, then wattage, then finish, then light colour.
Look up a code
Type one of today's codes to see the code the scheme would give it, block by block. Every one of today's codes in the workbook is here. The series codes and dictionaries are a draft: they become final only when you approve them, and a code marked pending waits on one of the decisions in §7.
Upper or lower case, with or without spaces. You can also type a product name (for example Lune R 10W) to list its codes, or a proposed code to find today's one.
Draft mapping of every code in the master workbook.
Blocks are separated by a hyphen and every block has a fixed width.
Characters: the digits 0–9 and the capital letters A–Z except I and O. Because the letters I and O never appear, a round character is always zero and an upright stroke is always one, even handwritten or on a poor phone line.
Length: 14 characters for most products, 18 when the beam is part of the code, 17 when a model is needed. The spec-sheet target of 18 is met by every code in the workbook today.
Family code: the first two blocks alone (RL-LNR010) name the whole product family. Products quoted by family (no codes today) are quoted with this family code. A family code has two blocks, a product code three or more, so the two can never be confused.
Codes are frozen once issued. If a finish is later renamed or a product moves category, its code does not change. A code is never reused for another product, even after a product is withdrawn.
Segment table
#
Block
Width
What it holds
Examples
1
Category
2 letters
One code per website category (16), plus AX for accessories
RL Ceiling Recessed Trimless, EX Exterior, DR LED Drivers
2a
Series
3 characters
The product line, from a registry: two characters for the collection plus one for the line
Only for families where finish, light and beam do not tell the codes apart. A running number until the client names the real difference
01, 02 …
Reserved:XX / XXX = "not applicable or not stated"; AX = accessory; Z as the first character of a block = special or project-only version (never used by the catalogue); no new code ever starts with BU, so it cannot be mistaken for one of today's codes.
3. Ten sample families
Chosen to cover every shape the catalogue has. Four are families you named (Lune R 10W, Aglaia 12W IP66, Emergence I, Gisele 10W Diffused); six fill shapes your list did not cover (a beam per code, an optic chosen on the quote line, a colour product, accessories, a family without codes, an LED driver). The other six families you named are in Appendix B.
3.1 Lune R 10W — a simple recessed downlight (finish × CCT)
Ceiling Recessed Trimless · IP20 · one beam for the whole family (24°), so the beam is not in the code. Family code RL-LNR010 · 12 codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU121198
Matt White
2700K
—
RL-LNR010-MW27
BU121201
Matt White
3000K
—
RL-LNR010-MW30
BU121204
Matt White
4000K
—
RL-LNR010-MW40
BU121210
Matt Black
2700K
—
RL-LNR010-MB27
BU121213
Matt Black
3000K
—
RL-LNR010-MB30
BU121216
Matt Black
4000K
—
RL-LNR010-MB40
BU121222
Polish White
2700K
—
RL-LNR010-PW27
BU121225
Polish White
3000K
—
RL-LNR010-PW30
BU121228
Polish White
4000K
—
RL-LNR010-PW40
BU121234
Polish Black
2700K
—
RL-LNR010-PB27
BU121237
Polish Black
3000K
—
RL-LNR010-PB30
BU121240
Polish Black
4000K
—
RL-LNR010-PB40
3.2 Extense S 7W — the beam is part of each code
Ceiling Recessed Trimless · IP20 · each code has its own beam (15°, 24° or 35°), so the code gets the beam block. This is the longest shape: 18 characters. Family code RL-EXS007 · 9 codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU114138
White body/ Black reflector
2700K
15°
RL-EXS007-WB27-015
BU114139
White body/ Black reflector
2700K
24°
RL-EXS007-WB27-024
BU114140
White body/ Black reflector
2700K
35°
RL-EXS007-WB27-035
BU114141
White body/ Black reflector
3000K
15°
RL-EXS007-WB30-015
BU114142
White body/ Black reflector
3000K
24°
RL-EXS007-WB30-024
BU114143
White body/ Black reflector
3000K
35°
RL-EXS007-WB30-035
BU114144
White body/ Black reflector
4000K
15°
RL-EXS007-WB40-015
BU114145
White body/ Black reflector
4000K
24°
RL-EXS007-WB40-024
BU114146
White body/ Black reflector
4000K
35°
RL-EXS007-WB40-035
3.3 Martine 8W — the optic is chosen on the quote line
Ceiling Recessed Trimless · IP20 · the workbook lists optics 15°/24°/36° for the family but gives one code per finish and CCT, not one per optic. The code therefore has no beam block; the visitor picks the optic on the quote line, and the quote shows it next to the code (for example RL-MRT008-TW30 · optic 24°). Whether each optic should get its own code is a question for the client (§7). Family code RL-MRT008 · 6 codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU120276
Text White
2700K
—
RL-MRT008-TW27
BU120279
Text White
3000K
—
RL-MRT008-TW30
BU120282
Text White
4000K
—
RL-MRT008-TW40
BU120288
Text Black
2700K
—
RL-MRT008-TB27
BU120291
Text Black
3000K
—
RL-MRT008-TB30
BU120294
Text Black
4000K
—
RL-MRT008-TB40
3.4 Aglaia 24W RGBW IP66 — a colour product
Exterior · IP66 · one beam for the family (30°). The light block holds the colour (RW = RGBW) instead of a Kelvin value. The white-light Aglaia 24W IP66 also exists at 24 W, so the colour line gets its own series code (AGC, not AGL): that is how the scheme keeps two families with the same name and wattage apart. Family code EX-AGC024 · 2 codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU115495
Grey
RGBW
—
EX-AGC024-GYRW
BU115491
Black
RGBW
—
EX-AGC024-BKRW
3.5 Aglaia 12W IP66 — an exterior IP66 product
Exterior · IP66 · one beam for the family (24°). Family code EX-AGL012 · 6 codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU115344
Black
2700K
—
EX-AGL012-BK27
BU115349
Black
3000K
—
EX-AGL012-BK30
BU115354
Black
4000K
—
EX-AGL012-BK40
BU115369
Grey
2700K
—
EX-AGL012-GY27
BU115374
Grey
3000K
—
EX-AGL012-GY30
BU115379
Grey
4000K
—
EX-AGL012-GY40
3.6 BU1616T — a profile with accessories
Profile System · the profile itself has no code in the workbook; its two codes are accessories (an end cap and a bracket). Accessories use the reserved category AX, followed by the parent profile's product block and a four-letter block: accessory type (EC end cap, BR bracket) + finish (WH white, XX not stated). Profiles have no wattage, so the number is a running number (001). Family code PR-PRF001 · 2 accessory codes.
Today's code
Finish
CCT / colour
Beam
Proposed code
WEC1616T
White End Cap
—
—
AX-PRF001-ECWH
MBracket1616T
Metal Bracket
—
—
AX-PRF001-BRXX
3.7 Led Track Light Fixed 60W — a family without codes
Industrial · IP20 · 60 W · no codes in the workbook; staff assign the exact code when quoting. The optics (30°/60°/90°/120°/PC Diff/Double Asym) are chosen on the quote line. The family is quoted with its family code ND-LTF060. Its sister, Led Track Light Double 60W, would be ND-LTD060.
No product codes: the family code is the only code.
3.8 Emergence I — an emergency light that needs the model block
Emergency Lights · IP54 · all nine codes are White, 6500 K, with no beam — finish and light cannot tell them apart (the workbook flags this family as ambiguous). The model block keeps every code distinct. Today the difference only lives inside the old code (the "Model" column shows that part); until the client names what LFP, CV, CS, RF, FB and PL03/05/10 mean, the model block is a plain running number. The name has no wattage, so the number block is a running number (001, which also matches the "I" in the name). Family code EM-EMG001 · 9 codes.
Today's code
Finish
CCT / colour
Beam
Model
Proposed code
BU-EXIUNI2-X1LFP
White
6500K
—
X1LFP
EM-EMG001-WH65-01
BU-EXIUNI2-X1LFP CV
White
6500K
—
X1LFP CV
EM-EMG001-WH65-02
BU-EXIUNI2-X1CS
White
6500K
—
X1CS
EM-EMG001-WH65-03
BU-EXIUNI2-X1CS CV
White
6500K
—
X1CS CV
EM-EMG001-WH65-04
BU-EXIUNI2-X1RF
White
6500K
—
X1RF
EM-EMG001-WH65-05
BU-EXIUNI2-X1FB
White
6500K
—
X1FB
EM-EMG001-WH65-06
BU-EXIUNI2- 1PL03
White
6500K
—
1PL03
EM-EMG001-WH65-07
BU-EXIUNI2- 1PL05
White
6500K
—
1PL05
EM-EMG001-WH65-08
BU-EXIUNI2- 1PL10
White
6500K
—
1PL10
EM-EMG001-WH65-09
3.9 60W IP20 — an LED driver
LED Drivers · IP20 · no codes in the workbook. The family code uses the driver's rated wattage: DR-DRV060. The other drivers would be DR-DRV100, DR-DRV150 and DR-DRV200.
No product codes: the family code is the only code.
3.10 Gisele 10W Diffused — a magnetic-track product with a missing code
Magnetic System · IP20 · one beam for the family (120°). The workbook has a 3000 K row with no code, so today that version cannot be sold on the site. The scheme can name it (MG-GSD010-TB30), but the code stays reserved — not shown — until the client confirms the product exists and gives it one of today's codes (or agrees that the new code is enough). Family code MG-GSD010 · 2 codes + 1 reserved.
Today's code
Finish
CCT / colour
Beam
Proposed code
BU114949
Textured Black
2700K
—
MG-GSD010-TB27
BU114951
Textured Black
4000K
—
MG-GSD010-TB40
none in workbook
Textured Black
3000K
—
MG-GSD010-TB30reserved
4. Edge cases and how the scheme handles them
Situation
Today
With the scheme
Beam: one for the whole family (Lune R 10W, 24°)
Shown as a fact on the product page
Not in the code (it never varies inside the family)
Beam: different per code (Extense S 7W)
Third picker axis
Beam block, e.g. -015
Beam: option list chosen on the quote line (Martine 8W)
Optic picked on the quote line
No beam block; the optic stays on the quote line next to the code
Some codes of a family have a beam, some do not (Aubin XTL 9W: "Diffused glass" versions)
Placeholder "—" on the beam axis
XXX in the beam block
No finish or no CCT (Terra 48W Adj has no finish)
Axis missing
XX in that half of the look block (GR-TRA048-XX30)
Colours (RGB, RGBW, RED, BLUE, GREEN)
Mixed into the CCT column
Two-letter colour code in the light block (RG, RW, RD, BL, GN)
The client confirms what they are first; "DMXS12" (the control type) would go in the model block, not the colour
Accessories (end caps, brackets)
Variations of the profile family
Reserved category AX + parent product block + type and finish
Families without codes (58, e.g. drivers, many profiles)
"Code assigned by Búho"
Quoted with the family code (DR-DRV060)
Ambiguous families (16, e.g. Emergence I)
Extra "Model" axis showing the old code
Model block -01, -02…; the client is asked for the real difference
The same code in two families (43 codes in the workbook, e.g. BU108764 in Orbit I X, Orbit II Moon S and Orbit II X)
All those families are left out of the import
New codes are built from the family's own blocks, so two families can never produce the same new code. Each old code can be linked to only one new code, so a duplicated old code stays unlinked until the client says which family owns it
Same name and wattage, different product (41 groups: Aglaia 24W vs Aglaia 24W RGBW, Solar 25W IP44 vs Solar R 25W, Neo Flex 8W in six sizes, Maigre 40W in seven versions)
Told apart only by the title
Each product line gets its own series code (AGL/AGC, SLA/SLR); the registry refuses a family block that already exists
Same title in two categories (Martine 10W and 20W are both recessed and magnetic)
The second one is left out of the import
Different series codes (MRT recessed, MRM magnetic)
Multi-head names ("Lune S II 10W x2", Martine 4W = 2×2 W)
—
The wattage in the name (010, 004); the series code already tells single and double heads apart
Decimal wattages (Metta I 7.5W, LED strip 4.8W)
—
Rounded to whole watts (008, 005); the registry guarantees uniqueness
No wattage at all (profiles, emergency lights)
—
Running number within the series (001, 002…)
Names starting with I or O (Orbit, Industrial)
—
The series skips those letters: Orbit → RB…, Industrial → ND
Special versions for one project
—
Reserved: a block starting with Z is never used by the catalogue
5. What would change on the site
Only what people see. Data, links and the ERP key stay as they are.
Product page: the picker shows the new code large (with the copy button) and today's code just under it as "Ref. BU121213". The "All codes in this family" table gets both columns.
Search and links: searching either code, or opening ?code= with either code, finds the product.
Quote list, request emails, PDFs and CSV export: every line shows both codes. Each request's snapshot stores both, so a sent request always shows the codes it was sent with.
Families without codes: the quote line shows the family code ("DR-DRV060 · exact code assigned by Búho").
wp-admin: staff see both codes on every request and message.
Not changed: today's code stays the WooCommerce SKU and the permanent key for the ERP and quote history; URLs, filters and datasheets stay as they are (the datasheet PDFs show today's codes until the client reissues them).
6. How we would get there
You approve the rule (this page), then the client approves it.
The lead prepares the dictionaries — 16 category codes, one series code per product line, the finish list, the colour list and the beam list — and the client approves them.
The importer generates a new code for every one of today's codes and checks them all: every code unique, every code at most 18 characters, nothing that looks like an old code. Anything it cannot code (an unknown finish, a duplicated old code, a missing code) goes on the client's fix list, like the import issues today.
The approved codes are frozen in a registry file in the repository (old code ↔ new code, plus the family codes). From then on, a re-import never changes an issued code; only new products get new codes.
The site shows both codes (§5). A dry run on staging first, then live.
The client starts using the new codes in its own price lists, datasheets and packaging, at its own pace.
The ERP connects on today's codes. Switching the ERP to the new code as its main key can be decided later; the registry makes that a lookup, not a migration.
7. Decisions needed
For Ibrahim
Approve the shapeCC-SSSNNN-FFLL[-BBB][-MM], including the category at the front. Recommended: yes — it makes lists sort by category and reads well on a spec sheet.
Which code leads on the site: the new code large with "Ref. BU…" under it (recommended), or today's code first until the client has adopted the new one.
Accessories: own AX category block (recommended — an accessory code can never be mistaken for a light), or the parent profile's category.
For the client
The finish list: are "Text White" and "Textured White" the same finish (both would be TW)? Same for "Text Black"/"Textured Black". Some finish names also hold an IP rating or a wattage ("… (White Reflector) IP44", "ss316 front cover 36W"), and there are typos ("Snad Grey"). The clean list decides the finish codes.
Optics chosen on the quote line (11 families today, e.g. Martine 8W): keep one code per finish × CCT and the optic on the quote line (recommended — matches today's codes one to one), or give each optic its own code.
The 16 ambiguous families: what really tells their codes apart (e.g. Emergence I: LFP, CV, CS, RF, FB, PL03/05/10)? The answer replaces the running-number model block with a meaningful one.
Missing codes (e.g. Gisele 10W Diffused 3000K): does the product exist, and should it get one of today's codes?
The 43 codes used by two or more families: which family owns each code?
Series codes for products whose name is only a number (drivers "60W IP20", profiles "BU1616T"): accept DRV / PRF with a number, or propose names.
Using the new codes outside the site (datasheets, price lists, packaging) — and from when.
Appendix A — technical details
A.1 Grammar
product code : ^[A-HJ-NP-Z]{2}-[0-9A-HJ-NP-Z]{3}[0-9]{3}-[0-9A-HJ-NP-Z]{4}(-[0-9A-HJ-NP-Z]{3})?(-[0-9]{2})?$
family code : ^[A-HJ-NP-Z]{2}-[0-9A-HJ-NP-Z]{3}[0-9]{3}$
Upper case only; input is normalised (trim, upper-case, Unicode dashes → -) before lookup.
Within a family every code (accessories apart) has the same blocks: either all codes have a beam block or none; either all have a model block or none.
The beam block (3 characters) and the model block (2 digits) differ in width, so a parser always knows which is which.
A.2 Category codes
Category
Code
Category
Code
Ceiling Recessed Trim
RT
Track Light
TR
Ceiling Recessed Trimless
RL
Exterior
EX
Ceiling Surface
CS
Inground Lamp
GR
Wall Recessed
WR
Industrial
ND
Wall Surface
WS
LED Strip
LS
Profile System
PR
Underwater
UW
Suspended
SU
Magnetic System
MG
Accessories (any category)
AX
LED Drivers
DR
Emergency Lights
EM
The category block records the category when the code is issued; moving a product later does not change its code.
A.3 Dictionaries used in the samples
Finishes:MW Matt White · MB Matt Black · PW Polish White · PB Polish Black · TW Text/Textured White · TB Text/Textured Black · TG Text Grey · WH White · BK Black · GY Grey · WB White body / Black reflector · RW / RC / RS Textured White with White / Chrome / Silver reflector · XX none. Guidance for the full list: first letter = treatment (M matt, P polished, T textured, S sand, G gun), second = colour (W white, B black, G grey); plain colours get a two-letter colour code; two-tone and special finishes get a dictionary code. The workbook has 83 raw finish values today; after the client's cleanup (decision 4) we expect roughly 45–50 codes.
Light:27303540506065 (Kelvin ÷ 100) · RG RGB · RW RGBW · RD Red · GN Green · BL Blue · XX none. Other colour names in the workbook ("Red & pink", "Light Green", "Nattier Blue") get codes once the client confirms them.
Accessory types:EC end cap · BR bracket (more as the client supplies them: clip, connector, cover, diffuser…).
Series used here:LNR Lune R · EXS Extense S · MRT Martine (recessed/surface) · MRM Martine (magnetic) · AGL Aglaia · AGC Aglaia RGB/RGBW · PRF aluminium profiles · LTF / LTD Led Track Light Fixed / Double · EMG Emergence · DRV LED drivers · GSD Gisele Diffused · RBM Orbit Moon S · PCP PCP Profile · SLA Solar (IP44) · SLR Solar R · FAB Fabio · TRA Terra. Series codes are assigned by hand once, then frozen.
A.4 Checks run on the real workbook (27 October 2026)
The 88 sample codes (49 in §3, 39 in Appendix B) are all unique, all match the grammar, and the longest is 18 characters.
None of the 1,954 SKU rows (1,885 distinct codes) in the workbook matches the new grammar, so an old code can never be read as a new one, and search can tell them apart by shape.
41 groups of families share the same collection and wattage (Lune 5/7/10/18/30 W, Aglaia and Phantom white vs RGBW, Neo Flex 8 W in six sizes, Maigre 40 W in seven versions…). That is why the series code names the product line, not the collection, and why the registry, not a formula, gives out series codes.
A.5 Storage and display (when built)
Today's code stays in the WooCommerce variation SKU (_sku) — the ERP key.
New meta: _buho_code on each variation (unique), _buho_family_code on each product. Written only by the importer, from the registry.
Registry file data/code-registry.php (in git): families (family key → family code), codes (old code → new code) and reserved codes. The importer refuses any change to an issued pair; it only adds.
Generation (for new products): category from the sheet, series from the registry (a new product line needs a series code first), wattage from the title, finish/light/beam from the dictionaries, model only when the family is ambiguous. An unknown dictionary value or a block collision is an import error for that family (new issue codes such as CODE_UNMAPPED_FINISH, CODE_COLLISION), like today's duplicate-SKU errors.
Search, the picker (?code=), the quote list snapshot, the PDF, emails, CSV and the ERP REST read both codes. data-no-translation applies to the new code as to today's.
Appendix B — the other families you named
All codes of the six remaining families from your list, to show the scheme on products you know.
Orbit I Moon S 15W IP65
Wall Surface · family code WS-RBM015
Today's code
Finish
CCT / colour
Beam
Proposed code
BU111829
White
2700K
—
WS-RBM015-WH27
BU111830
White
3000K
—
WS-RBM015-WH30
BU111831
White
4000K
—
WS-RBM015-WH40
BU111833
Black
2700K
—
WS-RBM015-BK27
BU111834
Black
3000K
—
WS-RBM015-BK30
BU111835
Black
4000K
—
WS-RBM015-BK40
BU111837
Grey
2700K
—
WS-RBM015-GY27
BU111838
Grey
3000K
—
WS-RBM015-GY30
BU111839
Grey
4000K
—
WS-RBM015-GY40
PCP Profile 30W IP20
Suspended · family code SU-PCP030
Today's code
Finish
CCT / colour
Beam
Proposed code
BU20625
Text Black
2700K
—
SU-PCP030-TB27
BU20626
Text Black
3000K
—
SU-PCP030-TB30
BU20627
Text Black
4000K
—
SU-PCP030-TB40
BU20629
Text White
2700K
—
SU-PCP030-TW27
BU20630
Text White
3000K
—
SU-PCP030-TW30
BU20631
Text White
4000K
—
SU-PCP030-TW40
BU20633
Text Grey
2700K
—
SU-PCP030-TG27
BU20634
Text Grey
3000K
—
SU-PCP030-TG30
BU20635
Text Grey
4000K
—
SU-PCP030-TG40
Solar 25W IP44
Industrial · family code ND-SLA025. The three finishes differ only in the reflector, so the finish codes name the reflector (RW, RC, RS).
Today's code
Finish
CCT / colour
Beam
Proposed code
BU108373
Textured White (White Reflector)
2700K
—
ND-SLA025-RW27
BU108374
Textured White (White Reflector)
3000K
—
ND-SLA025-RW30
BU108375
Textured White (White Reflector)
4000K
—
ND-SLA025-RW40
BU108377
Textured White (Chrome Reflector)
2700K
—
ND-SLA025-RC27
BU108378
Textured White (Chrome Reflector)
3000K
—
ND-SLA025-RC30
BU108379
Textured White (Chrome Reflector)
4000K
—
ND-SLA025-RC40
BU108381
Textured White (Silver Reflector)
2700K
—
ND-SLA025-RS27
BU108382
Textured White (Silver Reflector)
3000K
—
ND-SLA025-RS30
BU108383
Textured White (Silver Reflector)
4000K
—
ND-SLA025-RS40
Martine 4W
Ceiling Surface · family code CS-MRT004
Today's code
Finish
CCT / colour
Beam
Proposed code
BU123922
Text White
2700K
—
CS-MRT004-TW27
BU123923
Text White
3000K
—
CS-MRT004-TW30
BU123924
Text White
4000K
—
CS-MRT004-TW40
BU123934
Text Black
2700K
—
CS-MRT004-TB27
BU123935
Text Black
3000K
—
CS-MRT004-TB30
BU123936
Text Black
4000K
—
CS-MRT004-TB40
Fabio 12W
Track Light · family code TR-FAB012
Today's code
Finish
CCT / colour
Beam
Proposed code
BU114013
Textured White
2700K
—
TR-FAB012-TW27
BU114014
Textured White
3000K
—
TR-FAB012-TW30
BU114015
Textured White
4000K
—
TR-FAB012-TW40
Terra 48W Adj
Inground Lamp · family code GR-TRA048. No finish in the workbook, so the finish half is XX. Today's codes end in "-Adj"; the new code does not need it, because every Terra family is adjustable.