Spare Parts Data Model

How PSI tracks recommended spare parts, MTBF, and the autogenerated .sp (Recommended Spare Parts) manual stored at K:\PROJECT\{job}\man\{job}.sp. This is the authoritative customer-facing list of parts the customer should keep on hand.


The .sp File

Every PSI machine has an autogenerated Recommended Spare Parts Manual at:

K:\PROJECT\{jobNumber}\man\{jobNumber}.sp

Format: WordPerfect (.sp extension = Spare Parts). Generated automatically from AFTEC data. Example: K:\PROJECT\2296\man\2296.sp.

The manual organizes parts into four categories:

CategoryDefinition (from manual text)
Consumable PartsWear items consumed in normal operation (blast nozzles, filters, blast hose, belts, reclaim ductwork, seals, wear plates)
Recommended Spare PartsWear items not consumable but with finite life (bearings, motors, ball screws, solenoid valves, gears, boots, pulleys, cyclones)
General Replacement PartsLocally available items requiring replacement over machine lifetime (light bulbs, fuses, batteries, electronic modules)
Sub-ComponentsRepair parts kits available for purchased components (pinch valve liners, solenoid valve kits, gaskets, replacement filters)

For each part, the manual lists:

  • PSI part number
  • Manufacturer name and catalog number
  • Description
  • Where used (parent assemblies)
  • Recommended quantity

This is the primary list a customer should reference for spare parts strategy — much more meaningful than a raw “obsolete parts” list from AFTEC.


AFTEC Data Sources

PRODUCT Table (Part Master)

Per-part metadata visible in Part Manager → “Other” tab:

Part Manager LabelAFTEC FieldNotes
Sales CategoryCATEG (attr 4)Most parts default to SPARE (“SPARE PARTS SALES”)
Sales ClassPCLS (attr 2)S = SPARE PARTS
Manf ClassMANF.CLASS (attr 20)1000=Electrical, 2000=?, 3000=Mechanical, 4000=PSI-made, 5000=Raw stock, 9000=Fasteners
Purchase CategoryPO.CAT (attr 32)e.g., 1200
Inventory CategoryINV.CAT (attr 31)e.g., RAW, JOB
CA ClassCA.CLASS (attr 21)M1, M2, M4, M9 — significance not yet confirmed

PRODUCT.1287 Table (Extended Part Data)

Part Manager LabelAFTEC FieldNotes
MTBFMTBF (also F8)Mean Time Between Failures, in hours. 0 = not measured, 99999 = effectively infinite
Engineering StatusENG.STAT (F1)OBS, FLG, FLG OBS (multi-valued)
FootprintFOOTPRINTDrawing footprint reference
Last Activity DateLAST.ACT.DATE
Last Receipt DateLAST.REC.DATE

BMF Table (Bill of Materials per project) — Where the spare-category data lives

The wiki documents VB_GETPDMLIST.REV1 (signature: VB_BOMLIST(CO, ASSYNO, BMFDATA, BMFNOTES, MESSAGE)) which returns single-level BOM with 13 columns per component:

1. comp        - component part number
2. seq         - sequence
3. desc        - description
4. status      - INC/OBS status
5. MRP         - MRP code
6. qty         - BOM quantity
7. UM          - unit of measure
8. MTBF        - Mean Time Between Failures
9. spare       - spare flag
10. cat        - category (the 4-category classification!)
11. rec qty    - recommended spare quantity
12. manual     - "in manual" flag (whether it appears in the .sp file)
13. mfg        - manufacturer

Tables Referenced: BMF, BMF.1287, BMF.NOTES, GL-COMPANY, ITEMMANF, PRODUCT, PRODUCT.1287, PRODXREF, JOBMASTER.1287, OPENWO

This means the spare parts categorization is per-BOM-line, not just per-part. The same part might be flagged as a Consumable in one machine’s BOM and a Sub-Component in another’s, depending on how it’s assembled.

Note: VB_GETPDMLIST.REV1 is documented but currently fails to load on the server (UniData error 30105). Need to investigate whether it’s missing from the catalog or has a different name. The data is likely accessible via direct BMF.1287 table reads.


Data Flow

                    K:\PROJECT\{job}\man\{job}.sp
                    (WordPerfect, autogenerated)
                              ▲
                              │
              ┌───────────────┴───────────────┐
              │   Spare Parts Manual Generator │
              │   (PSI internal tool/macro)    │
              └───────────────┬───────────────┘
                              │
                              │ reads
                              ▼
           ┌──────────────────────────────────────┐
           │     AFTEC (UniData)                  │
           │                                       │
           │  PRODUCT/PRODUCT.1287                │
           │  ├─ MTBF                             │
           │  ├─ ENG.STAT (FLG/OBS)               │
           │  ├─ MANF.CLASS                       │
           │  ├─ Spare Parts Suggested Price      │
           │  └─ ...                              │
           │                                       │
           │  BMF/BMF.1287 (per BOM line)         │
           │  ├─ spare flag                       │
           │  ├─ category (1 of 4)                │
           │  ├─ recommended quantity             │
           │  └─ in-manual flag                   │
           └──────────────────────────────────────┘

