PRODUCT.1287 — Field & Program Map

Canonical map of the PRODUCT.1287 UniData table: its dictionary (field layout), how densely those fields are actually populated, and the AFTEC BASIC programs in S:\LinuxShare\pro3prog that read or write it. Built 2026-07-06 from the live DICT (GET /api/dict/dev/tables/PRODUCT.1287), a 200-record data sample, and a pro3prog source scan.


What this table is

PRODUCT.1287 is the manufacturing / engineering extension record for a part. It shares its key (CO!PARTNO, e.g. 1!054761) with the PRODUCT master item — PRODUCT holds the item identity (description, MRP type, obsolescence flag), and PRODUCT.1287 holds engineering/routing sidecar data (routing codes, MTBF, safety flag, paint, assembly cross-refs). Think of it as a 1:1 companion to PRODUCT, not a standalone entity.

Key facts

File typeF (hashed)
KeyCO!PARTNO (company prefix + part number)
Dictionary entries61 — 36 D-type (31 distinct attribute positions + 5 aliases) + 25 I-type calculated
Populated in practice~3 attributes carry real data (see fill rates) — the table is defined-rich but data-sparse

Attribute-8 collision

Attribute 8 is MTBF in PRODUCT.1287, but attribute 8 is the INC/OBS obsolescence flag in the sibling PRODUCT table. Same position, different file, different meaning. Any code addressing “attr 8” must be explicit about which file it opened.


D-type attributes (physical layout)

Fill % measured over the first 200 records. Aliases (F1ENG.STAT, F2PROD.DWG, F7PHYS, F8MTBF, F12PAINT) are collapsed to the semantic name.

PosFieldConvFmtMVFill %Notes
1ENG.STAT3L3.0Engineering status
2PROD.DWG20L5.0Product drawing; also the ASSY→COMP cross-ref slot written by E0052
3(F3) FASTENERS10R0
4(F4) CONDUIT10R0
5(F5) CONDUCTORS10R0
6(F6) TERMINATIONS10R0
7PHYS6L5.0Physical part; also the COMP→ASSY cross-ref slot written by E0052
8MTBF5R93.5Mean time between failures (hours). Often the literal "NA"
9F9 (ROUTE CODES)1L91.5Routing codes; written by VB_ROUTE.* (attr 9)
10(F10) MANF.PARTNO50L0
11F11 (SAFETY ITEM)1L39.0Safety-item flag
12PAINT2L2.0
13ASSYCODE6L0
14ASSYCOMP6L0
15ASSYQTY6R0
16ASSYWU6L0
17FOOTPRINT6L0
18LAST.REC.DATED2/8L16.5Date (epoch 1967-12-31)
19MRPX4L0
20LABEL.RQRD1L0
21PLANORD.NOTE15L0
22LAST.ACT.DATED2/8L13.5Last receipt/issue date
23KEEP.DATED2/8L0
24COUNT.ERR10L0
25BODY.BOXMD26R2.5Bounding box X/Y/Z (see BB.X/Y/Z)
26RSVD.BIN6L0
27WELD.TYPE3L0.5
28TAX.CODE8L0
29PAINT.NOTE20L0
30(F30) PAINT CODES1L0
31(F31) PAINT DESC10L0

Reality: only MTBF (8), route codes (9), and safety flag (11) are broadly populated; the two date fields are partial (13–17%); the remaining ~25 attributes are effectively empty in the sample.


I-type (calculated) fields — mostly virtual foreign keys

The 25 I-type entries are not stored data — they are DICT expressions evaluated at read time. Many TRANS() out to other tables, which is the important structural insight: description, MRP type, GT code, and cost do not live in PRODUCT.1287.

