@measurequick/measurequick-report-generator 1.0.70 → 1.0.72

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/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as mqReportGenerator from "./jspdf/mq-report-generator.js";
2
2
  import * as mqSystemVitalsReportGenerator from "./mq-system-vitals-report-generator.js";
3
+ import * as mqSystemVitalsHeatingReportGenerator from "./mq-system-vitals-heating-report-generator.js";
3
4
  import * as mqPtcsReportGenerator from "./mq-ptcs-report-generator.js";
5
+ import * as pdfSigner from "./sign-pdf.js";
4
6
 
5
7
  export function generateReport(reportType, payload) {
6
8
  if (reportType == "mqStandard") reportType = "mqCooling";
@@ -8,7 +10,12 @@ export function generateReport(reportType, payload) {
8
10
  case "mqCooling":
9
11
  case "mqHeating": return mqReportGenerator.generateReport(reportType, payload);
10
12
  case "mqSystemVitals": return mqSystemVitalsReportGenerator.generateReport(payload);
13
+ case "mqSystemVitalsHeating": return mqSystemVitalsHeatingReportGenerator.generateReport(payload);
11
14
  case "mqPtcs": return mqPtcsReportGenerator.generateReport(payload);
12
15
  default: return false;
13
16
  }
14
17
  }
18
+
19
+ export async function addSignatureToFillableReport(fillableReportFileName, fillableFieldName, signatureBase64) {
20
+ return await pdfSigner.signPdf(fillableReportFileName, fillableFieldName, signatureBase64);
21
+ }
@@ -0,0 +1,198 @@
1
+ import { PDFDocument } from 'pdf-lib';
2
+ import * as base64 from './graphics.js';
3
+
4
+ export async function generateReport(payload) {
5
+
6
+ // fetch and load form
7
+ const formPdfBytes = _base64ToArrayBuffer(base64.systemVitalsHeatingPdfTemplate);
8
+ const pdfDoc = await PDFDocument.load(formPdfBytes);
9
+
10
+ // fetch resources
11
+ const iconRangeGreenBytes = _base64ToArrayBuffer(base64.iconRangeGreen);
12
+ const iconRangeRedBytes = _base64ToArrayBuffer(base64.iconRangeRed);
13
+ const iconFlagBlackBytes = _base64ToArrayBuffer(base64.iconFlagBlack);
14
+ const iconFlagGreenBytes = _base64ToArrayBuffer(base64.iconFlagGreen);
15
+ const iconFlagRedBytes = _base64ToArrayBuffer(base64.iconFlagRed);
16
+ const iconFlagYellowBytes = _base64ToArrayBuffer(base64.iconFlagYellow);
17
+ const iconStabilityBytes = _base64ToArrayBuffer(base64.iconStability);
18
+ const iconThumbprintGreenBytes = _base64ToArrayBuffer(base64.iconThumbprintGreen);
19
+ const iconThumbprintRedBytes = _base64ToArrayBuffer(base64.iconThumbprintRed);
20
+
21
+ // load resources
22
+ const iconRangeGreen = await pdfDoc.embedPng(iconRangeGreenBytes);
23
+ const iconRangeRed = await pdfDoc.embedPng(iconRangeRedBytes);
24
+ const iconFlagBlack = await pdfDoc.embedPng(iconFlagBlackBytes);
25
+ const iconFlagGreen = await pdfDoc.embedPng(iconFlagGreenBytes);
26
+ const iconFlagRed = await pdfDoc.embedPng(iconFlagRedBytes);
27
+ const iconFlagYellow = await pdfDoc.embedPng(iconFlagYellowBytes);
28
+ const iconStability = await pdfDoc.embedPng(iconStabilityBytes);
29
+ const iconThumbprintGreen = await pdfDoc.embedPng(iconThumbprintGreenBytes);
30
+ const iconThumbprintRed = await pdfDoc.embedPng(iconThumbprintRedBytes);
31
+
32
+ // get form for filling
33
+ const form = pdfDoc.getForm();
34
+
35
+ // print system diagnostics section
36
+ let scoreDeduction = 0;
37
+
38
+ let systemScorePercentage = +(100 - +(scoreDeduction.toFixed(0)));
39
+ let systemScoreGrade = getGradeFromScore(systemScorePercentage);
40
+ let systemScoreColor = getColorFromGrade(systemScoreGrade);
41
+
42
+ console.log("system score color is : " + systemScoreColor);
43
+
44
+ // get text fields
45
+ let textFields = getTextFields(payload);
46
+
47
+ // print customer data
48
+ let dateTimePlacement = "Upper";
49
+ let e = "";
50
+ let d = "";
51
+
52
+ let date = new Date();
53
+ if (textFields.cName && textFields.address && textFields.city && textFields.state && textFields.zip) {
54
+ dateTimePlacement = "Lower";
55
+ form.getTextField('Name').setText(`${textFields.cName}`);
56
+ form.getTextField('Address1').setText(`${textFields.address}`);
57
+ if (textFields.address2) {
58
+ form.getTextField('Address2').setText(`${textFields.address2}`);
59
+ form.getTextField('CityStateZip').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
60
+ } else form.getTextField('Address2').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
61
+ form.getTextField('DateOfServiceLabelUpper').setText("");
62
+ form.getTextField('TimeOfServiceLabelUpper').setText("");
63
+ form.getTextField('DateOfServiceLabelLower').setText("Date of Service:");
64
+ form.getTextField('TimeOfServiceLabelLower').setText("Time of Service:");
65
+ form.getTextField('DateOfServiceLower').setText(date.toLocaleDateString("en-US"));
66
+ form.getTextField('TimeOfServiceLower').setText(date.toLocaleTimeString("en-US"));
67
+ } else {
68
+ form.getTextField('DateOfServiceLabelLower').setText("");
69
+ form.getTextField('TimeOfServiceLabelLower').setText("");
70
+ form.getTextField('DateOfServiceLabelUpper').setText("Date of Service:");
71
+ form.getTextField('TimeOfServiceLabelUpper').setText("Time of Service:");
72
+ form.getTextField('DateOfServiceUpper').setText(date.toLocaleDateString("en-US"));
73
+ form.getTextField('TimeOfServiceUpper').setText(date.toLocaleTimeString("en-US"));
74
+ }
75
+
76
+ // print measurement data
77
+ form.getTextField(`YourSystemScore${systemScoreColor}`).setText(`${systemScorePercentage}% ${systemScoreGrade}`);
78
+
79
+ form.getTextField('COaf').setText(`${textFields.coaf} ppm`);
80
+ form.getTextField('Efficiency').setText(`${textFields.efficiency}`);
81
+ form.getTextField('ManifoldPressure').setText(`${textFields.manifoldPressure} inH2O`);
82
+ form.getTextField('TemperatureSplit').setText(`${textFields.tempSplit} °${payload.units.temperature}`);
83
+ form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp} inH2O`);
84
+ form.getTextField('FilterFaceVelocity').setText(`${textFields.fltrFace} FPM`);
85
+
86
+ // print targets and range icons
87
+ const measureLabels = ["ManifoldPressure", "TempSplit", "Tesp", "FilterFace"];
88
+ const targetKeys = ["pressure_manifold", "temperature_split", "pressure_static_total_external", "velocity_face_filter1"];
89
+ for (let i = 0; i < measureLabels.length; i++) {
90
+ let iconPlacement = "Mid";
91
+ let icon = iconRangeRed;
92
+ let actual = +payload.test.data[targetKeys[i]];
93
+ let mid = +payload.test.targets[targetKeys[i]];
94
+ let low = +payload.test.targets[`${targetKeys[i]}_ideal_low`];
95
+ let high = +payload.test.targets[`${targetKeys[i]}_ideal_high`];
96
+ low = mid - low;
97
+ high = mid + high;
98
+ if (targetKeys[i] == "pressure_static_total_external") high = mid * 1.4;
99
+ else if (targetKeys[i] == "velocity_face_filter1") high = 500;
100
+ if (actual < low && targetKeys[i] != "velocity_face_filter1") iconPlacement = "Low";
101
+ else if (actual > high) iconPlacement = "High";
102
+ else icon = iconRangeGreen;
103
+ form.getButton(`Image${measureLabels[i]}${iconPlacement}`).setImage(icon);
104
+ let targetZone = "";
105
+ if (targetKeys[i] == "pressure_static_total_external" || targetKeys[i] == "velocity_face_filter1") targetZone = `(< ${high})`;
106
+ else if (!isNaN(low) && low != "NaN" && !isNaN(high) && high != "NaN" ) targetZone = `(${low.toFixed(1)} - ${high.toFixed(1)})`;
107
+ form.getTextField(`${measureLabels[i]}Target`).setText(targetZone);
108
+ }
109
+
110
+ let specialCaseIcon = iconRangeRed;
111
+ let specialCasePlacement = "Mid";
112
+ if (payload.test.data.coaf < 100) {
113
+ specialCaseIcon = iconRangeGreen;
114
+ specialCasePlacement = "Low";
115
+ } else if (payload.test.data.coaf > 400) specialCasePlacement = "High";
116
+ form.getButton(`ImageCOaf${specialCasePlacement}`).setImage(specialCaseIcon);
117
+
118
+ specialCaseIcon = iconRangeRed;
119
+ specialCasePlacement = "Low";
120
+ if (payload.test.data.efficiency >= 80) specialCasePlacement = "Mid";
121
+ else if (payload.test.data.coaf >= 90) {
122
+ specialCasePlacement = "High";
123
+ specialCaseIcon = iconRangeGreen;
124
+ }
125
+ form.getButton(`ImageEfficiency${specialCasePlacement}`).setImage(specialCaseIcon);
126
+
127
+ // print pass fail measures
128
+ let passFails = ["ambient_co_pass_fail", "control_system_pass_fail", "electrical_system_pass_fail", "air_distribution_system_pass_fail", "air_filtration_system_pass_fail", "condensate_drain_system_pass_fail", "indoor_equipment_pass_fail", "venting_system_pass_fail", "fuel_delivery_system_pass_fail", "make_up_air_system_pass_fail", "heat_exchanger_pass_fail", "safety_system_pass_fail", "heating_operation_pass_fail", "combustion_safety_pass_fail", "combustion_efficiency_pass_fail"];
129
+ for (let i = 1; i <= passFails.length; i++) {
130
+ let meas = payload.test[passFails[i - 1]];
131
+ let icon = meas == "Pass" || meas == "High" || meas == "Mid" ? iconRangeGreen : iconRangeRed;
132
+ form.getButton(`ImageSubsystem${i}_af_image`).setImage(icon);
133
+ }
134
+
135
+ // flatten and return as base64
136
+ //form.flatten();
137
+ if (payload.project.isCordova) {
138
+ const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
139
+ return pdfBase64;
140
+ } else {
141
+ const pdfBytes = await pdfDoc.save();
142
+ const fn = "vitals-heating-test.pdf";
143
+ //require("downloadjs").download(pdfBytes, fn, "application/pdf");
144
+ return fn;
145
+ }
146
+ }
147
+
148
+ function getGradeFromScore(score) {
149
+ let grade = "F";
150
+ if (score == 100) return "A+";
151
+ else if (score >= 94) return "A";
152
+ else if (score >= 90) return "A-";
153
+ else if (score >= 87) return "B+";
154
+ else if (score >= 84) return "B";
155
+ else if (score >= 80) return "B-";
156
+ else if (score >= 77) return "C+";
157
+ else if (score >= 74) return "C";
158
+ else if (score >= 70) return "C-";
159
+ else if (score >= 67) return "D+";
160
+ else if (score >= 64) return "D";
161
+ else if (score >= 60) return "D-";
162
+ else return "F";
163
+ }
164
+
165
+ function getColorFromGrade(grade) {
166
+ if (grade.includes("A")) return "Green";
167
+ else if (grade.includes("B")) return "Yellow";
168
+ else if (grade.includes("C")) return "Orange";
169
+ else return "Red";
170
+ }
171
+
172
+ function getTextFields(payload) {
173
+ return {
174
+ "cName": payload.site.customer.first_name && payload.site.customer.last_name ? `${payload.site.customer.first_name} ${payload.site.customer.last_name}` : "",
175
+ "address": payload.site.location.address ? payload.site.location.address : "",
176
+ "address2": payload.site.location.address2 ? payload.site.location.address2 : "",
177
+ "city": payload.site.location.city ? payload.site.location.city : "",
178
+ "state": payload.site.location.state ? `, ${payload.site.location.state}` : "",
179
+ "zip": payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
180
+ "coaf": payload.test.data.coaf ? (+payload.test.data.coaf).toFixed(1) : "--",
181
+ "efficiency": payload.test.data.efficiency ? (+payload.test.data.efficiency).toFixed(1) : "--",
182
+ "manifoldPressure": payload.test.data.pressure_manifold ? (+payload.test.data.pressure_manifold).toFixed(1) : "--",
183
+ "tempSplit": payload.test.data.temperature_rise ? (+payload.test.data.temperature_rise).toFixed(1) : "--",
184
+ "tesp": payload.test.data.pressure_static_total_external ? (+payload.test.data.pressure_static_total_external).toFixed(2) : "--",
185
+ "fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--"
186
+ }
187
+ }
188
+
189
+ function _base64ToArrayBuffer(base64) {
190
+ base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
191
+ var binary_string = window.atob(base64);
192
+ var len = binary_string.length;
193
+ var bytes = new Uint8Array(len);
194
+ for (var i = 0; i < len; i++) {
195
+ bytes[i] = binary_string.charCodeAt(i);
196
+ }
197
+ return bytes.buffer;
198
+ }
@@ -95,7 +95,7 @@ export async function generateReport(payload) {
95
95
  form.getTextField('TimeOfServiceUpper').setText(date.toLocaleTimeString("en-US"));
96
96
  }
97
97
 
98
- // print measurement data
98
+ // print measurement data (first page)
99
99
  form.getTextField(`YourSystemScore${systemScoreColor}`).setText(`${systemScorePercentage}% ${systemScoreGrade}`);
100
100
  form.getTextField('Superheat').setText(`${textFields.superheat} °${payload.units.temperature}`);
101
101
  form.getTextField('Subcooling').setText(`${textFields.subcooling} °${payload.units.temperature}`);
@@ -104,6 +104,14 @@ export async function generateReport(payload) {
104
104
  form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp} inH2O`);
