@campfire-interactive/master-data-client 4.12.0 → 4.13.0

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.
package/dist/types.d.ts CHANGED
@@ -97,16 +97,12 @@ export interface ListProgramsOptions {
97
97
  customerCompanyId?: string;
98
98
  /** @deprecated Use customerCompanyId. Removed in the next major. */
99
99
  oemCompanyId?: string;
100
- /** Batch-get a specific set of programs by id — returns them regardless of
101
- * status. Comma-joined server-side; cap ~100/call for URL length and chunk
102
- * larger sets. The server bumps the page size to cover the ids. */
103
- ids?: string[];
104
100
  include?: ('customerCompany' | 'oemCompany')[];
105
101
  }
106
102
  export interface GetProgramOptions {
107
103
  include?: ('customerCompany' | 'oemCompany')[];
108
104
  }
109
- export type QuoteStatus = 'draft' | 'costing_requested' | 'costing_in_progress' | 'costing_complete' | 'pricing' | 'routed_for_approval' | 'in_review' | 'approved' | 'submitted' | 'negotiating' | 'awarded' | 'lost' | 'not_taken';
105
+ export type QuoteStatus = 'draft' | 'costing_requested' | 'costing_in_progress' | 'costing_complete' | 'pricing' | 'routed_for_approval' | 'in_review' | 'approved' | 'submitted' | 'negotiating' | 'awarded' | 'lost';
110
106
  /**
111
107
  * Who is driving the transition. Required on every status update so the
112
108
  * server can enforce role-gated transitions. `admin` is the escape hatch
@@ -137,23 +133,6 @@ export interface Quote {
137
133
  name: string | null;
138
134
  customerCompanyId: string;
139
135
  programId: string | null;
140
- /**
141
- * The OEM request this quote is one competing answer to — see {@link QuoteAsk}.
142
- * Null means it competes with nothing and is awardable on its own, which is a
143
- * legitimate state, not missing data.
144
- */
145
- askId: string | null;
146
- /**
147
- * @deprecated A DERIVED MIRROR of the quote's lines — read `quoteLines.list()`
148
- * instead.
149
- *
150
- * Free text holding a part NUMBER (never a uuid), historically the quote's only
151
- * part reference. A quote is multi-part now, and this reflects the FIRST line
152
- * only, so it is lossy the moment a quote has more than one. Writes still work
153
- * for the whole deprecation window (they transparently maintain the quote's
154
- * single line), but new code should not read it as "the quote's part". Dropped
155
- * in a later major. See the nextgen ADR `2026-08-05-multi-part-quotes.md`.
156
- */
157
136
  partId: string | null;
158
137
  /**
159
138
  * The historical/parent quote this one was copied from. OMSF sets this when
@@ -232,24 +211,6 @@ export interface Quote {
232
211
  * column stays the canonical yearly curve.
233
212
  */
234
213
  effectiveVolumesByYear: EffectiveVolumeByYear[] | null;
235
- /**
236
- * The VEHICLE stream (added 2026-08-06) — how many vehicles the program
237
- * builds, NOT how many parts we sell.
238
- *
239
- * This is what each {@link QuoteLine} bridges from: `vehicleAnnualVolume ×
240
- * takeRate × partsPerVehicle` is that finished good's part volume. One quote
241
- * covering four finished goods has ONE vehicle stream and four different part
242
- * volumes, which is why the part columns above cannot serve as the input.
243
- *
244
- * **Null on every quote written before 2026-08-06**, and that is not a gap:
245
- * those quotes' lines bridge from the part columns instead, at a 100/1 bridge
246
- * that leaves the figure untouched. Read it as "does this quote calculate its
247
- * line volumes, or carry them directly?" rather than as missing data.
248
- */
249
- vehicleAnnualVolume: number | null;
250
- /** Per-year vehicle curve, same shape as {@link effectiveVolumesByYear}.
251
- * Bridged year by year onto each line. */
252
- vehicleVolumesByYear: EffectiveVolumeByYear[] | null;
253
214
  /**
254
215
  * Customer-committed PART volume on ARBITRARY periods — the general form of
255
216
  * {@link effectiveVolumesByYear}, for deals tracked at a granularity the year
@@ -341,230 +302,6 @@ export interface SetEffectivePriceInput {
341
302
  /** Which app is writing — gated to 'omsf' | 'cpq' | 'admin' server-side. */
