@d19n/youfibre-odin-sdk 2.0.116 → 2.0.118

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.
@@ -107,6 +107,20 @@ export declare type KciDispatchDecision = {
107
107
  dateFrom: string;
108
108
  timeBlockFrom: string;
109
109
  supplierReferenceFrom: string;
110
+ /**
111
+ * Optional co-effect — when present, the caller must ALSO apply a
112
+ * PROPERTY_WRITE on the named entity + properties after the
113
+ * schedule-appointment dispatch succeeds. Used by REAPPOINTED /
114
+ * AMENDED rows whose dto carries a new `provideServiceOrder.committedDate`
115
+ * for the rebooked appointment — without this co-effect the Order's
116
+ * CommittedDate would stay frozen at the ORIGINAL committed date and
117
+ * downstream consumers (Supply→Active cron, customer-facing dashboards)
118
+ * make decisions on stale data.
119
+ */
120
+ propertyWrite?: {
121
+ entityKey: YfKciTargetEntity;
122
+ properties: ReadonlyArray<string>;
123
+ };
110
124
  } | {
111
125
  kind: 'PROPERTY_WRITE';
112
126
  row: KciEffectRow;
@@ -193,12 +193,22 @@ exports.KCI_EFFECT_ROWS = [
193
193
  timeBlockFrom: 'provideServiceOrder.appointmentTimeslot.classification',
194
194
  supplierReferenceFrom: 'provideServiceOrder.appointmentReservationReference',
195
195
  },
196
+ // Co-effect: REAPPOINTED's dto also carries an updated
197
+ // `provideServiceOrder.committedDate` for the rebooked appointment.
198
+ // Update Order.CommittedDate atomically with the schedule-appointment
199
+ // dispatch so downstream consumers (Supply→Active cron, dashboards)
200
+ // see the new supplier-committed date rather than the original.
201
+ propertyWrite: {
202
+ entityKey: 'OrderModule:Order',
203
+ properties: ['CommittedDate'],
204
+ },
196
205
  notes: 'Supplier-confirmed reschedule. Bundled effect: WO Pending→Scheduled + ' +
197
- 'set appointment date + stamp supplier reservation reference. Single ' +
198
- 'scheduleAppointment service call handles all three (skipSupplierBooking=true ' +
199
- 'because KCI is the commit, not a request). Target WO resolved from ' +
200
- 'dto.tenantWorkOrderReference; field-service picks the right Scheduled-stage ' +
201
- 'key per WO type.',
206
+ 'set appointment date + stamp supplier reservation reference + write the ' +
207
+ 'new Order.CommittedDate. Single scheduleAppointment service call handles ' +
208
+ 'the WO transition + appointment write (skipSupplierBooking=true because ' +
209
+ 'KCI is the commit, not a request); a follow-on PATCH on the Order writes ' +
210
+ 'CommittedDate. Target WO resolved from dto.tenantWorkOrderReference; ' +
211
+ 'field-service picks the right Scheduled-stage key per WO type.',
202
212
  },
203
213
  logAgainstOrder: true,
204
214
  },