105
105
  form.getTextField('FilterFaceVelocity').setText(`${textFields.fltrFace} FPM`);
106
106
 
107
+ // print losses data (second page)
108
+ form.getTextField('AgeLosses').setText(`${textFields.ageLosses}`);
109
+ form.getTextField('TemperatureSplitLosses').setText(`${textFields.tempSplitLosses}`);
110
+ form.getTextField('StaticPressureLosses').setText(`${textFields.staticLosses}`);
111
+ form.getTextField('ApproachLosses').setText(`${textFields.approachLosses}`);
112
+ form.getTextField('RefrigerantChargeIssues').setText(`${textFields.refChargeLosses}`);
113
+ form.getTextField('YourSystemScorePage2').setText(`${systemScorePercentage}% ${systemScoreGrade}`);
114
+
107
115
  // print targets and range icons
108
116
  const measureLabels = ["Superheat", "Subcooling", "Condenser", "TempSplit", "Tesp", "FilterFace"];
109
117
  const targetKeys = ["superheat", "subcooling", "approach", "temperature_split", "pressure_static_total_external", "velocity_face_filter1"];
@@ -138,8 +146,15 @@ export async function generateReport(payload) {
138
146
 
139
147
  // flatten and return as base64
140
148
  //form.flatten();
141
- const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
142
- return pdfBase64;
149
+ if (payload.project.isCordova) {
150
+ const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
151
+ return pdfBase64;
152
+ } else {
153
+ const pdfBytes = await pdfDoc.save();
154
+ const fn = "vitals-test.pdf";
155
+ //require("downloadjs").download(pdfBytes, fn, "application/pdf");
156
+ return fn;
157
+ }
143
158
  }