342
303
  callerRole: 'omsf' | 'cpq' | 'admin';
343
304
  }
344
- export type QuoteAskStatus = 'open' | 'resolved' | 'cancelled';
345
- export interface QuoteAsk {
346
- id: string;
347
- tenantId: string;
348
- /** `ASK-YYYY-NNN`, minted server-side from an atomic per-(tenant, year) counter. */
349
- askNumber: string;
350
- name: string | null;
351
- customerCompanyId: string;
352
- /** Reporting only — NEVER used to decide competition. An opportunity spans
353
- * rounds; an ask is one round. */
354
- opportunityId: string | null;
355
- dueDate: string | null;
356
- status: QuoteAskStatus;
357
- /** Which quote won. A recorded fact — closing the siblings is a later phase. */
358
- resolvedByQuoteId: string | null;
359
- resolvedAt: string | null;
360
- createdBy: string;
361
- updatedBy: string;
362
- createdAt: string;
363
- updatedAt: string;
364
- }
365
- export interface QuoteAskSummary extends QuoteAsk {
366
- /** How many quotes compete in this ask. Deliberately not a value aggregate. */
367
- quoteCount: number;
368
- }
369
- /**
370
- * A RANGE across the ask's quotes — deliberately not a total.
371
- *
372
- * The quotes are ALTERNATIVES: three of four lose on every multi-scenario RFQ by
373
- * construction, so adding them multiply-counts the same business.
374
- */
375
- export interface QuoteAskRange {
376
- quoteCount: number;
377
- minValue: number | null;
378
- maxValue: number | null;
379
- minBlendedMarginPct: number | null;
380
- maxBlendedMarginPct: number | null;
381
- }
382
- export interface QuoteAskCompetingQuote {
383
- id: string;
384
- quoteNumber: string;
385
- name: string | null;
386
- status: QuoteStatus;
387
- lines: QuoteLine[];
388
- rollUp: QuoteLineRollUp;
389
- }
390
- export interface QuoteAskDetail extends QuoteAsk {
391
- quotes: QuoteAskCompetingQuote[];
392
- range: QuoteAskRange;
393
- }
394
- export interface CreateQuoteAskInput {
395
- customerCompanyId: string;
396
- name?: string | null;
397
- opportunityId?: string | null;
398
- dueDate?: string | null;
399
- }
400
- export interface UpdateQuoteAskInput {
401
- name?: string | null;
402
- dueDate?: string | null;
403
- opportunityId?: string | null;
404
- status?: QuoteAskStatus;
405
- /** Required when resolving; must be one of this ask's own quotes. */
406
- resolvedByQuoteId?: string | null;
407
- }
408
- export interface ListQuoteAsksOptions {
409
- status?: QuoteAskStatus;
410
- customerCompanyId?: string;
411
- opportunityId?: string;
412
- }
413
- /** A per-year volume point. Same shape the quote header uses. */
414
- export interface QuoteLineVolumeByYear {
415
- year: number;
416
- effectiveVolume: number;
417
- }
418
- export interface QuoteLine {
419
- id: string;
420
- tenantId: string;
421
- quoteId: string;
422
- /** Document order. Also picks the line that supplies the deprecated `Quote.partId`. */
423
- sortOrder: number;
424
- /**
425
- * The canonical master-data {@link Part}. NULL is legal — soft enforcement, so a
426
- * part number not yet reconciled into the catalog can still be quoted. Denotes
427
- * the BASE part per the part-identity ADR.
428
- */
429
- partId: string | null;
430
- /** Required, denormalised. Carries the line on its own when `partId` is null. */
431
- partNumber: string;
432
- /** Engineering revision this line is quoted AT, when known. Never identity. */
433
- revision: string | null;
434
- /**
435
- * Vehicle→part bridge, unique per line. At the defaults (100 / 1) the
436
- * header→line volume projection is the IDENTITY.
437
- */
438
- takeRate: number | null;
439
- partsPerVehicle: number | null;
440
- /** Authored. Null inherits the header through the bridge. */
441
- annualVolume: number | null;
442
- /** Authored per-year series. Authoritative over `annualVolume` when present. */
443
- effectiveVolumesByYear: QuoteLineVolumeByYear[] | null;
444
- /** Authored offered price for this line. */
445
- unitPrice: string | null;
446
- /** Free text against an unhealthy line. Writable during review. */
447
- note: string | null;
448
- /** DERIVED — published only via `quoteLines.setEffectiveCost`. */
449
- effectiveUnitCost: string | null;
450
- effectiveCostSource: string | null;
451
- effectiveCostBasis: string | null;
452
- effectiveCostedAt: string | null;
453
- effectiveCostedBy: string | null;
454
- effectiveCostBreakdown: unknown | null;
455
- /** DERIVED — published only via `quoteLines.setEffectivePrice`. */
456
- effectiveUnitPrice: string | null;
457
- effectivePriceSource: string | null;
458
- effectivePriceBasis: string | null;
459
- effectivePricedAt: string | null;
460
- effectivePricedBy: string | null;
461
- effectivePriceBreakdown: unknown | null;
462
- createdBy: string;
463
- updatedBy: string;
464
- createdAt: string;
465
- updatedAt: string;
466
- /** Present when the line resolves to a catalog part. */
467
- part?: {
468
- id: string;
469
- partNumber: string;
470
- name: string;
471
- partTypeId: string | null;
472
- } | null;
473
- /** Resolved figures — see {@link ResolvedQuoteLineTerms}. */
474
- terms: ResolvedQuoteLineTerms;
475
- }
476
- /**
477
- * A line's resolved terms. The `*Source` / `*FromLine` flags let a caller tell an
478
- * authored figure from an inherited one without re-deriving the precedence.
479
- */
480
- export interface ResolvedQuoteLineTerms {
481
- annualVolume: number;
482
- volumesByYear: QuoteLineVolumeByYear[] | null;
483
- unitCost: number | null;
484
- unitPrice: number | null;
485
- value: number;
486
- marginPct: number | null;
487
- /**
488
- * Which tier the volume came from: the line's own series, the line's own annual
489
- * figure, or the quote header bridged through take rate × parts per vehicle.
490
- */
491
- volumeSource: 'line_years' | 'line_annual' | 'header_bridged';
492
- costFromLine: boolean;
493
- priceFromLine: boolean;
494
- }
495
- /**
496
- * Consolidated figures for ONE quote's lines, computed on read.
497
- *
498
- * `blendedMarginPct` is value-weighted over the lines whose margin is KNOWN, not
499
- * over the whole quote value — a blend diluted by parts with no cost yet is a
500
- * worse number that is equally false. `linesWithoutMargin` reports that gap.
501
- */
502
- export interface QuoteLineRollUp {
503
- lineCount: number;
504
- totalAnnualVolume: number;
505
- totalValue: number;
506
- blendedMarginPct: number | null;
507
- linesWithoutMargin: number;
508
- /** Lines whose part number isn't reconciled into the catalog yet. */
509
- linesWithoutCatalogPart: number;
510
- }
511
- export interface QuoteLinesResponse {
512
- quoteId: string;
513
- quoteNumber: string;
514
- lines: QuoteLine[];
515
- rollUp: QuoteLineRollUp;
516
- }
517
- export interface QuoteLinesWithApprovalFlag extends QuoteLinesResponse {
518
- /**
519
- * True when the published figure landed on a quote already in approval — the
520
- * approver signed off on a different number. Surfaced rather than silently
521
- * absorbed; the caller decides whether to void and re-route.
522
- */
523
- invalidatesApproval: boolean;
524
- }
525
- export interface AddQuoteLineInput {
526
- partNumber: string;
527
- /** Omit to resolve from `partNumber`; pass `null` to pin it null. */
528
- partId?: string | null;
529
- revision?: string | null;
530
- /** Defaults to the end of the list, so a new line can't take over the mirror. */
531
- sortOrder?: number;
532
- /** Percentage, 0–100. Defaults to 100. */
533
- takeRate?: number;
534
- /** Defaults to 1. */
535
- partsPerVehicle?: number;
536
- annualVolume?: number | null;
537
- effectiveVolumesByYear?: QuoteLineVolumeByYear[] | null;
538
- unitPrice?: number | null;
539
- note?: string | null;
540
- }
541
- export interface UpdateQuoteLineInput {
542
- partNumber?: string;
543
- /** Omitted with a changed `partNumber` re-resolves the catalog link. */
544
- partId?: string | null;
545
- revision?: string | null;
546
- sortOrder?: number;
547
- takeRate?: number;
548
- partsPerVehicle?: number;
549
- annualVolume?: number | null;
550
- effectiveVolumesByYear?: QuoteLineVolumeByYear[] | null;
551
- unitPrice?: number | null;
552
- note?: string | null;
553
- }
554
- export interface SetQuoteLineEffectiveCostInput {
555
- unitCost: number;
556
- /** Required — what the figure was costed against. */
557
- costBasis: string;
558
- /** Declared by the adapter. Defaults to 'cpq'. */
559
- source?: string;
560
- breakdown?: unknown;
561
- }
562
- export interface SetQuoteLineEffectivePriceInput {
563
- unitPrice: number;
564
- priceBasis: string;
565
- source?: string;
566
- breakdown?: unknown;
567
- }
568
305
  export interface CreateQuoteInput {
569
306
  /**
570
307
  * MIGRATION ESCAPE HATCH — do not set this from production code.
@@ -582,10 +319,6 @@ export interface CreateQuoteInput {
582
319
  name?: string;
583
320
  customerCompanyId: string;
584
321
  programId?: string;
585
- /** Join the quote to an OEM request ({@link QuoteAsk}). Optional — a quote with
586
- * no ask competes with nothing and is awardable on its own. Validated to exist
587
- * in-tenant AND to belong to the same customer as the quote. */
588
- askId?: string | null;
589
322
  partId?: string;
590
323
  /** Historical/parent quote this one was copied from. Validated to exist
591
324
  * in-tenant on write; no DB FK. */
@@ -605,12 +338,6 @@ export interface CreateQuoteInput {
605
338
  eopPrecision?: SopEopPrecision;
606
339
  effectiveAnnualVolume?: number;
607
340
  effectiveVolumesByYear?: EffectiveVolumeByYear[];
608
- /** The VEHICLE stream every line bridges from — vehicles the program builds,
609
- * not parts sold. Each line turns it into its own part volume with its take
610
- * rate and parts-per-vehicle. Omit it and the lines fall back to the part
611
- * columns, which is what pre-2026-08-06 quotes do. (4.12.0) */
612
- vehicleAnnualVolume?: number;
613
- vehicleVolumesByYear?: EffectiveVolumeByYear[];
614
341
  /** Arbitrary-period committed volume. Non-empty makes the two fields above
615
342
  * derived — passing either alongside it is a 422. (4.8.0) */
616
343
  effectiveVolumesByPeriod?: EffectiveVolumeByPeriod[];
@@ -641,9 +368,6 @@ export interface UpdateQuoteInput {
641
368
  quoteNumber?: string;
642
369
  name?: string | null;
643
370
  programId?: string | null;
644
- /** Join the quote to an OEM request ({@link QuoteAsk}), or `null` to detach it
645
- * (it then competes with nothing). Validated to match the quote's customer. */
646
- askId?: string | null;
647
371
  partId?: string | null;
648
372
  /** Set to a quote id to record provenance, or `null` to clear it. */
649
373
  referenceQuoteId?: string | null;
@@ -661,11 +385,6 @@ export interface UpdateQuoteInput {
661
385
  eopPrecision?: SopEopPrecision | null;
662
386
  effectiveAnnualVolume?: number | null;
663
387
  effectiveVolumesByYear?: EffectiveVolumeByYear[] | null;
664
- /** The VEHICLE stream. Editing it moves EVERY line's calculated volume at
665
- * once — one program build rate, many finished goods. `null` hands the lines
666
- * back to the part columns. (4.12.0) */
667
- vehicleAnnualVolume?: number | null;
668
- vehicleVolumesByYear?: EffectiveVolumeByYear[] | null;
669
388
  /** Full replace. Non-empty makes the yearly fields derived (writing them is a
670
389
  * 422); `null` or `[]` clears the schedule and hands them back. The last
671
390
  * derived values are left in place — clearing stops maintaining them, it
@@ -2067,7 +1786,7 @@ export type SourceApp = 'master-data' | 'erfq' | 'cpq' | 'bom' | 'forecast' | 'o
2067
1786
  * "Empty" means SQL NULL only — a stored '', 0, false, or 0.0 counts as
2068
1787
  * populated and will not be overwritten by fill_empty. */
2069
1788
  export type MergePolicy = 'overwrite' | 'fill_empty';
2070
- export type ImportTargetField = 'name' | 'legalName' | 'code' | 'taxId' | 'dunsNumber' | 'website' | 'logoUrl' | 'roles' | 'email' | 'phone' | 'role' | 'type' | 'description' | 'street' | 'city' | 'stateProvince' | 'postalCode' | 'country' | 'category' | 'parent_company_ref' | 'companyCode' | 'companyName' | 'locationCode' | 'region' | 'headcount' | 'annualCapacityHours' | 'currentUtilization' | 'riskLevel' | 'numShifts' | 'hoursPerShift' | 'workingDaysPerYear' | 'indirectHeadcountPct' | 'currency' | 'effectiveDate' | 'effectiveTo' | 'libraryCode' | 'kind' | 'plantCode' | 'skillTier' | 'materialCode' | 'regionCode' | 'lane' | 'rate' | 'unit' | 'sourcingMode' | 'indexRef' | 'notes' | 'partNumber' | 'manufacturingPartNumber' | 'customerPartNumber' | 'partType' | 'manufacturer' | 'partCategoryCode' | 'quality' | 'revision' | 'uom' | 'weightPerUnit' | 'recycledPct' | 'pcfPerUnit' | 'releaseStatus' | 'leadTime' | 'customerCompanyCode' | 'customerCompanyName' | 'sopDate' | 'eopDate' | 'displayOrder' | 'label' | 'sortOrder' | 'processFamily' | 'capacityHoursPerYear' | 'cavities' | 'availabilityPct' | 'performancePct' | 'defaultHeadcount' | 'defaultAutomationPct' | 'defaultMachinesPerOperator' | 'defaultSetupCrew' | 'perUsd' | 'effectiveFrom' | 'quoteNumber' | 'programCode' | 'partId' | 'regionName' | 'annualVolume' | 'apw' | 'mpw' | 'targetPrice' | 'dueDate' | 'status' | 'key' | 'dataType' | 'options' | 'group' | 'required' | 'min' | 'max' | 'regex' | 'precision' | 'basis' | 'bindings' | 'perBaseFactor' | 'needsDensity' | 'binding' | 'allowedUoms' | 'defaultUom' | 'escalationDefault' | 'density' | 'densityUnit';
1789
+ export type ImportTargetField = 'name' | 'legalName' | 'code' | 'taxId' | 'dunsNumber' | 'website' | 'logoUrl' | 'roles' | 'email' | 'phone' | 'role' | 'type' | 'description' | 'street' | 'city' | 'stateProvince' | 'postalCode' | 'country' | 'category' | 'parent_company_ref' | 'companyCode' | 'locationCode' | 'region' | 'headcount' | 'annualCapacityHours' | 'currentUtilization' | 'riskLevel' | 'numShifts' | 'hoursPerShift' | 'workingDaysPerYear' | 'indirectHeadcountPct' | 'currency' | 'effectiveDate' | 'effectiveTo' | 'libraryCode' | 'kind' | 'plantCode' | 'skillTier' | 'materialCode' | 'regionCode' | 'lane' | 'rate' | 'unit' | 'sourcingMode' | 'indexRef' | 'notes' | 'partNumber' | 'manufacturingPartNumber' | 'customerPartNumber' | 'partType' | 'manufacturer' | 'partCategoryCode' | 'quality' | 'revision' | 'uom' | 'weightPerUnit' | 'recycledPct' | 'pcfPerUnit' | 'releaseStatus' | 'leadTime' | 'customerCompanyCode' | 'customerCompanyName' | 'sopDate' | 'eopDate' | 'displayOrder' | 'label' | 'sortOrder' | 'processFamily' | 'capacityHoursPerYear' | 'cavities' | 'availabilityPct' | 'performancePct' | 'defaultHeadcount' | 'defaultAutomationPct' | 'defaultMachinesPerOperator' | 'defaultSetupCrew' | 'perUsd' | 'effectiveFrom' | 'quoteNumber' | 'programCode' | 'partId' | 'regionName' | 'annualVolume' | 'apw' | 'mpw' | 'targetPrice' | 'dueDate' | 'key' | 'dataType' | 'options' | 'group' | 'required' | 'min' | 'max' | 'regex' | 'precision' | 'basis' | 'bindings' | 'perBaseFactor' | 'needsDensity' | 'binding' | 'allowedUoms' | 'defaultUom' | 'escalationDefault' | 'density' | 'densityUnit';
2071
1790
  export interface ImportSession {
2072
1791
  id: string;
2073
1792
  tenantId: string;
@@ -2343,20 +2062,10 @@ export interface BulkArchiveResult {
2343
2062
  errors: number;
2344
2063
  };
2345
2064
  }
2346
- /** Ownership verdict carried on an *enforced* entity's read/list response
2347
- * `meta` (Master Data Ownership Phase 4). Present only for enforced elements
2348
- * (Plant today). `readOnly` ⇒ the element is externally owned and Campfire
2349
- * edits are rejected server-side; the UI renders read-only + `editHint`. */
2350
- export interface OwnershipMeta {
2351
- readOnly: boolean;
2352
- ownerSystem: string;
2353
- editHint: string | null;
2354
- }
2355
2065
  export interface ApiMeta {
2356
2066
  requestId: string;
2357
2067
  timestamp: string;
2358
2068
  resolvedFrom?: string;
2359
- ownership?: OwnershipMeta;
2360
2069
  }
2361
2070
  export interface ListMeta extends ApiMeta {
2362
2071
  nextCursor: string | null;
@@ -2370,29 +2079,6 @@ export interface DuplicateWarning {
2370
2079
  matchName: string;
2371
2080
  score: number;
2372
2081
  }
2373
- export type OwnerType = 'campfire' | 'external';
2374
- /** One catalog element merged with its (optional) stored ownership row. The
2375
- * GET response fills catalog defaults where a tenant has no row. */
2376
- export interface MasterDataElementOwnership {
2377
- element: string;
2378
- label: string;
2379
- category: string;
2380
- ownerType: OwnerType;
2381
- /** Owning system display name; 'Campfire' when Campfire-owned. */
2382
- systemName: string;
2383
- syncMethod: string | null;
2384
- /** Opaque integrations Source id (external only) — traceability, not a FK. */
2385
- sourceRef: string | null;
2386
- updatedAt: string | null;
2387
- updatedBy: string | null;
2388
- }
2389
- export interface SetOwnershipInput {
2390
- ownerType: OwnerType;
2391
- /** Required when ownerType is 'external'. */
2392
- systemName?: string;
2393
- syncMethod?: string;
2394
- sourceRef?: string;
2395
- }
2396
2082
  export interface SingleResponse<T> {
2397
2083
  data: T;
2398
2084
  meta: ApiMeta;
@@ -2414,10 +2100,6 @@ export interface ListCompaniesOptions {
2414
2100
  status?: 'active' | 'archived' | 'all';
2415
2101
  quality?: 'draft' | 'verified';
2416
2102
  role?: 'supplier' | 'customer' | 'oem';
2417
- /** Batch-get a specific set of companies by id — returns them regardless of
2418
- * status. Comma-joined server-side; cap ~100/call for URL length and chunk
2419
- * larger sets. The server bumps the page size to cover the ids. */
2420
- ids?: string[];
2421
2103
  include?: ('contacts' | 'locations')[];
2422
2104
  }
2423
2105
  export interface GetCompanyOptions {