FieldConvExpressionResolves from
DESCTRANS(PRODUCT,@ID,'F1','X')PRODUCT (F1)
DESC2TRANS(PRODUCT,@ID,'F22','X')PRODUCT (F22)
MRPTYPETRANS(PRODUCT,@ID,'F10','X')PRODUCT (F10)
GTCODETRANS(ITEMMANF,@ID,'F9','X')ITEMMANF
TRANS.ASYTRANS(ITEMMANF,@ID,'F6','X')ITEMMANF
LMATMD4TRANS(ITEMCA,CO!PARTNO,'F8','X')ITEMCA (material cost)
LCVENDMD4TRANS(ITEMCA,CO!PARTNO,'F10','X')ITEMCA (vendor cost)
LCLABMD4TRANS(ITEMCA,CO!PARTNO,'F12','X')ITEMCA (labor cost)
TOTLSTMD4LMAT+LCVEND+LCLABderived total last cost
BB.X/BB.Y/BB.ZMD2FIELD(BODY.BOX,@VM,n)attr 25 split
CO / PARTNOFIELD(@ID,"!",n)key split
MW/MECHASSY/ELECASSY/JS.ROUTEEXTRACT(F9,1,n,0)route-code positions
ERR.BIN/ERR.MVEQTY/ERR.CNTQTYFIELD(COUNT.ERR,@VM,n)attr 24 split
ASSYCOMP.COUNT/.EXIST, RTE.CNT, C.ENG.STATDCOUNT / IF / concatderived

Cost lives in ITEMCA, not here. A consumer wanting last cost should read ITEMCA (or the TOTLST I-type), never a stored PRODUCT.1287 attribute.


Programs in pro3prog that touch PRODUCT.1287

A source scan matched 118 program files (after dropping temp/test/data noise). Collapsed into logical families and separated by era, the real surface is much smaller. Version families (an OG plus later customized revisions — .REV1/2/3, A, _DOTNET) are grouped; the _DOTNET suffix marks the variant forked for the .NET/WCF interop layer.

Writers / mutators (verified by reading the source)

Program (family)Live?Operation on PRODUCT.1287
VB_WRITEPRODUCT (VBBASE, 2000)✅ liveFull-record writeWRITE PART1287REC ON PRODUCT.1287,ID. The canonical write path (used by the .NET write flow)
E0052 (PBSBASE) + VB_E0052A / VB_E0052A.REV1 (VBBASE)✅ liveInteractive part-master assembly↔component maintenanceWRITEVs attr 2 (PROD xref) and 7 (PHYS xref); blanks them on unlink
VB_ROUTE.REV2 (2021) + .REV1 (2017) + VB_ROUTE.DELETE (2015)✅ live (REV2)RoutingWRITEVU ROUTE.SUGG ON PRODUCT.1287,ROUTEID,9 (maintains route codes at attr 9)
DELETE.PRODUCT (PBSBASE, 2018)✅ liveGuarded delete + cascade — 7 safety checks, then DELETE PRODUCT.1287,KEY and cascades to PRODUCT, PRODUCT.NOTES, ITEMCA, ITEMQTY, ITEMORD, ITEMMANF, ITEMHIST, PRD.PRICE
VB_DELETE0001 (1997)legacyOlder delete utility

VB_UPDATECOST (2025) and PRODUCT.LDS.1287.UPDATE (2002) open/read PRODUCT.1287 but write elsewhere — the former writes cost to ITEMCA/PVXREF, the latter writes the sibling PRODUCT.LDS.1287. They are readers of this table.

Readers — live cohort (2018–2026)

Representative, version-families collapsed:

  • BOM engines: VB_BOMX.REV1 (the explosion sub the API calls), VB_BOMLIST.REV1/REV1A/_DOTNET, VB_BOMEXPLORER.3/.3.REV3, VB_BOMNOTROUTED.REV3/REV2/REV1, VB_JOBBOM.REV1, VB_IMPORTBOM.REV1
  • Part / product info: VB_PARTINFO.REV2 (API part lookup), VB_PRODUCT.REV1/_DOTNET, VB_PRODUCT_DB + VB_PRODUCT_DB_2 (⚠ both declare SUBROUTINE VB_PRODUCT_DB — OG + customized fork), VB_PRODUCTS.REV1, VB_GET.PARTINFO
  • Inventory / history: VB_GET.INVENTORY, VB_GET.ITEMHIST, VB_INACT.INVNTY, VB_OPENPOINQ.REV7/REV6
  • WIP BOM / spare-parts quoting: WIPBMF.REV6/REV7/REV8, VB_WIPBMF.REV5, VB_SPQUOTEMAINT2.REV3/REV2/REV1, SP_QUOTELINEINFO, VB_READ.SP.QUOTE.REV1, VB_BMF.REV1
  • Reports (PBSBASE, still maintained): RPT.PARTMASTER, RPT.INVHIST/RPT.INVHIST2, RPT.INVENTORY, RPT.PO, RPT.APHIST, RPT.JOBPARTS, RPT.100HEPARTS, RPT.FIXEDPRICEPARTS, SFPACK, PORECEIPT, UPDATECOSTVENDOR, VB_WO.VERIFY.REV1

