@measurequick/measurequick-report-generator 1.5.198 → 1.5.200

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measurequick/measurequick-report-generator",
3
- "version": "1.5.198",
3
+ "version": "1.5.200",
4
4
  "description": "Generates PDF documents for various measureQuick applications.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -245,21 +245,6 @@ export async function getReport(payload) {
245
245
  formPg1.getButton("HalfWidthLogo").setImage(mqLogoPg1);
246
246
  formPg2.getButton("HalfWidthLogo").setImage(mqLogoPg2);
247
247
  }
248
- if (
249
- payload.meta.profile_settings.techFirstName ||
250
- payload.meta.profile_settings.techLastName
251
- ) {
252
- formPg1
253
- .getTextField("TechName")
254
- .setText(
255
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
256
- );
257
- formPg2
258
- .getTextField("TechName")
259
- .setText(
260
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
261
- );
262
- }
263
248
  }
264
249
 
265
250
  // print company logo and profile picture
@@ -268,41 +253,11 @@ export async function getReport(payload) {
268
253
  formPg1.getButton("HalfWidthLogo").setImage(companyImagePg1);
269
254
  formPg2.getButton("ProfilePicture").setImage(profileImagePg2);
270
255
  formPg2.getButton("HalfWidthLogo").setImage(companyImagePg2);
271
- if (
272
- payload.meta.profile_settings.techFirstName ||
273
- payload.meta.profile_settings.techLastName
274
- ) {
275
- formPg1
276
- .getTextField("TechName")
277
- .setText(
278
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
279
- );
280
- formPg2
281
- .getTextField("TechName")
282
- .setText(
283
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
284
- );
285
- }
286
256
  } else if (!isNCI && profileImagePg1) {
287
257
  formPg1.getButton("ProfilePicture").setImage(profileImagePg1);
288
258
  formPg1.getButton("HalfWidthLogo").setImage(mqLogoPg1);
289
259
  formPg2.getButton("ProfilePicture").setImage(profileImagePg2);
290
260
  formPg2.getButton("HalfWidthLogo").setImage(mqLogoPg2);
291
- if (
292
- payload.meta.profile_settings.techFirstName ||
293
- payload.meta.profile_settings.techLastName
294
- ) {
295
- formPg1
296
- .getTextField("TechName")
297
- .setText(
298
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
299
- );
300
- formPg2
301
- .getTextField("TechName")
302
- .setText(
303
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
304
- );
305
- }
306
261
  } else if (!isNCI) {
307
262
  if (companyImagePg1) {
308
263
  formPg1.getButton("FullWidthLogo").setImage(companyImagePg1);
@@ -313,6 +268,13 @@ export async function getReport(payload) {
313
268
  }
314
269
  }
315
270
 
271
+ // Set tech name using helper function
272
+ const techName = util.getTechName(payload);
273
+ if (techName) {
274
+ formPg1.getTextField("TechName").setText(techName);
275
+ formPg2.getTextField("TechName").setText(techName);
276
+ }
277
+
316
278
  for (let t = 0; t < payload.tests.length; t++) {
317
279
  let section = t == 0 ? "test_in" : "test_out";
318
280
  let sectionLabel = t == 0 ? "Test In " : "Test Out ";
@@ -159,15 +159,6 @@ export async function getReport(payload, _test) {
159
159
  } else {
160
160
  form.getButton("HalfWidthLogo").setImage(mqLogo);
161
161
  }
162
- if (
163
- payload.meta.profile_settings.techFirstName ||
164
- payload.meta.profile_settings.techLastName
165
- )
166
- form
167
- .getTextField("TechName")
168
- .setText(
169
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
170
- );
171
162
  }
172
163
 
173
164
  // print company logo and profile picture
@@ -175,34 +166,22 @@ export async function getReport(payload, _test) {
175
166
  // both images are embedded in the document
176
167
  form.getButton("ProfilePicture").setImage(profileImage);
177
168
  form.getButton("HalfWidthLogo").setImage(companyImage);
178
- if (
179
- payload.meta.profile_settings.techFirstName ||
180
- payload.meta.profile_settings.techLastName
181
- )
182
- form
183
- .getTextField("TechName")
184
- .setText(
185
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
186
- );
187
169
  } else if (!isNCI && profileImage) {
188
170
  // no company logo is embedded in the document
189
171
  form.getButton("ProfilePicture").setImage(profileImage);
190
172
  form.getButton("HalfWidthLogo").setImage(mqLogo);
191
- if (
192
- payload.meta.profile_settings.techFirstName ||
193
- payload.meta.profile_settings.techLastName
194
- )
195
- form
196
- .getTextField("TechName")
197
- .setText(
198
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
199
- );
200
173
  } else if (!isNCI) {
201
174
  // no profile picture is embedded in the document
202
175
  if (companyImage) form.getButton("FullWidthLogo").setImage(companyImage);
203
176
  else form.getButton("FullWidthLogo").setImage(mqLogo);
204
177
  }
205
178
 
179
+ // Set tech name using helper function
180
+ const techName = util.getTechName(payload);
181
+ if (techName) {
182
+ form.getTextField("TechName").setText(techName);
183
+ }
184
+
206
185
  // print customer data
207
186
  let dateTimePlacement = "Upper";
208
187
  let e = "";
@@ -125,32 +125,26 @@ export async function getReport(payload, _test) {
125
125
  } else {
126
126
  form.getButton("HalfWidthLogo").setImage(mqLogo);
127
127
  }
128
- if (payload.meta.profile_settings.techFirstName || payload.meta.profile_settings.techLastName)
129
- form.getTextField("TechName").setText(
130
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
131
- );
132
128
  }