@@ -394,26 +404,26 @@ exports.KCI_EFFECT_ROWS = [
394
404
  reasonCode: 'AMENDED',
395
405
  serviceOrderKind: 'PROVIDE',
396
406
  yfEffect: {
397
- kind: 'WO_SCHEDULE_APPOINTMENT',
398
- scheduleAppointment: {
399
- dateFrom: 'provideServiceOrder.appointmentTimeslot.timeslotStartDateTime',
400
- timeBlockFrom: 'provideServiceOrder.appointmentTimeslot.classification',
401
- supplierReferenceFrom: 'provideServiceOrder.appointmentReservationReference',
407
+ kind: 'PROPERTY_WRITE',
408
+ propertyWrite: {
409
+ entityKey: 'OrderModule:Order',
410
+ properties: ['CommittedDate'],
402
411
  },
403
- notes: 'Supplier-confirmed amendment new appointment locked in. Bundled ' +
404
- 'effect: WO Pending→Scheduled + set appointment date + stamp supplier ' +
405
- 'reservation reference. Single scheduleAppointment service call handles ' +
406
- 'all three (skipSupplierBooking=true because NET has already accepted ' +
407
- 'the amendment server-side). Target WO resolved from ' +
408
- 'dto.tenantWorkOrderReference; field-service picks the right ' +
409
- 'Scheduled-stage key per WO type. ' +
410
- 'AMENDED is the canonical "supplier has accepted an amendment with new ' +
411
- 'appointment details" signal emitted whether the amendment was ' +
412
- 'YF-tenant-driven (customer rebooks via /schedule-appointment YF ' +
413
- 'amends NET NET responds AMENDED) or NET-autonomous (rare; NET ' +
414
- 'reserves + amends server-side). Same JSONPaths as REAPPOINTED the ' +
415
- 'two rows differ only in semantics: REAPPOINTED = NET initiated, ' +
416
- 'AMENDED = amendment-accept confirmation (tenant or auto-amend path).',
412
+ notes: 'Supplier confirmation that an amendment has been accepted with a new ' +
413
+ 'appointment. In production this KCI always arrives AFTER the tenant ' +
414
+ 'has driven the amendment customer triggers YF /schedule-appointment ' +
415
+ ' YF moves its WO Pending→Scheduled locally + calls NET amendOrder ' +
416
+ ' NET responds with AMENDED. By the time AMENDED arrives at YF, the ' +
417
+ 'WO is already at Scheduled with the new appointment data populated, ' +
418
+ 'so the KCI carries no new state-change responsibility for the WO. ' +
419
+ 'Only effect: update Order.CommittedDate from ' +
420
+ 'provideServiceOrder.committedDate so the parent order tracks the ' +
421
+ 'supplier-committed date for the rebooked slot (the initial COMMITTED ' +
422
+ 'KCI set this on first commit; AMENDED overwrites with the post-amend ' +
423
+ 'commitment). Earlier in this session a WO_SCHEDULE_APPOINTMENT bridge ' +
424
+ 'was tried here but is wrong for production it would cause a ' +
425
+ 'double-amend cycle (YF amends NET → NET emits AMENDED → YF amends ' +
426
+ 'NET again).',
417
427
  },
418
428
  logAgainstOrder: true,
419
429
  specRef: 'fibrecafe-docs/pages/orderstate.md (AMENDED) + Frank 2026-05-12 spec quote',
@@ -499,13 +509,14 @@ function decideKciDispatch(dto) {
499
509
  if (!row.yfEffect.scheduleAppointment) {
500
510
  throw new Error(`bridge invariant: WO_SCHEDULE_APPOINTMENT row ${row.id} missing scheduleAppointment`);
501
511
  }
502
- return {
503
- kind: 'WO_SCHEDULE_APPOINTMENT',
504
- row,
505
- dateFrom: row.yfEffect.scheduleAppointment.dateFrom,
506
- timeBlockFrom: row.yfEffect.scheduleAppointment.timeBlockFrom,
507
- supplierReferenceFrom: row.yfEffect.scheduleAppointment.supplierReferenceFrom,
508
- };
512
+ return Object.assign({ kind: 'WO_SCHEDULE_APPOINTMENT', row, dateFrom: row.yfEffect.scheduleAppointment.dateFrom, timeBlockFrom: row.yfEffect.scheduleAppointment.timeBlockFrom, supplierReferenceFrom: row.yfEffect.scheduleAppointment.supplierReferenceFrom }, (row.yfEffect.propertyWrite
513
+ ? {
514
+ propertyWrite: {
515
+ entityKey: row.yfEffect.propertyWrite.entityKey,
516
+ properties: row.yfEffect.propertyWrite.properties,
517
+ },
518
+ }
519
+ : {}));
509
520
  case 'PROPERTY_WRITE':
510
521
  if (!row.yfEffect.propertyWrite) {
511
522
  throw new Error(`bridge invariant: PROPERTY_WRITE row ${row.id} missing propertyWrite`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d19n/youfibre-odin-sdk",
3
- "version": "2.0.116",
3
+ "version": "2.0.118",
4
4
  "description": "",
5
5
  "author": "@d19n",
6
6
  "license": "UNLICENSED",