onroute-policy-engine 2.8.0 → 2.10.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/README.md CHANGED
@@ -301,6 +301,46 @@ npm test -- --coverage
301
301
  npm test -- validate-tros.spec.ts
302
302
  ```
303
303
 
304
+
305
+ ## Using npm link for local policy engine changes
306
+
307
+ Use this when you want this frontend example, including the permit form application flow, to pick up local `onroute-policy-engine` changes without publishing a package.
308
+
309
+ ```bash
310
+ # policy engine repo route
311
+ # note: linking only works the BUILT files! so you must run `npm run build` after pulling down any PR, making any code changes, etc, to the policy engine
312
+ npm run build
313
+ # npm run build -- --watch # optional for active library development; rebuilds dist on change
314
+ npm link
315
+
316
+ # this example app
317
+ cd src/_examples/usage/react-frontend-example
318
+ npm link onroute-policy-engine
319
+ npm run dev
320
+
321
+
322
+ # OPTIONAL - Now assume you have further changes to make to policy engine, or are switching policy engine branches, etc. To bring those changes in, you would:
323
+
324
+ # in PE repo, after changes are made
325
+ npm run build
326
+
327
+ # in application repo, after build is done
328
+ kill the npm run dev
329
+ npm run dev
330
+
331
+ # now that you've built + restarted the dev server, changes should be represented.
332
+ ```
333
+
334
+ If Chrome DevTools shows import/module resolution issues after linking, add this to `vite.config.ts`:
335
+
336
+ ```ts
337
+ export default defineConfig({
338
+ resolve: {
339
+ preserveSymlinks: true,
340
+ },
341
+ });
342
+ ```
343
+
304
344
  ## License
305
345
 
306
346
  This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
@@ -5,6 +5,7 @@ export declare enum PolicyFacts {
5
5
  DaysBetween = "daysBetween",
6
6
  DaysInPermitYear = "daysInPermitYear",
7
7
  EndOfPermitQuarter = "endOfPermitQuarter",
8
+ EndOfPermitYear = "endOfPermitYear",
8
9
  GrossVehicleCombinationWeight = "gvcw",
9
10
  PolicyCheckPassed = "policyCheckPassed",
10
11
  ValidationDate = "validationDate",
@@ -9,6 +9,7 @@ var PolicyFacts;
9
9
  PolicyFacts["DaysBetween"] = "daysBetween";
10
10
  PolicyFacts["DaysInPermitYear"] = "daysInPermitYear";
11
11
  PolicyFacts["EndOfPermitQuarter"] = "endOfPermitQuarter";
12
+ PolicyFacts["EndOfPermitYear"] = "endOfPermitYear";
12
13
  PolicyFacts["GrossVehicleCombinationWeight"] = "gvcw";
13
14
  PolicyFacts["PolicyCheckPassed"] = "policyCheckPassed";
14
15
  PolicyFacts["ValidationDate"] = "validationDate";
@@ -85,4 +85,32 @@ export declare function selectCorrectWeightDimensionHelper(policy: Policy, weigh
85
85
  * to be returned.
86
86
  * @returns VehicleRelatives for the axle at the indicated axleIndex
87
87
  */
88
- export declare function getVehicleRelatives(policy: Policy, configuration: Array<string>, axleIndex: number): VehicleRelatives;
88
+ export declare function getVehicleRelatives(policy: Policy, configuration: Array<string>, axleIndex: number, axleUnitVehicleIndexes?: Array<number>): VehicleRelatives;
89
+ /**
90
+ * Maps each axle unit to the vehicle configuration index that owns it.
91
+ *
92
+ * Every axle unit must supply vehicleIndex and the values must be valid,
93
+ * front-to-back vehicle configuration indexes. This lets the consuming
94
+ * application state axle ownership explicitly instead of relying on
95
+ * policy-engine inference.
96
+ *
97
+ * @example
98
+ * // Additional power-unit axle: CONCRET owns all three axle units explicitly.
99
+ * getAxleUnitVehicleIndexes(policy, ['CONCRET'], [
100
+ * { ...axleUnit, vehicleIndex: 0 },
101
+ * { ...axleUnit, vehicleIndex: 0 },
102
+ * { ...axleUnit, vehicleIndex: 0 },
103
+ * ]);
104
+ * // Returns [0, 0, 0]
105
+ *
106
+ * @example
107
+ * // Additional trailer axle: the trailer owns both trailer axle units explicitly.
108
+ * getAxleUnitVehicleIndexes(policy, ['TRKTRAC', 'STROPRT'], [
109
+ * { ...axleUnit, vehicleIndex: 0 },
110
+ * { ...axleUnit, vehicleIndex: 0 },
111
+ * { ...axleUnit, vehicleIndex: 1 },
112
+ * { ...axleUnit, vehicleIndex: 1 },
113
+ * ]);
114
+ * // Returns [0, 0, 1, 1]
115
+ */
116
+ export declare function getAxleUnitVehicleIndexes(policy: Policy, configuration: Array<string>, axleConfiguration: Array<AxleConfiguration>): Array<number>;
@@ -6,6 +6,7 @@ exports.getDefaultPowerUnitWeightHelper = getDefaultPowerUnitWeightHelper;
6
6
  exports.getDefaultTrailerWeightHelper = getDefaultTrailerWeightHelper;
7
7
  exports.selectCorrectWeightDimensionHelper = selectCorrectWeightDimensionHelper;
8
8
  exports.getVehicleRelatives = getVehicleRelatives;
9
+ exports.getAxleUnitVehicleIndexes = getAxleUnitVehicleIndexes;
9
10
  const enum_1 = require("onroute-policy-engine/enum");
10
11
  /**
11
12
  * Gets the maximum size dimensions for a given permit type, commodity,
@@ -263,7 +264,7 @@ function getDefaultVehicleWeightHelper(policy, subType, axles, isPowerUnit) {
263
264
  const vehicleCategory = vehicleCategories === null || vehicleCategories === void 0 ? void 0 : vehicleCategories.find((c) => c.id === vehicleDefinition.category);
264
265
  if (vehicleCategory) {
265
266
  const overridesForAxle = (_d = vehicleCategory.defaultWeightDimensions) === null || _d === void 0 ? void 0 : _d.filter((w) => w.axles === axles);
266
- if (overridesForAxle) {
267
+ if (overridesForAxle && overridesForAxle.length > 0) {
267
268
  return JSON.parse(JSON.stringify(overridesForAxle));
268
269
  }
269
270
  }
@@ -272,7 +273,7 @@ function getDefaultVehicleWeightHelper(policy, subType, axles, isPowerUnit) {
272
273
  ? (_e = policy.policyDefinition.globalWeightDefaults) === null || _e === void 0 ? void 0 : _e.powerUnits
273
274
  : (_f = policy.policyDefinition.globalWeightDefaults) === null || _f === void 0 ? void 0 : _f.trailers;
274
275
  const vehicleDefaults = globalDefaults === null || globalDefaults === void 0 ? void 0 : globalDefaults.filter((w) => w.axles === axles);
275
- if (vehicleDefaults) {
276
+ if (vehicleDefaults && vehicleDefaults.length > 0) {
276
277
  // Return a copy of the vehicle weights
277
278
  return JSON.parse(JSON.stringify(vehicleDefaults));
278
279
  }
@@ -311,23 +312,29 @@ function selectCorrectWeightDimensionHelper(policy, weightDimensions, configurat
311
312
  if (axleIndex >= axleConfiguration.length) {
312
313
  throw new Error('Invalid axle index value');
313
314
  }
314
- const realVehicleConfig = configuration.filter((v) => {
315
- const vehicleDef = policy.getVehicleDefinition(v);
316
- return !(vehicleDef === null || vehicleDef === void 0 ? void 0 : vehicleDef.ignoreForAxleCalculation);
317
- });
318
- if (realVehicleConfig.length !== axleConfiguration.length - 1) {
319
- // We expect the axle configuration array length to be one more
320
- // than the real configuration length because the power unit has two
321
- // axle units.
322
- throw new Error('Wrong number of axles configured for vehicle configuration');
315
+ const hasVehicleIndexes = axleConfiguration.some((axleUnit) => axleUnit.vehicleIndex !== undefined);
316
+ const axleUnitVehicleIndexes = hasVehicleIndexes
317
+ ? getAxleUnitVehicleIndexes(policy, configuration, axleConfiguration)
318
+ : undefined;
319
+ const powerUnitAxleUnitCount = axleUnitVehicleIndexes
320
+ ? axleUnitVehicleIndexes.filter((vehicleIndex) => vehicleIndex === 0).length
321
+ : 2;
322
+ if (!axleUnitVehicleIndexes) {
323
+ const realVehicleConfig = configuration.filter((v) => {
324
+ const vehicleDef = policy.getVehicleDefinition(v);
325
+ return !(vehicleDef === null || vehicleDef === void 0 ? void 0 : vehicleDef.ignoreForAxleCalculation);
326
+ });
327
+ if (realVehicleConfig.length !== axleConfiguration.length - 1) {
328
+ throw new Error('Wrong number of axles configured for vehicle configuration');
329
+ }
323
330
  }
324
- const relatives = getVehicleRelatives(policy, configuration, axleIndex);
331
+ const relatives = getVehicleRelatives(policy, configuration, axleIndex, axleUnitVehicleIndexes);
325
332
  for (const weightDimension of weightDimensions) {
326
333
  // Just renaming this for conciseness
327
334
  const m = weightDimension.modifier;
328
335
  if (!m) {
329
336
  // This dimension has no modifiers, so it is the default
330
- if (axleIndex <= 1) {
337
+ if (axleIndex < powerUnitAxleUnitCount) {
331
338
  const pwd = weightDimension;
332
339
  matchingDimension = {
333
340
  legal: axleIndex === 0 ? pwd.saLegal : pwd.daLegal,
@@ -436,8 +443,8 @@ function selectCorrectWeightDimensionHelper(policy, weightDimensions, configurat
436
443
  * to be returned.
437
444
  * @returns VehicleRelatives for the axle at the indicated axleIndex
438
445
  */
439
- function getVehicleRelatives(policy, configuration, axleIndex) {
440
- var _a, _b;
446
+ function getVehicleRelatives(policy, configuration, axleIndex, axleUnitVehicleIndexes) {
447
+ var _a, _b, _c;
441
448
  if (!configuration || configuration.length === 0) {
442
449
  throw new Error('Cannot get relatives with an empty configuration');
443
450
  }
@@ -452,22 +459,19 @@ function getVehicleRelatives(policy, configuration, axleIndex) {
452
459
  firstCategory: firstVehicle === null || firstVehicle === void 0 ? void 0 : firstVehicle.category,
453
460
  lastCategory: lastVehicle === null || lastVehicle === void 0 ? void 0 : lastVehicle.category,
454
461
  };
455
- if (axleIndex <= 1) {
462
+ const vehicleIndex = (_a = axleUnitVehicleIndexes === null || axleUnitVehicleIndexes === void 0 ? void 0 : axleUnitVehicleIndexes[axleIndex]) !== null && _a !== void 0 ? _a : axleIndex - 1;
463
+ if (vehicleIndex <= 0) {
456
464
  // First two axles are for the power unit which has no
457
465
  // previous type (it is first in the configuration always)
458
466
  vehicleRelatives.prevType = null;
459
467
  vehicleRelatives.prevCategory = null;
460
468
  }
461
469
  else {
462
- // Subtract 2 from the configuration index to account for
463
- // the fact that the power unit has two axles. We walk the
464
- // configuration here to jump over any pseudo vehicles like
465
- // additional axle units.
466
- const prevVehicleType = walk(policy, configuration, axleIndex - 2, -1);
470
+ const prevVehicleType = walk(policy, configuration, vehicleIndex - 1, -1);
467
471
  vehicleRelatives.prevType = prevVehicleType === null || prevVehicleType === void 0 ? void 0 : prevVehicleType.id;
468
- vehicleRelatives.prevCategory = (_a = policy.getVehicleDefinition(vehicleRelatives.prevType)) === null || _a === void 0 ? void 0 : _a.category;
472
+ vehicleRelatives.prevCategory = (_b = policy.getVehicleDefinition(vehicleRelatives.prevType)) === null || _b === void 0 ? void 0 : _b.category;
469
473
  }
470
- if (configuration.length === 1 || axleIndex === configuration.length) {
474
+ if (configuration.length === 1 || vehicleIndex >= configuration.length - 1) {
471
475
  // The axleIndex is for the last vehicle in the configuration,
472
476
  // so it has no next type.
473
477
  vehicleRelatives.nextType = null;
@@ -476,12 +480,75 @@ function getVehicleRelatives(policy, configuration, axleIndex) {
476
480
  else {
477
481
  // Walk the configuration towards the rear, to jump over any
478
482
  // pseudo vehicle in the line.
479
- const nextVehicleType = walk(policy, configuration, axleIndex, 1);
483
+ const nextVehicleType = walk(policy, configuration, vehicleIndex + 1, 1);
480
484
  vehicleRelatives.nextType = nextVehicleType === null || nextVehicleType === void 0 ? void 0 : nextVehicleType.id;
481
- vehicleRelatives.nextCategory = (_b = policy.getVehicleDefinition(vehicleRelatives.nextType)) === null || _b === void 0 ? void 0 : _b.category;
485
+ vehicleRelatives.nextCategory = (_c = policy.getVehicleDefinition(vehicleRelatives.nextType)) === null || _c === void 0 ? void 0 : _c.category;
482
486
  }
483
487
  return vehicleRelatives;
484
488
  }
489
+ /**
490
+ * Maps each axle unit to the vehicle configuration index that owns it.
491
+ *
492
+ * Every axle unit must supply vehicleIndex and the values must be valid,
493
+ * front-to-back vehicle configuration indexes. This lets the consuming
494
+ * application state axle ownership explicitly instead of relying on
495
+ * policy-engine inference.
496
+ *
497
+ * @example
498
+ * // Additional power-unit axle: CONCRET owns all three axle units explicitly.
499
+ * getAxleUnitVehicleIndexes(policy, ['CONCRET'], [
500
+ * { ...axleUnit, vehicleIndex: 0 },
501
+ * { ...axleUnit, vehicleIndex: 0 },
502
+ * { ...axleUnit, vehicleIndex: 0 },
503
+ * ]);
504
+ * // Returns [0, 0, 0]
505
+ *
506
+ * @example
507
+ * // Additional trailer axle: the trailer owns both trailer axle units explicitly.
508
+ * getAxleUnitVehicleIndexes(policy, ['TRKTRAC', 'STROPRT'], [
509
+ * { ...axleUnit, vehicleIndex: 0 },
510
+ * { ...axleUnit, vehicleIndex: 0 },
511
+ * { ...axleUnit, vehicleIndex: 1 },
512
+ * { ...axleUnit, vehicleIndex: 1 },
513
+ * ]);
514
+ * // Returns [0, 0, 1, 1]
515
+ */
516
+ function getAxleUnitVehicleIndexes(policy, configuration, axleConfiguration) {
517
+ if (!configuration || configuration.length === 0) {
518
+ throw new Error('Missing configuration');
519
+ }
520
+ if (!axleConfiguration || axleConfiguration.length === 0) {
521
+ throw new Error('Missing axle configuration');
522
+ }
523
+ const vehicleIndexCount = axleConfiguration.filter((axleUnit) => axleUnit.vehicleIndex !== undefined).length;
524
+ if (vehicleIndexCount !== axleConfiguration.length) {
525
+ throw new Error('All axle units must include vehicleIndex');
526
+ }
527
+ const axleUnitVehicleIndexes = axleConfiguration.map((axleUnit) => {
528
+ const vehicleIndex = axleUnit.vehicleIndex;
529
+ if (vehicleIndex === undefined ||
530
+ !Number.isInteger(vehicleIndex) ||
531
+ vehicleIndex < 0 ||
532
+ vehicleIndex >= configuration.length) {
533
+ throw new Error('Invalid vehicleIndex in axle configuration');
534
+ }
535
+ const vehicleDef = policy.getVehicleDefinition(configuration[vehicleIndex]);
536
+ if (vehicleDef === null || vehicleDef === void 0 ? void 0 : vehicleDef.ignoreForAxleCalculation) {
537
+ throw new Error('vehicleIndex cannot reference ignored vehicle');
538
+ }
539
+ return vehicleIndex;
540
+ });
541
+ if (axleUnitVehicleIndexes.length >= 2 &&
542
+ (axleUnitVehicleIndexes[0] !== 0 || axleUnitVehicleIndexes[1] !== 0)) {
543
+ throw new Error('First two axle units must belong to the power unit');
544
+ }
545
+ for (let i = 1; i < axleUnitVehicleIndexes.length; i++) {
546
+ if (axleUnitVehicleIndexes[i] < axleUnitVehicleIndexes[i - 1]) {
547
+ throw new Error('Axle unit vehicleIndex values must be in vehicle order');
548
+ }
549
+ }
550
+ return axleUnitVehicleIndexes;
551
+ }
485
552
  /**
486
553
  * Walks along the vehicle configuration from the start index
487
554
  * in the direction indicated by increment, which will typically
@@ -39,6 +39,17 @@ function addRuntimeFacts(engine, policy) {
39
39
  const endOfQuarter = dateFrom.endOf('quarter');
40
40
  return endOfQuarter.format(enum_1.PermitAppInfo.PermitDateFormat);
41
41
  });
42
+ /**
43
+ * Add runtime fact to get the last day of the year
44
+ * that the permit start date falls in. Returns the date
45
+ * formatted as a string in the standard permit date format.
46
+ */
47
+ engine.addFact(enum_1.PolicyFacts.EndOfPermitYear, async function (params, almanac) {
48
+ const startDate = await almanac.factValue(enum_1.PermitAppInfo.PermitData, {}, enum_1.PermitAppInfo.PermitStartDate);
49
+ const dateFrom = (0, dayjs_1.default)(startDate, enum_1.PermitAppInfo.PermitDateFormat);
50
+ const endOfYear = dateFrom.endOf('year').format(enum_1.PermitAppInfo.PermitDateFormat);
51
+ return endOfYear;
52
+ });
42
53
  /**
43
54
  * Adds a runtime fact specifying whether the vehicle configuration
44
55
  * in the permit application is valid for the permit type and
@@ -91,16 +91,17 @@ export declare function CheckNumTiresPerAxle(_policy: Policy, _vehicleConfigurat
91
91
  * Validates that each axle unit's weight does not exceed the permittable weight limits.
92
92
  *
93
93
  * This function performs weight validation for each axle unit in a vehicle configuration.
94
- * It retrieves the default weight dimensions for power units and trailers based on their
95
- * vehicle types and axle counts, then compares the actual axle unit weights against the
96
- * permittable weight limits. The function handles both power units (with steer and drive
97
- * axles) and trailers, ensuring compliance with weight regulations.
94
+ * It maps axle units to their owning vehicles, retrieves the default weight dimensions for
95
+ * those vehicles based on vehicle type and axle count, then compares actual axle unit
96
+ * weights against the permittable weight limits. Additional axle units require explicit
97
+ * vehicleIndex values on the axle configuration so ownership is not inferred.
98
98
  *
99
99
  * @param policy - The policy instance containing weight dimension configurations and validation rules
100
100
  * @param vehicleConfiguration - Array of vehicle type identifiers representing the vehicle configuration.
101
101
  * The first element should be a power unit type, followed by trailer types.
102
102
  * @param axleConfiguration - Array of axle configurations containing weight and axle count information.
103
- * For power units, this includes both steer and drive axle configurations.
103
+ * For power units, this includes steer, drive, and any configured additional
104
+ * axle units.
104
105
  * @returns Array of AxleUnitPolicyCheckResult objects, one for each axle unit tested.
105
106
  * Each result indicates whether the axle unit's weight is within permittable limits.
106
107
  *
@@ -121,6 +122,19 @@ export declare function CheckNumTiresPerAxle(_policy: Policy, _vehicleConfigurat
121
122
  * ]);
122
123
  * // Returns results for steer and drive axle units only
123
124
  *
125
+ * @example
126
+ * // For a configured power unit with an additional axle unit
127
+ * const results = CheckPermittableWeight(
128
+ * policy,
129
+ * ['CONCRET'],
130
+ * [
131
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 },
132
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 },
133
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 }
134
+ * ]
135
+ * );
136
+ * // Returns results for all configured power-unit axle units.
137
+ *
124
138
  * @see PolicyCheck
125
139
  * @see AxleUnitPolicyCheckResult
126
140
  * @see WeightDimension
@@ -9,6 +9,7 @@ exports.CheckMinSteerAxleWeight = CheckMinSteerAxleWeight;
9
9
  exports.CheckMinDriveAxleWeight = CheckMinDriveAxleWeight;
10
10
  exports.CheckMaxTireLoad = CheckMaxTireLoad;
11
11
  exports.CheckBoosterAxleLimit = CheckBoosterAxleLimit;
12
+ const dimensions_helper_1 = require("./dimensions.helper");
12
13
  const enum_1 = require("../enum");
13
14
  /**
14
15
  * Validates the number of axles in each axle unit.
@@ -141,15 +142,18 @@ function CheckNumTiresPerAxle(_policy, _vehicleConfiguration, axleConfiguration)
141
142
  }
142
143
  else {
143
144
  const checkResult = [numAxles * 2, numAxles * 4, numAxles * 8].includes(numTires);
144
- message = `Number of wheels for axle unit ${axleNum} is ${checkResult ? '' : 'not '}permittable.`;
145
+ message = checkResult
146
+ ? `No. of Wheels for Axle Unit ${axleNum} is permittable.`
147
+ : `No. of Wheels for Axle Unit ${axleNum} is not permittable.`;
145
148
  if (checkResult)
146
149
  result = enum_1.PolicyCheckResultType.Pass;
147
150
  }
148
151
  policyCheckResults.push({
149
152
  id: policyId,
150
- message: message,
151
- result: result,
152
- axleUnit: axleNum,
153
+ message,
154
+ result,
155
+ startAxleUnit: axleNum,
156
+ endAxleUnit: axleNum,
153
157
  });
154
158
  axleNum++;
155
159
  });
@@ -159,16 +163,17 @@ function CheckNumTiresPerAxle(_policy, _vehicleConfiguration, axleConfiguration)
159
163
  * Validates that each axle unit's weight does not exceed the permittable weight limits.
160
164
  *
161
165
  * This function performs weight validation for each axle unit in a vehicle configuration.
162
- * It retrieves the default weight dimensions for power units and trailers based on their
163
- * vehicle types and axle counts, then compares the actual axle unit weights against the
164
- * permittable weight limits. The function handles both power units (with steer and drive
165
- * axles) and trailers, ensuring compliance with weight regulations.
166
+ * It maps axle units to their owning vehicles, retrieves the default weight dimensions for
167
+ * those vehicles based on vehicle type and axle count, then compares actual axle unit
168
+ * weights against the permittable weight limits. Additional axle units require explicit
169
+ * vehicleIndex values on the axle configuration so ownership is not inferred.
166
170
  *
167
171
  * @param policy - The policy instance containing weight dimension configurations and validation rules
168
172
  * @param vehicleConfiguration - Array of vehicle type identifiers representing the vehicle configuration.
169
173
  * The first element should be a power unit type, followed by trailer types.
170
174
  * @param axleConfiguration - Array of axle configurations containing weight and axle count information.
171
- * For power units, this includes both steer and drive axle configurations.
175
+ * For power units, this includes steer, drive, and any configured additional
176
+ * axle units.
172
177
  * @returns Array of AxleUnitPolicyCheckResult objects, one for each axle unit tested.
173
178
  * Each result indicates whether the axle unit's weight is within permittable limits.
174
179
  *
@@ -189,6 +194,19 @@ function CheckNumTiresPerAxle(_policy, _vehicleConfiguration, axleConfiguration)
189
194
  * ]);
190
195
  * // Returns results for steer and drive axle units only
191
196
  *
197
+ * @example
198
+ * // For a configured power unit with an additional axle unit
199
+ * const results = CheckPermittableWeight(
200
+ * policy,
201
+ * ['CONCRET'],
202
+ * [
203
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 },
204
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 },
205
+ * { numberOfAxles: 1, axleUnitWeight: 5000, vehicleIndex: 0 }
206
+ * ]
207
+ * );
208
+ * // Returns results for all configured power-unit axle units.
209
+ *
192
210
  * @see PolicyCheck
193
211
  * @see AxleUnitPolicyCheckResult
194
212
  * @see WeightDimension
@@ -197,33 +215,60 @@ function CheckNumTiresPerAxle(_policy, _vehicleConfiguration, axleConfiguration)
197
215
  function CheckPermittableWeight(policy, vehicleConfiguration, axleConfiguration) {
198
216
  const policyCheckResults = new Array();
199
217
  const policyId = enum_1.PolicyCheckId.CheckPermittableWeight;
200
- const singleAxleDimensions = [];
201
- vehicleConfiguration.forEach((vc, i) => {
202
- let weight;
203
- if (i === 0) {
204
- // This is a power unit, concatenate the steer and drive axle numbers
205
- const powerUnitAxles = axleConfiguration[0].numberOfAxles * 10 +
206
- axleConfiguration[1].numberOfAxles;
207
- weight = policy.getDefaultPowerUnitWeight(vc, powerUnitAxles);
208
- const steerAxleDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, 0) || {};
209
- singleAxleDimensions.push(steerAxleDimension);
210
- const driveAxleDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, 1) || {};
211
- singleAxleDimensions.push(driveAxleDimension);
212
- }
213
- else {
214
- if (i + 1 < axleConfiguration.length) {
215
- // We need this guard because the last trailer in a configuration may represent
216
- // the pseudo-trailer 'None'; in this case the axleConfiguration length will
217
- // be one fewer than normal because the 'None' trailer does not get an axleConfig entry
218
+ const hasVehicleIndexes = axleConfiguration.some((axleUnit) => axleUnit.vehicleIndex !== undefined);
219
+ // Legacy John Fletcher implementation, restored from:
220
+ // git show e4a9d6badd025dec844df43379f776a4995ad75b^:src/helper/policy-check.helper.ts
221
+ if (!hasVehicleIndexes) {
222
+ const singleAxleDimensions = [];
223
+ vehicleConfiguration.forEach((vc, i) => {
224
+ let weight;
225
+ if (i === 0) {
226
+ const powerUnitAxles = axleConfiguration[0].numberOfAxles * 10 +
227
+ axleConfiguration[1].numberOfAxles;
228
+ weight = policy.getDefaultPowerUnitWeight(vc, powerUnitAxles);
229
+ const steerAxleDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, 0) || {};
230
+ singleAxleDimensions.push(steerAxleDimension);
231
+ const driveAxleDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, 1) || {};
232
+ singleAxleDimensions.push(driveAxleDimension);
233
+ }
234
+ else if (i + 1 < axleConfiguration.length) {
218
235
  weight = policy.getDefaultTrailerWeight(vc, axleConfiguration[i + 1].numberOfAxles);
219
236
  const trailerDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, i + 1) || {};
220
237
  singleAxleDimensions.push(trailerDimension);
221
238
  }
222
- }
223
- });
239
+ });
240
+ axleConfiguration.forEach((ac, i) => {
241
+ const actualWeight = ac.axleUnitWeight;
242
+ const permittableWeight = singleAxleDimensions[i].permittable || 0;
243
+ const result = actualWeight <= permittableWeight;
244
+ const axleUnit = i + 1;
245
+ const message = `Weight for axle unit ${axleUnit} ${result ? 'is permittable' : `must not exceed ${permittableWeight} kgs`}`;
246
+ policyCheckResults.push({
247
+ id: policyId,
248
+ message: message,
249
+ result: result
250
+ ? enum_1.PolicyCheckResultType.Pass
251
+ : enum_1.PolicyCheckResultType.Fail,
252
+ axleUnit: axleUnit,
253
+ actualWeight: actualWeight,
254
+ thresholdWeight: permittableWeight,
255
+ });
256
+ });
257
+ return policyCheckResults;
258
+ }
259
+ // Explicit multi-axle ownership path supplied by the consuming application.
260
+ // This is the new way, using { vehicleIndex: num }
261
+ const axleUnitVehicleIndexes = (0, dimensions_helper_1.getAxleUnitVehicleIndexes)(policy, vehicleConfiguration, axleConfiguration);
224
262
  axleConfiguration.forEach((ac, i) => {
263
+ const vehicleIndex = axleUnitVehicleIndexes[i];
264
+ const vehicleType = vehicleConfiguration[vehicleIndex];
265
+ const weight = vehicleIndex === 0
266
+ ? policy.getDefaultPowerUnitWeight(vehicleType, axleConfiguration[0].numberOfAxles * 10 +
267
+ axleConfiguration[1].numberOfAxles)
268
+ : policy.getDefaultTrailerWeight(vehicleType, ac.numberOfAxles);
269
+ const axleDimension = policy.selectCorrectWeightDimension(weight, vehicleConfiguration, axleConfiguration, i) || {};
225
270
  const actualWeight = ac.axleUnitWeight;
226
- const permittableWeight = singleAxleDimensions[i].permittable || 0;
271
+ const permittableWeight = axleDimension.permittable || 0;
227
272
  const result = actualWeight <= permittableWeight;
228
273
  const axleUnit = i + 1;
229
274
  const message = `Weight for axle unit ${axleUnit} ${result ? 'is permittable' : `must not exceed ${permittableWeight} kgs`}`;
@@ -923,7 +923,7 @@ class Policy {
923
923
  if (!commodity) {
924
924
  throw new Error(`Invalid commodity type: '${commodityId}'`);
925
925
  }
926
- const powerUnit = commodity.powerUnits.find(pu => pu.type === powerUnitSubtype);
926
+ const powerUnit = commodity.powerUnits.find((pu) => pu.type === powerUnitSubtype);
927
927
  if (!powerUnit) {
928
928
  throw new Error(`Invalid power unit: '${powerUnitSubtype}'`);
929
929
  }
@@ -955,7 +955,7 @@ class Policy {
955
955
  if (!commodity) {
956
956
  throw new Error(`Invalid commodity type: '${commodityId}'`);
957
957
  }
958
- const powerUnit = commodity.powerUnits.find(pu => pu.type === powerUnitSubtype);
958
+ const powerUnit = commodity.powerUnits.find((pu) => pu.type === powerUnitSubtype);
959
959
  if (!powerUnit) {
960
960
  throw new Error(`Invalid power unit: '${powerUnitSubtype}'`);
961
961
  }
@@ -17,6 +17,12 @@ export type AxleConfiguration = {
17
17
  numberOfTires?: number;
18
18
  /** Tire size in centimetres */
19
19
  tireSize?: number;
20
+ /**
21
+ * Index of the owning vehicle in the vehicleConfiguration array.
22
+ * Index 0 is the power unit; following indexes map to the same positions
23
+ * in vehicleConfiguration.
24
+ */
25
+ vehicleIndex?: number;
20
26
  };
21
27
  export type IndexedAxleConfiguration = AxleConfiguration & {
22
28
  /** Index of the vehicle carrying this axle unit, where 0 is the power unit */
@@ -1,25 +1,25 @@
1
- export { AxleCalcResults, PolicyCheckResult, AxleUnitPolicyCheckResult, AxleGroupPolicyCheckResult, } from './axle-calculation-results';
2
- export { AxleConfiguration, IndexedAxleConfiguration, } from './axle-configuration';
3
- export { BridgeCalculationConstants } from './bridge-calculation-constants';
4
- export { BridgeCalculationResult } from './bridge-calculation-result';
5
- export { Commodity } from './commodity';
6
- export { CostRule } from './cost-rule';
7
- export { DimensionModifier, VehicleRelatives } from './dimension-modifier';
8
- export { VehicleDisplayCodeDefaults } from './display-code-defaults';
9
- export { PermitFacts } from './facts';
10
- export { GeographicRegion } from './geographic-region';
11
- export { IdentifiedObject } from './identified-object';
12
- export { PermitMailingAddress, PermitContactDetails, PermitVehicleDetails, PermitCommodity, PermitData, PermittedCommodity, VehicleInConfiguration, VehicleConfiguration, PermittedRoute, ManualRoute, PermitApplication, } from './permit-application';
13
- export { PermitConditionDefinition, ConditionRequirement, ConditionForPermit, } from './permit-condition';
14
- export { PermitType } from './permit-type';
15
- export { PolicyDefinition } from './policy-definition';
16
- export { Matrix, RangeMatrix } from './range-matrix';
17
- export { RegionSizeOverride } from './region-size-override';
18
- export { SelfIssuable } from './self-issuable';
19
- export { SizeDimension } from './size-dimension';
20
- export { SpecialAuthorizations } from './special-authorizations';
21
- export { StandardTireSize } from './standard-tire-size';
22
- export { VehicleCategory, PowerUnitCategory, TrailerCategory, VehicleCategories, } from './vehicle-category';
23
- export { VehicleType, PowerUnitType, TrailerType, VehicleTypes, } from './vehicle-type';
24
- export { TrailerDimensions, Vehicle, VehicleDimensions } from './vehicle';
25
- export { WeightDimension, PowerUnitWeightDimension, TrailerWeightDimension, DefaultWeightDimensions, SingleAxleDimension, } from './weight-dimension';
1
+ export type { AxleCalcResults, PolicyCheckResult, AxleUnitPolicyCheckResult, AxleGroupPolicyCheckResult, } from './axle-calculation-results';
2
+ export type { AxleConfiguration, IndexedAxleConfiguration, } from './axle-configuration';
3
+ export type { BridgeCalculationConstants } from './bridge-calculation-constants';
4
+ export type { BridgeCalculationResult } from './bridge-calculation-result';
5
+ export type { Commodity } from './commodity';
6
+ export type { CostRule } from './cost-rule';
7
+ export type { DimensionModifier, VehicleRelatives } from './dimension-modifier';
8
+ export type { VehicleDisplayCodeDefaults } from './display-code-defaults';
9
+ export type { PermitFacts } from './facts';
10
+ export type { GeographicRegion } from './geographic-region';
11
+ export type { IdentifiedObject } from './identified-object';
12
+ export type { PermitMailingAddress, PermitContactDetails, PermitVehicleDetails, PermitCommodity, PermitData, PermittedCommodity, VehicleInConfiguration, VehicleConfiguration, PermittedRoute, ManualRoute, PermitApplication, } from './permit-application';
13
+ export type { PermitConditionDefinition, ConditionRequirement, ConditionForPermit, } from './permit-condition';
14
+ export type { PermitType } from './permit-type';
15
+ export type { PolicyDefinition } from './policy-definition';
16
+ export type { Matrix, RangeMatrix } from './range-matrix';
17
+ export type { RegionSizeOverride } from './region-size-override';
18
+ export type { SelfIssuable } from './self-issuable';
19
+ export type { SizeDimension } from './size-dimension';
20
+ export type { SpecialAuthorizations } from './special-authorizations';
21
+ export type { StandardTireSize } from './standard-tire-size';
22
+ export type { VehicleCategory, PowerUnitCategory, TrailerCategory, VehicleCategories, } from './vehicle-category';
23
+ export type { VehicleType, PowerUnitType, TrailerType, VehicleTypes, } from './vehicle-type';
24
+ export type { TrailerDimensions, Vehicle, VehicleDimensions } from './vehicle';
25
+ export type { WeightDimension, PowerUnitWeightDimension, TrailerWeightDimension, DefaultWeightDimensions, SingleAxleDimension, } from './weight-dimension';
@@ -73,6 +73,8 @@ export type PermitVehicleDetails = {
73
73
  licensedGVW?: number | null;
74
74
  /** Whether to save this vehicle to the inventory (optional) */
75
75
  saveVehicle?: boolean | null;
76
+ /** Vehicle description (optional) */
77
+ vehicleDescription?: string | null;
76
78
  };
77
79
  /**
78
80
  * Commodity information for the permit application
@@ -89,6 +91,15 @@ export type PermitCommodity = {
89
91
  /** Whether this commodity option is disabled */
90
92
  disabled: boolean;
91
93
  };
94
+ /**
95
+ * ICBC certificate information for the permit application
96
+ */
97
+ export type ICBCInsuranceCertificate = {
98
+ /** Whether or not an ICBC insurance certificate is to be applied to the permit */
99
+ haveCertificate: boolean;
100
+ /** Certificate number */
101
+ certificateNumber?: string | null;
102
+ };
92
103
  /**
93
104
  * Complete permit data including all application details
94
105
  */
@@ -127,6 +138,8 @@ export type PermitData = {
127
138
  thirdPartyLiability?: string | null;
128
139
  /** Conditional licensing fee information (optional) */
129
140
  conditionalLicensingFee?: string | null;
141
+ /** ICBC insurance certificate information (optional) */
142
+ icbcInsuranceCertificate?: ICBCInsuranceCertificate | null;
130
143
  };
131
144
  /**
132
145
  * Selected commodity for the permit with load description
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "v2.8.0";
1
+ export declare const version = "v2.10.0";
package/dist/version.js CHANGED
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
4
  // Generated by genversion.
5
- exports.version = 'v2.8.0';
5
+ exports.version = 'v2.10.0';
package/package.json CHANGED
@@ -91,5 +91,5 @@
91
91
  ],
92
92
  "testEnvironment": "node"
93
93
  },
94
- "version": "v2.8.0"
94
+ "version": "v2.10.0"
95
95
  }