@campfire-interactive/master-data-client 3.0.2 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/client.d.ts +18 -2
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +27 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/equipment.d.ts +17 -0
  6. package/dist/equipment.d.ts.map +1 -0
  7. package/dist/equipment.js +73 -0
  8. package/dist/equipment.js.map +1 -0
  9. package/dist/index.d.ts +10 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +19 -3
  12. package/dist/index.js.map +1 -1
  13. package/dist/partAttributes.d.ts +14 -0
  14. package/dist/partAttributes.d.ts.map +1 -0
  15. package/dist/partAttributes.js +63 -0
  16. package/dist/partAttributes.js.map +1 -0
  17. package/dist/partTypeDefaults.d.ts +12 -0
  18. package/dist/partTypeDefaults.d.ts.map +1 -0
  19. package/dist/{partFamilies.js → partTypeDefaults.js} +12 -9
  20. package/dist/partTypeDefaults.js.map +1 -0
  21. package/dist/partTypes.d.ts +13 -0
  22. package/dist/partTypes.d.ts.map +1 -0
  23. package/dist/partTypes.js +57 -0
  24. package/dist/partTypes.js.map +1 -0
  25. package/dist/parts.d.ts +10 -1
  26. package/dist/parts.d.ts.map +1 -1
  27. package/dist/parts.js +11 -0
  28. package/dist/parts.js.map +1 -1
  29. package/dist/plants.d.ts +2 -2
  30. package/dist/plants.d.ts.map +1 -1
  31. package/dist/plants.js +3 -19
  32. package/dist/plants.js.map +1 -1
  33. package/dist/processFamilies.d.ts +19 -0
  34. package/dist/processFamilies.d.ts.map +1 -0
  35. package/dist/processFamilies.js +54 -0
  36. package/dist/processFamilies.js.map +1 -0
  37. package/dist/rateBooks.d.ts +18 -0
  38. package/dist/rateBooks.d.ts.map +1 -0
  39. package/dist/{suppliers.js → rateBooks.js} +22 -30
  40. package/dist/rateBooks.js.map +1 -0
  41. package/dist/rateCatalog.d.ts +46 -0
  42. package/dist/rateCatalog.d.ts.map +1 -0
  43. package/dist/rateCatalog.js +130 -0
  44. package/dist/rateCatalog.js.map +1 -0
  45. package/dist/rateElements.d.ts +31 -0
  46. package/dist/rateElements.d.ts.map +1 -0
  47. package/dist/rateElements.js +104 -0
  48. package/dist/rateElements.js.map +1 -0
  49. package/dist/rateLibraries.d.ts +3 -1
  50. package/dist/rateLibraries.d.ts.map +1 -1
  51. package/dist/rateLibraries.js +8 -0
  52. package/dist/rateLibraries.js.map +1 -1
  53. package/dist/rateTables.d.ts +32 -0
  54. package/dist/rateTables.d.ts.map +1 -0
  55. package/dist/rateTables.js +116 -0
  56. package/dist/rateTables.js.map +1 -0
  57. package/dist/rates.d.ts +2 -3
  58. package/dist/rates.d.ts.map +1 -1
  59. package/dist/rates.js +19 -10
  60. package/dist/rates.js.map +1 -1
  61. package/dist/types.d.ts +620 -122
  62. package/dist/types.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/dist/partFamilies.d.ts +0 -12
  65. package/dist/partFamilies.d.ts.map +0 -1
  66. package/dist/partFamilies.js.map +0 -1
  67. package/dist/suppliers.d.ts +0 -14
  68. package/dist/suppliers.d.ts.map +0 -1
  69. package/dist/suppliers.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -111,7 +111,7 @@ export type QuoteStatus = 'draft' | 'costing_requested' | 'costing_in_progress'
111
111
  */
112
112
  export type QuoteCallerRole = 'omsf' | 'cpq' | 'admin';
113
113
  /**
114
- * Quote type discriminator (added 3.1.0). `rfq` = new-business quote (the
114
+ * Quote type discriminator (added 3.0.2). `rfq` = new-business quote (the
115
115
  * default and the only kind before 2026-07). `eco` = Engineering Change
116
116
  * Order quote — a change against an already-awarded quote's assembly,
117
117
  * priced and approved as its own quote. Immutable post-create. When 'eco',
@@ -204,13 +204,13 @@ export interface Quote {
204
204
  */
205
205
  effectiveVolumesByYear: EffectiveVolumeByYear[] | null;
206
206
  status: QuoteStatus;
207
- /** rfq | eco — see {@link QuoteType}. Immutable post-create. (3.1.0) */
207
+ /** rfq | eco — see {@link QuoteType}. Immutable post-create. (3.0.2) */
208
208
  quoteType: QuoteType;
209
209
  /**
210
210
  * ECO-only: the source quote's as-awarded unit price/cost, frozen at ECO
211
211
  * creation. The stored operands for delta reporting — readers compute
212
212
  * delta = effective − baseline; the delta itself is never stored. Always
213
- * null on rfq-type quotes. Decimal-as-string like targetPrice. (3.1.0)
213
+ * null on rfq-type quotes. Decimal-as-string like targetPrice. (3.0.2)
214
214
  */
215
215
  baselineUnitPrice: string | null;
216
216
  baselineUnitCost: string | null;