133
129
 
134
130
  // print company logo and profile picture
135
131
  if (!isNCI && profileImage && companyImage) {
136
132
  form.getButton("ProfilePicture").setImage(profileImage);
137
133
  form.getButton("HalfWidthLogo").setImage(companyImage);
138
- if (payload.meta.profile_settings.techFirstName || payload.meta.profile_settings.techLastName)
139
- form.getTextField("TechName").setText(
140
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
141
- );
142
134
  } else if (!isNCI && profileImage) {
143
135
  form.getButton("ProfilePicture").setImage(profileImage);
144
136
  form.getButton("HalfWidthLogo").setImage(mqLogo);
145
- if (payload.meta.profile_settings.techFirstName || payload.meta.profile_settings.techLastName)
146
- form.getTextField("TechName").setText(
147
- `${payload.meta.profile_settings.techFirstName} ${payload.meta.profile_settings.techLastName}`
148
- );
149
137
  } else if (!isNCI) {
150
138
  if (companyImage) form.getButton("FullWidthLogo").setImage(companyImage);
151
139
  else form.getButton("FullWidthLogo").setImage(mqLogo);
152
140
  }
153
141
 
142
+ // Set tech name using helper function
143
+ const techName = util.getTechName(payload);
144
+ if (techName) {
145
+ form.getTextField("TechName").setText(techName);
146
+ }
147
+
154
148
  // print customer data
155
149
  let date = new Date();