144
159
 
145
160
  function getGradeFromScore(score) {
@@ -160,12 +175,10 @@ function getGradeFromScore(score) {
160
175
  }
161
176
 
162
177
  function getColorFromGrade(grade) {
163
- switch (grade.substr(0, 1)) {
164
- case "A": return "Green";
165
- case "B": return "Yellow";
166
- case "C": return "Orange";
167
- default: return "Red";
168
- }
178
+ if (grade.includes("A")) return "Green";
179
+ else if (grade.includes("B")) return "Yellow";
180
+ else if (grade.includes("C")) return "Orange";
181
+ else return "Red";
169
182
  }
170
183
 
171
184
  function getTextFields(payload) {
@@ -181,7 +194,12 @@ function getTextFields(payload) {
181
194
  "approach": payload.test.data.approach ? (+payload.test.data.approach).toFixed(1) : "--",
182
195
  "tempSplit": payload.test.data.temperature_split ? (+payload.test.data.temperature_split).toFixed(1) : "--",
183
196
  "tesp": payload.test.data.pressure_static_total_external ? (+payload.test.data.pressure_static_total_external).toFixed(2) : "--",
184
- "fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--"
197
+ "fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--",
198
+ "ageLosses": payload.test.data.age_loss ? (+payload.test.data.age_loss).toFixed(0) : 0,
199
+ "tempSplitLosses": payload.test.data.temp_split_loss ? (+payload.test.data.temp_split_loss).toFixed(0) : 0,
200
+ "staticLosses": payload.test.data.static_loss ? (+payload.test.data.static_loss).toFixed(0) : 0,
201
+ "approachLosses": payload.test.data.approach_loss ? (+payload.test.data.approach_loss).toFixed(0) : 0,
202
+ "refChargeLosses": payload.test.data.refrigerant_charge_loss ? (+payload.test.data.refrigerant_charge_loss).toFixed(0) : 0
185
203
  }
186
204
  }
187
205
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measurequick/measurequick-report-generator",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "description": "Generates PDF documents for various MeasureQuick applications.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/sign-pdf.js ADDED
@@ -0,0 +1,27 @@
1
+ import { PDFDocument } from 'pdf-lib';
2
+ import * as base64 from './graphics.js';
3
+
4
+ export async function signPdf(fillableReportFileName, fillableFieldName, signatureBase64) {
5
+ let fillablePdfTemplateFile = base64.icfSmecoSignaturePdfTemplate;
6
+ if (fillableReportFileName == 'bge_terms.pdf') fillablePdfTemplateFile = base64.icfBgeSignaturePdfTemplate;
7
+ const formPdfBytes = _base64ToArrayBuffer(fillablePdfTemplateFile);
8
+ const pdfDoc = await PDFDocument.load(formPdfBytes);
9
+ const signatureBytes = _base64ToArrayBuffer(signatureBase64);
10
+ const signature = await pdfDoc.embedPng(signatureBytes);
11
+ const form = pdfDoc.getForm();
12
+ form.getButton(fillableFieldName).setImage(signature);
13
+ //form.flatten();
14
+ const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
15
+ return pdfBase64;
16
+ }
17
+
18
+ function _base64ToArrayBuffer(base64) {
19
+ base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
20
+ var binary_string = window.atob(base64);
21
+ var len = binary_string.length;
22
+ var bytes = new Uint8Array(len);
23
+ for (var i = 0; i < len; i++) {
24
+ bytes[i] = binary_string.charCodeAt(i);
25
+ }
26
+ return bytes.buffer;
27
+ }