@@ -288,13 +288,13 @@ export interface CreateQuoteInput {
288
288
  /**
289
289
  * Quote type — defaults to 'rfq'. Immutable post-create. When 'eco',
290
290
  * `referenceQuoteId` becomes REQUIRED and must point to an in-tenant,
291
- * AWARDED, non-eco quote (server-validated). (3.1.0)
291
+ * AWARDED, non-eco quote (server-validated). (3.0.2)
292
292
  */
293
293
  quoteType?: QuoteType;
294
294
  /** ECO-only (422 otherwise): frozen as-awarded unit price of the source
295
- * quote. Decimal as number or string; string preferred. (3.1.0) */
295
+ * quote. Decimal as number or string; string preferred. (3.0.2) */
296
296
  baselineUnitPrice?: number | string;
297
- /** ECO-only (422 otherwise): frozen as-awarded unit cost. (3.1.0) */
297
+ /** ECO-only (422 otherwise): frozen as-awarded unit cost. (3.0.2) */
298
298
  baselineUnitCost?: number | string;
299
299
  }
300
300
  /**
@@ -356,7 +356,7 @@ export interface ListQuotesOptions {
356
356
  quality?: 'draft' | 'verified';
357
357
  customerCompanyId?: string;
358
358
  programId?: string;
359
- /** Filter by quote type. Omitting returns both kinds. (3.1.0) */
359
+ /** Filter by quote type. Omitting returns both kinds. (3.0.2) */
360
360
  quoteType?: QuoteType;
361
361
  include?: ('customerCompany' | 'program')[];
362
362
  }
@@ -407,96 +407,89 @@ export interface ListMaterialsOptions {
407
407
  quality?: 'draft' | 'verified';
408
408
  category?: string;
409
409
  }
410
- export type PlantStatus = 'active' | 'archived';
411
410
  export interface Plant {
412
411
  id: string;
413
412
  tenantId: string;
414
- companyId: string | null;
415
- locationId: string | null;
416
413
  code: string;
417
414
  name: string;
418
- description: string | null;
419
- /** Denormalised; useful even when locationId is null. */
415
+ location: string | null;
416
+ /** Denormalised country. */
420
417
  country: string | null;
421
- /** Free-text in v1; may FK to Region later. */
418
+ /** Free-text region. */
422
419
  region: string | null;
423
420
  headcount: number | null;
424
- annualCapacityHours: number | null;
421
+ /** Annual throughput capacity (units). */
422
+ annualCapacity: number | null;
425
423
  /** 0..1. */
426
424
  currentUtilization: number | null;
425
+ /** $/hr fully-loaded labor cost. Decimal-ish; carried as number. */
426
+ laborCostPerHour: number | null;
427
427
  riskLevel: string | null;
428
+ /** Plant operating currency (ISO 4217). Defaults to "USD". */
429
+ currency: string;
428
430
  numShifts: number;
429
431
  hoursPerShift: number;
430
432
  workingDaysPerYear: number;
431
433
  /** 0..1; defaults to 0.15. */
432
434
  indirectHeadcountPct: number;
433
- status: PlantStatus;
434
- quality: 'draft' | 'verified';
435
- createdBy: string;
436
- updatedBy: string;
435
+ active: boolean;
437
436
  createdAt: string;
438
437
  updatedAt: string;
439
- company?: Company;
440
- location?: Location;
441
438
  }
442
439
  export interface CreatePlantInput {
443
440
  code: string;
444
441
  name: string;
445
- description?: string;
446
- companyId?: string | null;
447
- locationId?: string | null;
442
+ location?: string;
448
443
  country?: string;
449
444
  region?: string;
450
445
  headcount?: number;
451
- annualCapacityHours?: number;
446
+ annualCapacity?: number;
452
447
  currentUtilization?: number;
448
+ laborCostPerHour?: number;
453
449
  riskLevel?: string;
450
+ currency?: string;
454
451
  numShifts?: number;
455
452
  hoursPerShift?: number;
456
453
  workingDaysPerYear?: number;
457
454
  indirectHeadcountPct?: number;
458
- quality?: 'draft' | 'verified';
455
+ active?: boolean;
459
456
  }
460
457
  export interface UpdatePlantInput {
461
458
  code?: string;
462
459
  name?: string;
463
- description?: string | null;
464
- companyId?: string | null;
465
- locationId?: string | null;
460
+ location?: string | null;
466
461
  country?: string | null;
467
462
  region?: string | null;
468
463
  headcount?: number | null;
469
- annualCapacityHours?: number | null;
464
+ annualCapacity?: number | null;
470
465
  currentUtilization?: number | null;
466
+ laborCostPerHour?: number | null;
471
467
  riskLevel?: string | null;
468
+ currency?: string;
472
469
  numShifts?: number;
473
470
  hoursPerShift?: number;
474
471
  workingDaysPerYear?: number;
475
472
  indirectHeadcountPct?: number;
476
- quality?: 'draft' | 'verified';
473
+ active?: boolean;
477
474
  }
478
475
  export interface ListPlantsOptions {
479
476
  limit?: number;
480
477
  cursor?: string;
481
478
  sort?: string;
482
479
  q?: string;
483
- status?: PlantStatus | 'all';
484
- quality?: 'draft' | 'verified';
485
- companyId?: string;
486
- locationId?: string;
480
+ active?: boolean;
487
481
  country?: string;
488
482
  region?: string;
489
- include?: ('company' | 'location')[];
490
483
  }
491
484
  export interface GetPlantOptions {
492
- include?: ('company' | 'location')[];
485
+ /** Reserved for future relation expansions; currently no-op. */
486
+ include?: string[];
493
487
  }
494
488
  export type PlantMatchType = 'exact_code' | 'trgm_name';