156
150
  if (textFields.cName && textFields.address && textFields.city && textFields.state && textFields.zip) {
@@ -229,55 +223,103 @@ export async function getReport(payload, _test) {
229
223
 
230
224
  form.getTextField("YourSystemScorePage2").setText(`${systemScorePercentage} ${systemScoreGrade}`);
231
225
 
232
- // Print targets and range icons (using appropriate values for heat pump heating)
233
- // Only show range icons for measurements that exist
234
- // Map field names to textFields values and check if they exist
235
- const measureChecks = [
236
- { label: "Superheat", value: textFields.tempRise }, // Temperature Rise
237
- { label: "Subcooling", value: textFields.approach, ref: "temperature_difference_condenser" }, // Approach
238
- { label: "Condenser", value: textFields.cop }, // COP/Efficiency
239
- { label: "TempSplit", value: textFields.oat }, // Outdoor Air Temp
240
- { label: "Tesp", value: textFields.tesp }, // Total External Static Pressure
241
- { label: "FilterFace", value: textFields.airflow } // Airflow
242
- ];
243
-
244
- for (let i = 0; i < measureChecks.length; i++) {
245
- const { label, value, ref } = measureChecks[i];
246
- // Only show range indicator if value exists (is not "--")
247
- if (value && value !== "--") {
248
- let icon = iconRangeGreen;
249
- let iconPlacement = "Mid";
250
-
251
- // Check if we have target zone data for this measurement
252
- if (ref && t.targets && t.targets[ref] !== undefined) {
253
- const target = parseFloat(t.targets[ref]);
254
- const idealLow = t.targets[`${ref}_ideal_low`] ? parseFloat(t.targets[`${ref}_ideal_low`]) : 0;
255
- const idealHigh = t.targets[`${ref}_ideal_high`] ? parseFloat(t.targets[`${ref}_ideal_high`]) : 0;
256
- const actual = parseFloat(value);
257
- const low = target - idealLow;
258
- const high = target + idealHigh;
259
-
260
- if (actual < low) {
261
- icon = iconRangeRed;
262
- iconPlacement = "Low";
263
- } else if (actual > high) {
264
- icon = iconRangeRed;
265
- iconPlacement = "High";
226
+ // Print targets and range icons for heat pump heating
227
+ // Heat pump heating target zones - some are in data, some in targets
228
+ const measureLabels = ["Superheat", "Subcooling", "Condenser", "TempSplit", "Tesp", "FilterFace"];
229
+
230
+ for (let i = 0; i < measureLabels.length; i++) {
231
+ const label = measureLabels[i];
232
+ let targetZone = "";
233
+ let icon = iconRangeGreen;
234
+ let iconPlacement = "Mid";
235
+ let value = "";
236
+ let mid, low, high;
237
+
238
+ if (label === "Superheat") {
239
+ // Temperature Rise - no specific target zone for HP heating, show measured value
240
+ value = textFields.tempRise;
241
+ // HP heating doesn't have fixed temp rise targets like gas heating
242
+ } else if (label === "Subcooling") {
243
+ // Approach - LLT minus entering dry bulb
244
+ value = textFields.approach;
245
+ // Check for approach targets in targets object
246
+ if (t.targets && t.targets.approach !== undefined) {
247
+ mid = parseFloat(t.targets.approach);
248
+ const idealLow = t.targets.approach_ideal_low !== undefined ? parseFloat(t.targets.approach_ideal_low) : 3;
249
+ const idealHigh = t.targets.approach_ideal_high !== undefined ? parseFloat(t.targets.approach_ideal_high) : 3;
250
+ low = mid - idealLow;
251
+ high = mid + idealHigh;
252
+ if (!isNaN(low) && !isNaN(high)) {
253
+ targetZone = `(${low.toFixed(1)} - ${high.toFixed(1)})`;
266
254
  }
267
255
  }
256
+ } else if (label === "Condenser") {
257
+ // COP - target is in data.hp_heating_cop_target
258
+ value = textFields.cop;
259
+ if (t.data && t.data.hp_heating_cop_target !== undefined) {
260
+ mid = parseFloat(t.data.hp_heating_cop_target);
261
+ // COP ideal range is typically ±0.3
262
+ low = mid - 0.3;
263
+ high = mid + 0.3;
264
+ if (!isNaN(low) && !isNaN(high)) {
265
+ targetZone = `(${low.toFixed(2)} - ${high.toFixed(2)})`;
266
+ }
267
+ }
268
+ } else if (label === "TempSplit") {
269
+ // Outdoor Air Temp - no target zone, just informational
270
+ value = textFields.oat;
271
+ } else if (label === "Tesp") {
272
+ // Total External Static Pressure
273
+ value = textFields.tesp;
274
+ if (t.targets && t.targets.pressure_static_total_external !== undefined) {
275
+ mid = parseFloat(t.targets.pressure_static_total_external);
276
+ high = mid * 1.4;
277
+ if (!isNaN(high)) {
278
+ targetZone = `(< ${high.toFixed(2)})`;
279
+ }
280
+ }
281
+ } else if (label === "FilterFace") {
282
+ // Airflow - no specific target zone
283
+ value = textFields.airflow;
284
+ }
268
285
 
269
- try {
270
- form.getButton(`Image${label}${iconPlacement}_af_image`).setImage(icon);
271
- } catch (e) {
272
- // Field may not exist
286
+ // Determine range indicator position if we have target values
287
+ if (value && value !== "--" && mid !== undefined) {
288
+ const actual = parseFloat(value);
289
+ if (!isNaN(actual)) {
290
+ if (label === "Tesp") {
291
+ // TESP: only check if above threshold
292
+ if (actual > high) {
293
+ icon = iconRangeRed;
294
+ iconPlacement = "High";
295
+ }
296
+ } else if (low !== undefined && high !== undefined) {
297
+ if (actual < low) {
298
+ icon = iconRangeRed;
299
+ iconPlacement = "Low";
300
+ } else if (actual > high) {
301
+ icon = iconRangeRed;
302
+ iconPlacement = "High";
303
+ }
304
+ }
273
305
  }
274
306
  }
275
- // Clear target zone text for heat pump heating (different targets apply)
307
+
308
+ // Set target zone text
276
309
  try {
277
- form.getTextField(`${label}Target`).setText("");
310
+ form.getTextField(`${label}Target`).setText(targetZone);
278
311
  } catch (e) {
279
312
  // Field may not exist
280
313
  }
314
+
315
+ // Set range indicator icon if value exists
316
+ if (value && value !== "--") {
317
+ try {
318
+ form.getButton(`Image${label}${iconPlacement}_af_image`).setImage(icon);
319
+ } catch (e) {
320
+ // Field may not exist
321
+ }
322
+ }
281
323
  }
282
324
 
283
325
  // Skip pass/fail subsystem review for heat pump heating
@@ -327,11 +369,13 @@ function getTextFields(payload, test) {
327
369
  zip: payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
328
370
  // Heat pump heating specific fields
329
371
  tempRise: tempRise,
330
- approach: test.data.temperature_difference_condenser !== undefined ? (+test.data.temperature_difference_condenser).toFixed(1) : "--",
372
+ approach: (test.data.temperature_liquid_line !== undefined && test.data.temperature_entering_dry_bulb !== undefined)
373
+ ? (test.data.temperature_liquid_line - test.data.temperature_entering_dry_bulb).toFixed(1)
374
+ : (test.data.temperature_difference_condenser !== undefined ? (+test.data.temperature_difference_condenser).toFixed(1) : "--"),
331
375
  cop: test.data.cop !== undefined ? (+test.data.cop).toFixed(2) : "--",
332
376
  oat: test.data.temperature_outdoor_dry_bulb !== undefined ? (+test.data.temperature_outdoor_dry_bulb).toFixed(1) : "--",
333
377
  tesp: test.data.pressure_static_total_external !== undefined ? (+test.data.pressure_static_total_external).toFixed(2) : "--",
334
- airflow: test.data.airflow !== undefined ? (+test.data.airflow).toFixed(0) :
378
+ airflow: (test.data.airflow !== undefined && test.data.airflow !== null && +test.data.airflow > 0) ? (+test.data.airflow).toFixed(0) :
335
379
  (test.data.airflow_estimated !== undefined ? (+test.data.airflow_estimated).toFixed(0) : "--"),
336
380
  // Heat pump heating scoring factors (points earned, not losses)
337
381
  ptsFilter: test.data.hp_heating_pts_filter !== undefined ? (+test.data.hp_heating_pts_filter).toFixed(0) : "--",
package/util.js CHANGED
@@ -1110,3 +1110,18 @@ export function getAiNotes(payload) {
1110
1110
  }
1111
1111
  return null;
1112
1112
  }
1113
+
1114
+ export function getTechName(payload) {
1115
+ // Check technician_name first (used by cover page)
1116
+ if (payload.meta && payload.meta.technician_name) {
1117
+ return payload.meta.technician_name;
1118
+ }
1119
+ // Fall back to profile_settings techFirstName/techLastName
1120
+ if (payload.meta && payload.meta.profile_settings) {
1121
+ const firstName = payload.meta.profile_settings.techFirstName || "";
1122
+ const lastName = payload.meta.profile_settings.techLastName || "";
1123
+ const fullName = `${firstName} ${lastName}`.trim();
1124
+ if (fullName) return fullName;
1125
+ }
1126
+ return null;
1127
+ }