Legacy / likely defunct (1995–2002 PBSBASE)

~40 files last touched 1995–2002 — old reporting and batch jobs that reference the table but are almost certainly out of the live path. Notable clusters: FAC.COST.RPT, FAC.JPC.RPT, FACILITY.RPT, FACILITY.JPC, JPH.BUILD, JPH.ALLOC.FAC, LDS.RPT, LDS.CNFDNCE2, LDS.INDX.Q, LDS.FLCHA.Q, the SBOM.* set, the 2013 SP.* spare-parts batch set (SP.MTBF, SP.LIST, SP.ALL.BAT, …), PROD.BOM.CHK, PROD.ROLLUP, PRODINQ, PRODUCTEM_COPY, E0055/E0055-CONTROL, E0065, ENGRSCHD, ENGRWO.EM, ECONNECT.RPT, ELECT.CONN.EM, DCROUTE.EM, BLD.JOB.COSTS, PROMISE.DUMP/PROMISE.UPDATE, MRPSHRTS.AUTO(+.6710), INV.INQ, INACT.INVNTY, NOTROUTED.EM, CA1740, I.0001, SROUTE.HRS.UPD, CI, BKPLOT.ASSY, JOB.ELEC.EM, JOB.PROD.ROLL, SP.ALL.PROJ.

“Live vs defunct” here is inferred from file mtime + naming + which subs the API demonstrably calls, not from a production VOC/call-graph. Treat the legacy list as candidates for retirement, to be confirmed against actual invocation before any cleanup.


The LDS sidecar — PRODUCT.LDS.1287 and associated

There is a second file keyed on the same CO!PARTNO: PRODUCT.LDS.1287. It is not a hand-edited peer of PRODUCT.1287 — it is a daily-rebuilt materialized projection derived from it.

How it’s built. PRODUCT.LDS.1287.UPDATE (PBSBASE, authored 2002 by JPT, “run as a daily job”) selects every non-obsolete product (SELECT PRODUCT WITH GT.CODE='PRODUCT' WITH F8 # 'O') and, per product, reads PRODUCT.1287 to denormalize product↔physical status plus a classification code:

AttrFieldFill %Sourced from
1PROD.STAT9.0PRODUCT.1287 attr 1 (ENG.STAT) of the product
2PHYS.NO100PRODUCT.1287 attr 7 (PHYS) — the product’s physical part
3PHYS.STAT10.5ENG status of that PHYS’s own PRODUCT.1287 record
4PROD.CLASS97.5matched from the product description → PRODUCT.CLASS.1287
5PHOTOS0(defined, unused in sample)

Plus 6 I-type helpers (INACT.OBS→PRODUCT INC/OBS, PROD.CLASS.NAME→PRODUCT.CLASS.1287, PROD.DESC/PROD.DESC2→PRODUCT, CO/PROD.NO key splits). Real payload = PHYS.NO + PROD.CLASS.

Relationship to PRODUCT.1287: downstream, one-way. PRODUCT.1287 is the source of truth (physical part at attr 7, ENG status at attr 1); PRODUCT.LDS.1287 is a flattened daily snapshot for LDS-facing consumers. Editing PRODUCT.LDS.1287 directly is pointless — the daily job overwrites it.

Legacy "LDS" ≠ LDS 4.0

This table’s “LDS” is the 2002 product/physical classification lineage — the conceptual ancestor of, but not the same thing as, the current LDS 4.0 initiative. If LDS 4.0 needs product classification, treat this stale derived table as a candidate to verify-still-running or supersede, not to build on.

Associated tables (the DICT knows 1,489 tables; genuinely LDS-related):

TableWhat it is
PRODUCT.CLASS.1287Class-code → CLASS.NAME lookup that PRODUCT.LDS.1287 resolves PROD.CLASS against
WORK.LDS.1287Thin (F1, F2/LVL) — WIP/level structure, minimal content
CO.STDS.LDS.1287Thin (F1F4, unnamed) — company-standards LDS, minimal content
CHILDSUPPORT.1287⚠️ not LDS — a substring false match (chiLDSupport). Actually payroll child-support garnishment data (name, CS.ID, account/routing #, amount). Notable only as PII sitting in the AFTEC schema