495
489
  export interface PlantMatch {
496
490
  id: string;
497
491
  name: string;
498
492
  code: string;
499
- companyId: string | null;
500
493
  country: string | null;
501
494
  region: string | null;
502
495
  /** 1.0 for exact-code match; pg_trgm similarity in (threshold..1] otherwise. */
@@ -505,8 +498,6 @@ export interface PlantMatch {
505
498
  }
506
499
  export interface PlantMatchQuery {
507
500
  name: string;
508
- /** When set, restricts both exact and fuzzy matches to plants of this company. */
509
- companyId?: string;
510
501
  /** When present, an exact match on (tenantId, code) is unioned at score=1.0. */
511
502
  code?: string;
512
503
  }
@@ -533,152 +524,485 @@ export interface MergePlantsRequest {
533
524
  survivorId: string;
534
525
  mergedIds: string[];
535
526
  }
536
- export type RateLibraryStatus = 'draft' | 'active' | 'archived';
537
- export type RateEntryKind = 'labor' | 'machine' | 'overhead' | 'material' | 'freight';
538
527
  export type RateSourcingMode = 'fixed' | 'indexed';
539
- export interface RateLibrary {
528
+ export type RateRollForwardMode = 'carry_forward_flagged' | 'blank_force_entry';
529
+ export type RateValueOrigin = 'entered' | 'escalated' | 'overridden' | 'carried_forward';
530
+ /** Legacy alias retained for the v0 rate-table entries + the lookup `kind` param. */
531
+ export type RateEntryKind = 'labor' | 'machine' | 'overhead' | 'material' | 'freight';
532
+ export interface RateBook {
540
533
  id: string;
541
534
  tenantId: string;
542
535
  name: string;
543
- code: string;
544
- description: string | null;
545
- currency: string;
536
+ year: number;
537
+ status: string;
546
538
  effectiveDate: string;
547
- effectiveTo: string | null;
548
- status: RateLibraryStatus;
549
- quality: 'draft' | 'verified';
550
- version: number;
539
+ currency: string;
540
+ horizonStart: number;
541
+ horizonEnd: number;
542
+ escalationPct: number;
543
+ rollForwardMode: RateRollForwardMode;
551
544
  publishedAt: string | null;
552
- publishedBy: string | null;
553
- archivedAt: string | null;
554
- archivedBy: string | null;
555
- createdBy: string;
556
- updatedBy: string;
557
545
  createdAt: string;
558
546
  updatedAt: string;
559
- entries?: RateEntry[];
560
- /** Which app most-recently wrote any field on this row. Derived from
561
- * `FieldProvenance` server-side. Defaults to `'master-data'` for rows
562
- * without provenance entries. Added in 2.15.0. */
563
- lastEditedBy?: SourceApp;
564
547
  }
565
- export interface RateEntry {
548
+ export interface CreateRateBookInput {
549
+ name: string;
550
+ year: number;
551
+ effectiveDate: string;
552
+ currency?: string;
553
+ horizonStart?: number;
554
+ horizonEnd?: number;
555
+ escalationPct?: number;
556
+ rollForwardMode?: RateRollForwardMode;
557
+ }
558
+ export interface UpdateRateBookInput {
559
+ name?: string;
560
+ year?: number;
561
+ effectiveDate?: string;
562
+ currency?: string;
563
+ horizonStart?: number;
564
+ horizonEnd?: number;
565
+ escalationPct?: number;
566
+ rollForwardMode?: RateRollForwardMode;
567
+ }
568
+ export interface ListRateBooksOptions {
569
+ limit?: number;
570
+ cursor?: string;
571
+ sort?: string;
572
+ q?: string;
573
+ status?: string;
574
+ year?: number;
575
+ currency?: string;
576
+ }
577
+ export interface RateElement {
566
578
  id: string;
567
579
  tenantId: string;
568
- rateLibraryId: string;
569
- kind: RateEntryKind;
580
+ scope: string;
570
581
  plantId: string | null;
571
- skillTier: string | null;
572
- materialId: string | null;
573
- regionId: string | null;
582
+ rateLineId: string | null;
583
+ gradeCode: string | null;
584
+ equipmentCode: string | null;
585
+ equipmentId: string | null;
586
+ skillClass: string | null;
574
587
  lane: string | null;
588
+ mode: string | null;
589
+ container: string | null;
590
+ /** Computed server-side from the element's dimensions. */
591
+ identityKey: string;
592
+ escalationPct: number | null;
593
+ externalRef: string | null;
594
+ sourceSystem: string | null;
595
+ createdAt: string;
596
+ updatedAt: string;
597
+ values?: RateValue[];
598
+ }
599
+ export interface CreateRateElementInput {
600
+ scope: string;
601
+ plantId?: string | null;
602
+ rateLineId?: string | null;
603
+ gradeCode?: string | null;
604
+ equipmentCode?: string | null;
605
+ equipmentId?: string | null;
606
+ skillClass?: string | null;
607
+ lane?: string | null;
608
+ mode?: string | null;
609
+ container?: string | null;
610
+ escalationPct?: number | null;
611
+ externalRef?: string | null;
612
+ sourceSystem?: string | null;
613
+ }
614
+ export interface ListRateElementsOptions {
615
+ limit?: number;
616
+ cursor?: string;
617
+ sort?: string;
618
+ scope?: string;
619
+ plantId?: string;
620
+ rateLineId?: string;
621
+ equipmentCode?: string;
622
+ equipmentId?: string;
623
+ gradeCode?: string;
624
+ }
625
+ export interface RateValue {
626
+ id: string;
627
+ tenantId: string;
628
+ elementId: string;
629
+ effectiveFrom: string;
630
+ effectiveTo: string | null;
631
+ origin: RateValueOrigin;
575
632
  /** Decimal serialized as string to preserve precision across the wire. */
576
633
  rate: string;
577
- unit: string;
578
634
  currency: string;
635
+ uom: string;
636
+ ratePerKg: string | null;
579
637
  sourcingMode: RateSourcingMode;
580
- indexRef: string | null;
581
- lastSyncedAt: string | null;
582
- notes: string | null;
583
- createdBy: string;
584
- updatedBy: string;
638
+ sourceSystem: string | null;
639
+ priceIndexId: string | null;
640
+ indexRefLegacy: string | null;
641
+ bookId: string;
585
642
  createdAt: string;
586
643
  updatedAt: string;
587
644
  }
588
- export interface CreateRateLibraryInput {
589
- name: string;
590
- code: string;
591
- description?: string;
645
+ export interface CreateRateValueInput {
646
+ effectiveFrom: string;
647
+ effectiveTo?: string | null;
648
+ origin?: RateValueOrigin;
649
+ /** Number accepted; string preferred for precision. */
650
+ rate: number | string;
592
651
  currency?: string;
652
+ uom: string;
653
+ ratePerKg?: number | string | null;
654
+ sourcingMode?: RateSourcingMode;
655
+ sourceSystem?: string | null;
656
+ priceIndexId?: string | null;
657
+ indexRefLegacy?: string | null;
658
+ bookId: string;
659
+ }
660
+ export interface ListRateValuesOptions {
661
+ bookId?: string;
662
+ asOf?: string;
663
+ }
664
+ export interface RateTable {
665
+ id: string;
666
+ tenantId: string;
667
+ name: string;
668
+ effectiveDate: string;
669
+ effectiveTo: string | null;
670
+ status: string;
671
+ year: number;
672
+ currency: string;
673
+ version: number;
674
+ publishedAt: string | null;
675
+ publishedById: string | null;
676
+ archivedAt: string | null;
677
+ archivedById: string | null;
678
+ createdAt: string;
679
+ updatedAt: string;
680
+ entries?: RateEntry[];
681
+ }
682
+ export interface CreateRateTableInput {
683
+ name: string;
593
684
  effectiveDate: string;
594
685
  effectiveTo?: string | null;
686
+ year: number;
687
+ currency?: string;
595
688
  }
596
- export interface UpdateRateLibraryInput {
689
+ export interface UpdateRateTableInput {
597
690
  name?: string;
598
- description?: string | null;
599
- currency?: string;
600
691
  effectiveDate?: string;
601
692
  effectiveTo?: string | null;
602
- quality?: 'draft' | 'verified';
693
+ year?: number;
694
+ currency?: string;
603
695
  }
604
- export interface ListRateLibrariesOptions {
696
+ export interface ListRateTablesOptions {
605
697
  limit?: number;
606
698
  cursor?: string;
607
699
  sort?: string;
608
700
  q?: string;
609
- status?: RateLibraryStatus | 'all';
610
- /** Filter to libraries effective on this date (effectiveDate <= asOf, effectiveTo null or > asOf). */
611
- asOf?: string;
612
- code?: string;
701
+ status?: string;
702
+ year?: number;
613
703
  currency?: string;
614
704
  }
615
- export interface GetRateLibraryOptions {
616
- include?: 'entries'[];
705
+ export interface RateEntry {
706
+ id: string;
707
+ tenantId: string;
708
+ rateTableId: string;
709
+ category: string;
710
+ subcategory: string;
711
+ region: string | null;
712
+ /** Decimal serialized as string to preserve precision across the wire. */
713
+ rate: string;
714
+ unit: string;
715
+ effectiveDate: string;
716
+ notes: string | null;
717
+ key: string | null;
718
+ alias: string | null;
719
+ type: string | null;
720
+ plantId: string | null;
721
+ plantSubtype: string | null;
722
+ skillTier: string | null;
723
+ lane: string | null;
724
+ mode: string | null;
725
+ sourcingMode: string | null;
726
+ indexRef: string | null;
727
+ source: string | null;
728
+ lastSyncedAt: string | null;
729
+ syncStatus: string | null;
730
+ confidence: number | null;
731
+ entryVersion: number;
732
+ currency: string | null;
733
+ density: number | null;
734
+ densityUnit: string | null;
735
+ ratePerKg: string | null;
736
+ createdAt: string;
737
+ updatedAt: string;
617
738
  }
618
739
  export interface CreateRateEntryInput {
619
- kind: RateEntryKind;
620
- plantId?: string | null;
621
- skillTier?: string | null;
622
- materialId?: string | null;
623
- regionId?: string | null;
624
- lane?: string | null;
740
+ category: string;
741
+ subcategory: string;
742
+ region?: string | null;
625
743
  /** Number accepted; string preferred for precision. */
626
744
  rate: number | string;
627
745
  unit: string;
628
- currency?: string;
629
- sourcingMode?: RateSourcingMode;
630
- indexRef?: string | null;
746
+ effectiveDate: string;
631
747
  notes?: string | null;
632
- }
633
- export interface UpdateRateEntryInput {
748
+ key?: string | null;
749
+ alias?: string | null;
750
+ type?: string | null;
634
751
  plantId?: string | null;
752
+ plantSubtype?: string | null;
635
753
  skillTier?: string | null;
636
- materialId?: string | null;
637
- regionId?: string | null;
638
754
  lane?: string | null;
755
+ mode?: string | null;
756
+ sourcingMode?: string | null;
757
+ indexRef?: string | null;
758
+ source?: string | null;
759
+ currency?: string | null;
760
+ density?: number | null;
761
+ densityUnit?: string | null;
762
+ ratePerKg?: number | string | null;
763
+ }
764
+ export interface UpdateRateEntryInput {
765
+ category?: string;
766
+ subcategory?: string;
767
+ region?: string | null;
639
768
  rate?: number | string;
640
769
  unit?: string;
641
- currency?: string;
642
- sourcingMode?: RateSourcingMode;
643
- indexRef?: string | null;
770
+ effectiveDate?: string;
644
771
  notes?: string | null;
645
- }
646
- export interface ListRateEntriesOptions {
647
- kind?: RateEntryKind;
648
- }
649
- export interface RateLookupInput {
650
- kind: RateEntryKind;
772
+ key?: string | null;
773
+ alias?: string | null;
774
+ type?: string | null;
651
775
  plantId?: string | null;
776
+ plantSubtype?: string | null;
652
777
  skillTier?: string | null;
653
- materialId?: string | null;
654
- regionId?: string | null;
655
778
  lane?: string | null;
779
+ mode?: string | null;
780
+ sourcingMode?: string | null;
781
+ indexRef?: string | null;
782
+ source?: string | null;
783
+ currency?: string | null;
784
+ density?: number | null;
785
+ densityUnit?: string | null;
786
+ ratePerKg?: number | string | null;
787
+ }
788
+ export interface RateLookupInput {
789
+ rateLineId?: string;
790
+ /** Legacy alias for rateLineId; accepted server-side for back-compat. */
791
+ kind?: string;
792
+ plantId?: string;
793
+ equipmentCode?: string;
794
+ equipmentId?: string;
795
+ skillClass?: string;
796
+ gradeCode?: string;
797
+ lane?: string;
798
+ mode?: string;
799
+ container?: string;
656
800
  /** ISO date (YYYY-MM-DD). Defaults to today. */
657
801
  asOf?: string;
658
802
  }
659
803
  export interface RateLookupResult {
660
- libraryId: string;
661
- libraryCode: string;
662
- libraryVersion: number;
663
- entryId: string;
664
- kind: RateEntryKind;
804
+ elementId: string;
805
+ bookId: string;
806
+ identityKey: string;
665
807
  /** Decimal serialized as string. */
666
808
  rate: string;
667
- unit: string;
809
+ /** Decimal serialized as string; null when not a mass-basis material rate. */
810
+ ratePerKg: string | null;
811
+ uom: string;
668
812
  currency: string;
669
813
  sourcingMode: RateSourcingMode;
670
- indexRef: string | null;
671
814
  /** Echoes the asOf the server resolved against (YYYY-MM-DD). */
672
815
  asOf: string;
673
- /** Echoes the dimensions on the matched entry — handy for consumer audit logging. */
816
+ /** Echoes the dimensions on the matched element — handy for consumer audit logging. */
674
817
  resolvedFrom: {
818
+ rateLineId: string | null;
675
819
  plantId: string | null;
676
- skillTier: string | null;
677
- materialId: string | null;
678
- regionId: string | null;
820
+ equipmentCode: string | null;
821
+ equipmentId: string | null;
822
+ skillClass: string | null;
823
+ gradeCode: string | null;
679
824
  lane: string | null;
825
+ mode: string | null;
826
+ container: string | null;
680
827
  };
681
828
  }
829
+ export interface Equipment {
830
+ id: string;
831
+ tenantId: string;
832
+ plantId: string;
833
+ code: string;
834
+ name: string;
835
+ processFamily: string;
836
+ capacityHoursPerYear: number;
837
+ cavities: number;
838
+ /** OEE availability factor (0..1). */
839
+ availabilityPct: number;
840
+ /** OEE performance factor (0..1). */
841
+ performancePct: number;
842
+ /** CPQ-authored operational defaults — advisory metadata for non-CPQ apps. */
843
+ defaultHeadcount: number;
844
+ defaultAutomationPct: number;
845
+ defaultMachinesPerOperator: number;
846
+ defaultSetupCrew: number;
847
+ active: boolean;
848
+ createdAt: string;
849
+ updatedAt: string;
850
+ }
851
+ export interface CreateEquipmentInput {
852
+ plantId: string;
853
+ code: string;
854
+ name: string;
855
+ processFamily: string;
856
+ capacityHoursPerYear?: number;
857
+ cavities?: number;
858
+ availabilityPct?: number;
859
+ performancePct?: number;
860
+ defaultHeadcount?: number;
861
+ defaultAutomationPct?: number;
862
+ defaultMachinesPerOperator?: number;
863
+ defaultSetupCrew?: number;
864
+ active?: boolean;
865
+ }
866
+ export interface UpdateEquipmentInput {
867
+ code?: string;
868
+ name?: string;
869
+ processFamily?: string;
870
+ capacityHoursPerYear?: number;
871
+ cavities?: number;
872
+ availabilityPct?: number;
873
+ performancePct?: number;
874
+ defaultHeadcount?: number;
875
+ defaultAutomationPct?: number;
876
+ defaultMachinesPerOperator?: number;
877
+ defaultSetupCrew?: number;
878
+ active?: boolean;
879
+ }
880
+ export interface ListEquipmentOptions {
881
+ limit?: number;
882
+ cursor?: string;
883
+ sort?: string;
884
+ q?: string;
885
+ plantId?: string;
886
+ processFamily?: string;
887
+ active?: boolean;
888
+ }
889
+ export interface ProcessFamily {
890
+ id: string;
891
+ tenantId: string | null;
892
+ code: string;
893
+ label: string;
894
+ category: string;
895
+ sortOrder: number;
896
+ active: boolean;
897
+ isDefault: boolean;
898
+ createdAt: string;
899
+ updatedAt: string;
900
+ }
901
+ export interface CreateProcessFamilyInput {
902
+ code: string;
903
+ label: string;
904
+ category: string;
905
+ sortOrder?: number;
906
+ active?: boolean;
907
+ isDefault?: boolean;
908
+ }
909
+ export interface UpdateProcessFamilyInput {
910
+ label?: string;
911
+ category?: string;
912
+ sortOrder?: number;
913
+ active?: boolean;
914
+ isDefault?: boolean;
915
+ }
916
+ export interface Uom {
917
+ id: string;
918
+ tenantId: string | null;
919
+ code: string;
920
+ label: string;
921
+ bindings: string[];
922
+ basis: string;
923
+ perBaseFactor: number | null;
924
+ needsDensity: boolean;
925
+ active: boolean;
926
+ createdAt: string;
927
+ updatedAt: string;
928
+ }
929
+ export interface CreateUomInput {
930
+ code: string;
931
+ label: string;
932
+ bindings?: string[];
933
+ basis: string;
934
+ perBaseFactor?: number | null;
935
+ needsDensity?: boolean;
936
+ active?: boolean;
937
+ }
938
+ export interface UpdateUomInput {
939
+ label?: string;
940
+ bindings?: string[];
941
+ basis?: string;
942
+ perBaseFactor?: number | null;
943
+ needsDensity?: boolean;
944
+ active?: boolean;
945
+ }
946
+ export interface RateLine {
947
+ id: string;
948
+ tenantId: string;
949
+ code: string;
950
+ label: string;
951
+ binding: string;
952
+ allowedUoms: string[];
953
+ defaultUom: string | null;
954
+ escalationDefault: number | null;
955
+ active: boolean;
956
+ createdAt: string;
957
+ updatedAt: string;
958
+ }
959
+ export interface CreateRateLineInput {
960
+ code: string;
961
+ label: string;
962
+ binding: string;
963
+ allowedUoms?: string[];
964
+ defaultUom?: string | null;
965
+ escalationDefault?: number | null;
966
+ active?: boolean;
967
+ }
968
+ export interface UpdateRateLineInput {
969
+ label?: string;
970
+ binding?: string;
971
+ allowedUoms?: string[];
972
+ defaultUom?: string | null;
973
+ escalationDefault?: number | null;
974
+ active?: boolean;
975
+ }
976
+ export interface RateGrade {
977
+ id: string;
978
+ tenantId: string;
979
+ code: string;
980
+ label: string;
981
+ allowedUoms: string[];
982
+ defaultUom: string;
983
+ density: number | null;
984
+ densityUnit: string | null;
985
+ active: boolean;
986
+ createdAt: string;
987
+ updatedAt: string;
988
+ }
989
+ export interface CreateRateGradeInput {
990
+ code: string;
991
+ label: string;
992
+ allowedUoms?: string[];
993
+ defaultUom: string;
994
+ density?: number | null;
995
+ densityUnit?: string | null;
996
+ active?: boolean;
997
+ }
998
+ export interface UpdateRateGradeInput {
999
+ label?: string;
1000
+ allowedUoms?: string[];
1001
+ defaultUom?: string;
1002
+ density?: number | null;
1003
+ densityUnit?: string | null;
1004
+ active?: boolean;
1005
+ }
682
1006
  export type ExchangeRateStatus = 'draft' | 'active' | 'archived';
683
1007
  export type ExchangeRateScope = 'tenant' | 'global';
684
1008
  export interface ExchangeRate {
@@ -780,9 +1104,19 @@ export interface Part {
780
1104
  partNumber: string;
781
1105
  /** Supplier's own number; nullable for customer-numbered parts. */
782
1106
  manufacturingPartNumber: string | null;
1107
+ /** Customer's own cross-reference number for this part. Additive alias only —
1108
+ * never an identity key; canonical key stays partNumber (Decision C). */
1109
+ customerPartNumber: string | null;
783
1110
  name: string;
784
1111
  description: string | null;
1112
+ /** Part-level (rev-invariant) attribute bag, governed by the tenant's
1113
+ * part-level attribute dictionary (Decision G). Rev-specific values are on
1114
+ * PartRevision.attributes. */
1115
+ attributes: Record<string, unknown> | null;
1116
+ /** @deprecated free-text; use partTypeId (governed PartType catalog). */
785
1117
  partType: string | null;
1118
+ /** The per-tenant PartType this part is classified as. */
1119
+ partTypeId: string | null;
786
1120
  /** The per-tenant PartCategory this part belongs to. */
787
1121
  partCategoryId: string | null;
788
1122
  manufacturer: string | null;
@@ -795,6 +1129,9 @@ export interface Part {
795
1129
  createdAt: string;
796
1130
  updatedAt: string;
797
1131
  partCategory?: PartCategory;
1132
+ /** Resolved PartType (?include=partType). Named partTypeRef server-side during
1133
+ * the additive window; exposed here as the resolved catalog row. */
1134
+ partTypeRef?: PartType;
798
1135
  currentRevision?: PartRevision;
799
1136
  revisions?: PartRevision[];
800
1137
  /** Which app most-recently wrote any field on this row (provenance). */
@@ -815,31 +1152,65 @@ export interface PartRevision {
815
1152
  releaseStatus: string | null;
816
1153
  leadTime: number | null;
817
1154
  attributes: Record<string, unknown> | null;
1155
+ /** Latest costed price per unit (string-serialized Decimal). */
1156
+ latestUnitCost: string | null;
1157
+ /** ISO 4217 currency of latestUnitCost. */
1158
+ latestCostCurrency: string | null;
1159
+ /** Opaque ref to the source CPQ quote (cross-app; not FK-validated). */
1160
+ latestCostSourceQuoteId: string | null;
1161
+ latestCostedAt: string | null;
1162
+ latestCostContext: Record<string, unknown> | null;
818
1163
  status: PartStatus;
819
1164
  createdBy: string;
820
1165
  updatedBy: string;
821
1166
  createdAt: string;
822
1167
  updatedAt: string;
823
1168
  }
1169
+ /** Input for `parts.setLatestCost` — the cost-owner-only snapshot write path
1170
+ * (Decision F). Mirrors the server's SetLatestCostInput. */
1171
+ export interface SetLatestCostInput {
1172
+ /** Costed price per unit. Required, must be >= 0. */
1173
+ unitCost: number;
1174
+ /** ISO 4217 currency of unitCost (e.g. "USD"). */
1175
+ currency?: string | null;
1176
+ /** Opaque ref to the source CPQ quote (cross-app; not FK-validated). */
1177
+ sourceQuoteId?: string | null;
1178
+ /** When the cost was struck (ISO string). Defaults to now server-side. */
1179
+ costedAt?: string | null;
1180
+ /** Lossless extras about the costing (quote line id, volume band, etc.). */
1181
+ context?: Record<string, unknown> | null;
1182
+ }
824
1183
  export interface CreatePartInput {
825
1184
  partNumber: string;
826
1185
  manufacturingPartNumber?: string | null;
1186
+ customerPartNumber?: string | null;
827
1187
  name: string;
828
1188
  description?: string | null;
1189
+ /** @deprecated free-text; use partTypeId. */
829
1190
  partType?: string | null;
1191
+ partTypeId?: string | null;
830
1192
  partCategoryId?: string | null;
831
1193
  manufacturer?: string | null;
832
1194
  quality?: 'draft' | 'verified';
1195
+ /** Part-level attribute bag; validated against the tenant's part-level
1196
+ * attribute dictionary (Decision G). */
1197
+ attributes?: Record<string, unknown> | null;
833
1198
  }
834
1199
  export interface UpdatePartInput {
835
1200
  partNumber?: string;
836
1201
  manufacturingPartNumber?: string | null;
1202
+ customerPartNumber?: string | null;
837
1203
  name?: string;
838
1204
  description?: string | null;
1205
+ /** @deprecated free-text; use partTypeId. */
839
1206
  partType?: string | null;
1207
+ partTypeId?: string | null;
840
1208
  partCategoryId?: string | null;
841
1209
  manufacturer?: string | null;
842
1210
  quality?: 'draft' | 'verified';
1211
+ /** Part-level attribute bag; merged key-level (overwrite) into the existing
1212
+ * bag and validated against the tenant's part-level dictionary (Decision G). */
1213
+ attributes?: Record<string, unknown> | null;
843
1214
  }
844
1215
  export interface CreatePartRevisionInput {
845
1216
  revision: string;
@@ -862,6 +1233,7 @@ export interface ListPartsOptions {
862
1233
  status?: PartStatus | 'all';
863
1234
  quality?: 'draft' | 'verified';
864
1235
  partCategoryId?: string;
1236
+ partTypeId?: string;
865
1237
  partType?: string;
866
1238
  manufacturer?: string;
867
1239
  include?: string[];
@@ -877,6 +1249,7 @@ export interface BatchUpsertPartInput {
877
1249
  partNumber: string;
878
1250
  name?: string;
879
1251
  manufacturingPartNumber?: string | null;
1252
+ customerPartNumber?: string | null;
880
1253
  description?: string | null;
881
1254
  partType?: string | null;
882
1255
  partCategoryId?: string | null;
@@ -892,7 +1265,12 @@ export interface BatchUpsertPartInput {
892
1265
  pcfPerUnit?: number | null;
893
1266
  releaseStatus?: string | null;
894
1267
  leadTime?: number | null;
1268
+ /** Revision-level (rev-specific) attribute bag; key-merged into the revision. */
895
1269
  attributes?: Record<string, unknown> | null;
1270
+ /** Part-level (rev-invariant) attribute bag; key-merged into Part.attributes.
1271
+ * Both bags are validated against the tenant's attribute dictionary by level
1272
+ * (Decision G) — a no-op while the dictionary is empty. */
1273
+ partAttributes?: Record<string, unknown> | null;
896
1274
  }
897
1275
  export interface BatchUpsertPartsOptions {
898
1276
  /** Which app is pushing these parts; recorded in FieldProvenance. Defaults to
@@ -906,7 +1284,10 @@ export interface BatchUpsertPartsOptions {
906
1284
  }
907
1285
  /** Per-row outcome from a parts batch upsert. 'mergedFields' / 'untouched' only
908
1286
  * occur under mergePolicy='fill_empty'. `revisionCreated` is true when the row
909
- * carried a `revision` that didn't already exist on the part. */
1287
+ * carried a `revision` that didn't already exist on the part. `filledFields`
1288
+ * are Part-header columns filled/overwritten; `mergedAttributeKeys` are
1289
+ * top-level `PartRevision.attributes` keys merged on an EXISTING revision
1290
+ * (Decision D — key-level attributes merge). */
910
1291
  export interface BatchPartItemResult {
911
1292
  index: number;
912
1293
  status: 'created' | 'mergedFields' | 'untouched' | 'error';
@@ -915,6 +1296,9 @@ export interface BatchPartItemResult {
915
1296
  code?: string;
916
1297
  filledFields?: string[];
917
1298
  revisionCreated?: boolean;
1299
+ /** Top-level attribute keys merged on an existing part/revision bag (Decision D
1300
+ * rev-level + Decision G part-level). Part-level keys are prefixed `part:`. */
1301
+ mergedAttributeKeys?: string[];
918
1302
  }
919
1303
  export interface BatchUpsertPartsResult {
920
1304
  results: BatchPartItemResult[];
@@ -974,6 +1358,120 @@ export interface ListPartCategoriesOptions {
974
1358
  /** When true, request only active categories (drops archived). */
975
1359
  activeOnly?: boolean;
976
1360
  }
1361
+ export interface PartTypeDefault {
1362
+ id: string;
1363
+ code: string;
1364
+ name: string;
1365
+ displayOrder: number;
1366
+ createdBy: string;
1367
+ updatedBy: string;
1368
+ createdAt: string;
1369
+ updatedAt: string;
1370
+ }
1371
+ export interface CreatePartTypeDefaultInput {
1372
+ code: string;
1373
+ name: string;
1374
+ displayOrder?: number;
1375
+ }
1376
+ export interface UpdatePartTypeDefaultInput {
1377
+ code?: string;
1378
+ name?: string;
1379
+ displayOrder?: number;
1380
+ }
1381
+ export type PartTypeStatus = 'active' | 'archived';
1382
+ export interface PartType {
1383
+ id: string;
1384
+ tenantId: string;
1385
+ code: string;
1386
+ name: string;
1387
+ displayOrder: number;
1388
+ status: PartTypeStatus;
1389
+ /** True for tool-seeded defaults: protected (no delete/archive/code-change). */
1390
+ isDefault: boolean;
1391
+ createdBy: string;
1392
+ updatedBy: string;
1393
+ createdAt: string;
1394
+ updatedAt: string;
1395
+ }
1396
+ export interface CreatePartTypeInput {
1397
+ code: string;
1398
+ name: string;
1399
+ displayOrder?: number;
1400
+ }
1401
+ export interface UpdatePartTypeInput {
1402
+ code?: string;
1403
+ name?: string;
1404
+ displayOrder?: number;
1405
+ status?: PartTypeStatus;
1406
+ }
1407
+ export interface ListPartTypesOptions {
1408
+ /** When true, request only active types (drops archived). */
1409
+ activeOnly?: boolean;
1410
+ }
1411
+ export type AttributeDataType = 'text' | 'number' | 'boolean' | 'enum' | 'date';
1412
+ export type AttributeLevel = 'part' | 'revision';
1413
+ export type AttributeStatus = 'active' | 'archived';
1414
+ /** Typed rules stored per definition and enforced by the server on every
1415
+ * attribute write. `min`/`max` are value bounds for `number` and length bounds
1416
+ * for `text`; `regex` applies to `text`; `precision` is max decimal places for
1417
+ * `number`. `required` (v1) means "non-empty if present". */
1418
+ export interface AttributeValidation {
1419
+ required?: boolean;
1420
+ min?: number;
1421
+ max?: number;
1422
+ regex?: string;
1423
+ precision?: number;
1424
+ }
1425
+ export interface PartAttributeDefinition {
1426
+ id: string;
1427
+ tenantId: string;
1428
+ /** Stable machine key; joins to a JSON key in the value bag. Immutable. */
1429
+ key: string;
1430
+ label: string;
1431
+ dataType: AttributeDataType;
1432
+ level: AttributeLevel;
1433
+ unit: string | null;
1434
+ /** Allowed values when `dataType='enum'`; null otherwise. */
1435
+ options: string[] | null;
1436
+ group: string | null;
1437
+ validation: AttributeValidation | null;
1438
+ status: AttributeStatus;
1439
+ sortOrder: number;
1440
+ createdBy: string;
1441
+ updatedBy: string;
1442
+ createdAt: string;
1443
+ updatedAt: string;
1444
+ }
1445
+ export interface CreatePartAttributeInput {
1446
+ key: string;
1447
+ label: string;
1448
+ dataType: AttributeDataType;
1449
+ level: AttributeLevel;
1450
+ unit?: string | null;
1451
+ options?: string[] | null;
1452
+ group?: string | null;
1453
+ validation?: AttributeValidation | null;
1454
+ sortOrder?: number;
1455
+ }
1456
+ /** `key` is intentionally omitted — it's immutable once created. dataType/level
1457
+ * may be changed but only govern future writes (existing values aren't migrated). */
1458
+ export interface UpdatePartAttributeInput {
1459
+ label?: string;
1460
+ dataType?: AttributeDataType;
1461
+ level?: AttributeLevel;
1462
+ unit?: string | null;
1463
+ options?: string[] | null;
1464
+ group?: string | null;
1465
+ validation?: AttributeValidation | null;
1466
+ sortOrder?: number;
1467
+ status?: AttributeStatus;
1468
+ }
1469
+ export interface ListPartAttributesOptions {
1470
+ /** When true, request only active definitions (drops archived). */
1471
+ activeOnly?: boolean;
1472
+ /** Filter to one level (part | revision). */
1473
+ level?: AttributeLevel;
1474
+ }
977
1475
  export interface AuditLogEntry {
978
1476
  id: string;
979
1477
  tenantId: string | null;