Why This Matters for Obsolescence Analysis

The AFTEC PRODUCT.F8 = "O" flag means “PSI engineering doesn’t use this in new designs” — it’s an internal standardization signal, not an OEM end-of-life indicator. Many “obsolete” parts are still actively manufactured by Rockwell, Banner, etc.

For a customer with an existing machine, the meaningful obsolescence question is:

  • Is this part on the spare parts manual (PSI told the customer to stock it)?
  • AND is it actually unavailable from the OEM?
  • AND does it have an MTBF that suggests likely failure?

Better filter for customer-facing obsolescence reports:

HIGH PRIORITY = (in spare parts manual)
              AND (OEM has formally discontinued — not just AFTEC flagged)
              AND (MTBF > 0 OR known to fail)

This dramatically reduces noise compared to a raw “obsolete parts” sweep that includes documents, raw materials, fasteners, and PSI-made physical parts.


Machine Explorer Integration (Proposed)

The PSI Explorer Machine Explorer page (https://explorer.progressivesurface.com/#machine) currently has these tabs:

  • Overview
  • Active Work
  • Service History
  • Parts & BOM
  • Drawings
  • Controls

Proposed: Add a “Spare Parts” tab (or section within Parts & BOM) showing:

Tab Layout

┌──────────────────────────────────────────────────────────────────┐
│ Spare Parts — Machine 2296 (PRATT & WHITNEY, Tinker AFB)         │
├──────────────────────────────────────────────────────────────────┤
│  ┌─ Summary ──────────────────────────────────────┐              │
│  │ 47 recommended spares  │  12 currently obsolete │              │
│  │ MTBF tracked: 31 parts │  Aftermarket only: 8   │              │
│  └────────────────────────┴────────────────────────┘              │
│                                                                    │
│  [ Consumable (15) ] [ Recommended (18) ] [ General (10) ]       │
│  [ Sub-Components (4) ] [ All ]                                   │
│                                                                    │
│  ┌── Filter: ☐ Obsolete only  ☐ Has MTBF  ☐ No replacement ─┐   │
│                                                                    │
│  Part #   Description                  Qty  MTBF   Status   PO   │
│  ──────  ─────────────────────────  ───  ────  ──────   ──   │
│  046572  TORIT FILTER CARTRIDGE       2   2400h Active   $        │
│  026008  8520-CP 9/240 PROCESSOR      1   —     OBSOLETE  ⚠       │
│  ...                                                              │
│                                                                    │
│  [Download spare parts manual (.sp)] [Generate quote] [Export]    │
└──────────────────────────────────────────────────────────────────┘

Backend Requirements

The PSI.UniData.API needs a new endpoint:

GET /api/spare-parts/dev/by-project/{jobNumber}

Returns:

{
  "jobNumber": "2296",
  "machineDescription": "...",
  "totalSpareParts": 47,
  "byCategory": {
    "Consumable": [ { partNumber, description, quantity, mtbf, manufacturer, ... } ],
    "RecommendedSpare": [ ... ],
    "GeneralReplacement": [ ... ],
    "SubComponent": [ ... ]
  },
  "obsoleteCount": 12,
  "manualUrl": "K:/PROJECT/2296/man/2296.sp"
}

Implementation Path

  1. Investigate why VB_GETPDMLIST.REV1 fails to load — confirm subroutine name and arguments
  2. Build new ASP.NET service SparePartsService that calls the subroutine (or reads BMF.1287 directly)
  3. Add API endpoint /api/spare-parts/dev/by-project/{job} and /by-project/{job}/csv
  4. Add MCP tool get_spare_parts_for_project so Ask the Fleet can answer “What spare parts should the customer stock for machine 2296?”
  5. Add Machine Explorer tab in bom-explorer-web with category tabs and obsolescence overlay
  6. Cross-reference with obsolete parts data to highlight which spares need attention

Open Questions

  1. What subroutine generates the .sp file? Likely a WordPerfect macro that calls a UniData report. Need to find it.
  2. Are there other categorization fields? The CA.CLASS field (M1-M9) might encode the 4 categories — but data so far shows mixed values.
  3. MTBF source — is it PSI-assigned, manufacturer-published, or field data?
  4. “In manual” flag — is this auto-set when the engineer marks a part as a spare in Part Manager, or is it a separate workflow?