@measurequick/measurequick-report-generator 1.0.69 → 1.0.71
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/graphics.js +6 -0
- package/index.js +9 -0
- package/mq-ptcs-report-generator.js +37 -0
- package/mq-system-vitals-heating-report-generator.js +174 -0
- package/mq-system-vitals-report-generator.js +11 -8
- package/package.json +1 -1
- package/sign-pdf.js +25 -0
package/index.js
CHANGED
|
@@ -1,5 +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";
|
|
4
|
+
import * as mqPtcsReportGenerator from "./mq-ptcs-report-generator.js";
|
|
5
|
+
import * as pdfSigner from "./sign-pdf.js";
|
|
3
6
|
|
|
4
7
|
export function generateReport(reportType, payload) {
|
|
5
8
|
if (reportType == "mqStandard") reportType = "mqCooling";
|
|
@@ -7,6 +10,12 @@ export function generateReport(reportType, payload) {
|
|
|
7
10
|
case "mqCooling":
|
|
8
11
|
case "mqHeating": return mqReportGenerator.generateReport(reportType, payload);
|
|
9
12
|
case "mqSystemVitals": return mqSystemVitalsReportGenerator.generateReport(payload);
|
|
13
|
+
case "mqSystemVitalsHeating": return mqSystemVitalsHeatingReportGenerator.generateReport(payload);
|
|
14
|
+
case "mqPtcs": return mqPtcsReportGenerator.generateReport(payload);
|
|
10
15
|
default: return false;
|
|
11
16
|
}
|
|
12
17
|
}
|
|
18
|
+
|
|
19
|
+
export async function addSignatureToFillableReport(fillableReportFileName, fillableFieldName, signatureBase64) {
|
|
20
|
+
return await pdfSigner.signPdf(fillableReportFileName, fillableFieldName, signatureBase64);
|
|
21
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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.ptcsPdfTemplate);
|
|
8
|
+
const pdfDoc = await PDFDocument.load(formPdfBytes);
|
|
9
|
+
|
|
10
|
+
// fetch resources
|
|
11
|
+
const iconRangeGreenBytes = _base64ToArrayBuffer(base64.iconRangeGreen);
|
|
12
|
+
|
|
13
|
+
// load resources
|
|
14
|
+
const iconRangeGreen = await pdfDoc.embedPng(iconRangeGreenBytes);
|
|
15
|
+
|
|
16
|
+
// get form for filling
|
|
17
|
+
const form = pdfDoc.getForm();
|
|
18
|
+
|
|
19
|
+
// fill form
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
// flatten and return as base64
|
|
23
|
+
//form.flatten();
|
|
24
|
+
const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
|
|
25
|
+
return pdfBase64;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function _base64ToArrayBuffer(base64) {
|
|
29
|
+
base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
|
|
30
|
+
var binary_string = window.atob(base64);
|
|
31
|
+
var len = binary_string.length;
|
|
32
|
+
var bytes = new Uint8Array(len);
|
|
33
|
+
for (var i = 0; i < len; i++) {
|
|
34
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
35
|
+
}
|
|
36
|
+
return bytes.buffer;
|
|
37
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
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
|
+
// get text fields
|
|
43
|
+
let textFields = getTextFields(payload);
|
|
44
|
+
|
|
45
|
+
// print customer data
|
|
46
|
+
let dateTimePlacement = "Upper";
|
|
47
|
+
let e = "";
|
|
48
|
+
let d = "";
|
|
49
|
+
|
|
50
|
+
let date = new Date();
|
|
51
|
+
if (textFields.cName && textFields.address && textFields.city && textFields.state && textFields.zip) {
|
|
52
|
+
dateTimePlacement = "Lower";
|
|
53
|
+
form.getTextField('Name').setText(`${textFields.cName}`);
|
|
54
|
+
form.getTextField('Address1').setText(`${textFields.address}`);
|
|
55
|
+
if (textFields.address2) {
|
|
56
|
+
form.getTextField('Address2').setText(`${textFields.address2}`);
|
|
57
|
+
form.getTextField('CityStateZip').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
|
|
58
|
+
} else form.getTextField('Address2').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
|
|
59
|
+
form.getTextField('DateOfServiceLabelUpper').setText("");
|
|
60
|
+
form.getTextField('TimeOfServiceLabelUpper').setText("");
|
|
61
|
+
form.getTextField('DateOfServiceLabelLower').setText("Date of Service:");
|
|
62
|
+
form.getTextField('TimeOfServiceLabelLower').setText("Time of Service:");
|
|
63
|
+
form.getTextField('DateOfServiceLower').setText(date.toLocaleDateString("en-US"));
|
|
64
|
+
form.getTextField('TimeOfServiceLower').setText(date.toLocaleTimeString("en-US"));
|
|
65
|
+
} else {
|
|
66
|
+
form.getTextField('DateOfServiceLabelLower').setText("");
|
|
67
|
+
form.getTextField('TimeOfServiceLabelLower').setText("");
|
|
68
|
+
form.getTextField('DateOfServiceLabelUpper').setText("Date of Service:");
|
|
69
|
+
form.getTextField('TimeOfServiceLabelUpper').setText("Time of Service:");
|
|
70
|
+
form.getTextField('DateOfServiceUpper').setText(date.toLocaleDateString("en-US"));
|
|
71
|
+
form.getTextField('TimeOfServiceUpper').setText(date.toLocaleTimeString("en-US"));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// print measurement data
|
|
75
|
+
form.getTextField(`YourSystemScore${systemScoreColor}`).setText(`${systemScorePercentage}% ${systemScoreGrade}`);
|
|
76
|
+
|
|
77
|
+
form.getTextField('COaf').setText(`${textFields.superheat} °${payload.units.temperature}`);
|
|
78
|
+
form.getTextField('Efficiency').setText(`${textFields.subcooling} °${payload.units.temperature}`);
|
|
79
|
+
form.getTextField('Manifold Pressure').setText(`${textFields.approach} °${payload.units.temperature}`);
|
|
80
|
+
form.getTextField('Temperature Split').setText(`${textFields.tempSplit} °${payload.units.temperature}`);
|
|
81
|
+
form.getTextField('Total External Static Pressure').setText(`${textFields.tesp} inH2O`);
|
|
82
|
+
form.getTextField('Filter Face Velocity').setText(`${textFields.fltrFace} FPM`);
|
|
83
|
+
|
|
84
|
+
// print targets and range icons
|
|
85
|
+
const measureLabels = ["Superheat", "Subcooling", "Condenser", "TempSplit", "Tesp", "FilterFace"];
|
|
86
|
+
const targetKeys = ["superheat", "subcooling", "approach", "temperature_split", "pressure_static_total_external", "velocity_face_filter1"];
|
|
87
|
+
for (let i = 0; i < measureLabels.length; i++) {
|
|
88
|
+
let iconPlacement = "Mid";
|
|
89
|
+
let icon = iconRangeRed;
|
|
90
|
+
let actual = +payload.test.data[targetKeys[i]];
|
|
91
|
+
let mid = +payload.test.targets[targetKeys[i]];
|
|
92
|
+
let low = +payload.test.targets[`${targetKeys[i]}_ideal_low`];
|
|
93
|
+
let high = +payload.test.targets[`${targetKeys[i]}_ideal_high`];
|
|
94
|
+
low = mid - low;
|
|
95
|
+
high = mid + high;
|
|
96
|
+
if (targetKeys[i] == "pressure_static_total_external") high = mid * 1.4;
|
|
97
|
+
else if (targetKeys[i] == "velocity_face_filter1") high = 500;
|
|
98
|
+
if (actual < low && targetKeys[i] != "velocity_face_filter1") iconPlacement = "Low";
|
|
99
|
+
else if (actual > high) iconPlacement = "High";
|
|
100
|
+
else icon = iconRangeGreen;
|
|
101
|
+
form.getButton(`Image${measureLabels[i]}${iconPlacement}_af_image`).setImage(icon);
|
|
102
|
+
let targetZone = "";
|
|
103
|
+
if (targetKeys[i] == "pressure_static_total_external" || targetKeys[i] == "velocity_face_filter1") targetZone = `(< ${high})`;
|
|
104
|
+
else if (!isNaN(low) && low != "NaN" && !isNaN(high) && high != "NaN" ) targetZone = `(${low.toFixed(1)} - ${high.toFixed(1)})`;
|
|
105
|
+
form.getTextField(`${measureLabels[i]}Target`).setText(targetZone);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// print pass fail measures
|
|
109
|
+
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"];
|
|
110
|
+
for (let i = 1; i <= passFails.length; i++) {
|
|
111
|
+
let meas = payload.test[passFails[i - 1]];
|
|
112
|
+
let icon = meas == "Pass" || meas == "High" || meas == "Mid" ? iconRangeGreen : iconRangeRed;
|
|
113
|
+
form.getButton(`ImageSubsystem${i}_af_image`).setImage(icon);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// flatten and return as base64
|
|
117
|
+
//form.flatten();
|
|
118
|
+
const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
|
|
119
|
+
return pdfBase64;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function getGradeFromScore(score) {
|
|
123
|
+
let grade = "F";
|
|
124
|
+
if (score == 100) return "A+";
|
|
125
|
+
else if (score >= 94) return "A";
|
|
126
|
+
else if (score >= 90) return "A-";
|
|
127
|
+
else if (score >= 87) return "B+";
|
|
128
|
+
else if (score >= 84) return "B";
|
|
129
|
+
else if (score >= 80) return "B-";
|
|
130
|
+
else if (score >= 77) return "C+";
|
|
131
|
+
else if (score >= 74) return "C";
|
|
132
|
+
else if (score >= 70) return "C-";
|
|
133
|
+
else if (score >= 67) return "D+";
|
|
134
|
+
else if (score >= 64) return "D";
|
|
135
|
+
else if (score >= 60) return "D-";
|
|
136
|
+
else return "F";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getColorFromGrade(grade) {
|
|
140
|
+
switch (grade.substr(0, 1)) {
|
|
141
|
+
case "A": return "Green";
|
|
142
|
+
case "B": return "Yellow";
|
|
143
|
+
case "C": return "Orange";
|
|
144
|
+
default: return "Red";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function getTextFields(payload) {
|
|
149
|
+
return {
|
|
150
|
+
"cName": payload.site.customer.first_name && payload.site.customer.last_name ? `${payload.site.customer.first_name} ${payload.site.customer.last_name}` : "",
|
|
151
|
+
"address": payload.site.location.address ? payload.site.location.address : "",
|
|
152
|
+
"address2": payload.site.location.address2 ? payload.site.location.address2 : "",
|
|
153
|
+
"city": payload.site.location.city ? payload.site.location.city : "",
|
|
154
|
+
"state": payload.site.location.state ? `, ${payload.site.location.state}` : "",
|
|
155
|
+
"zip": payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
|
|
156
|
+
"superheat": payload.test.data.superheat ? (+payload.test.data.superheat).toFixed(1) : "--",
|
|
157
|
+
"subcooling": payload.test.data.subcooling ? (+payload.test.data.subcooling).toFixed(1) : "--",
|
|
158
|
+
"approach": payload.test.data.approach ? (+payload.test.data.approach).toFixed(1) : "--",
|
|
159
|
+
"tempSplit": payload.test.data.temperature_split ? (+payload.test.data.temperature_split).toFixed(1) : "--",
|
|
160
|
+
"tesp": payload.test.data.pressure_static_total_external ? (+payload.test.data.pressure_static_total_external).toFixed(2) : "--",
|
|
161
|
+
"fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function _base64ToArrayBuffer(base64) {
|
|
166
|
+
base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
|
|
167
|
+
var binary_string = window.atob(base64);
|
|
168
|
+
var len = binary_string.length;
|
|
169
|
+
var bytes = new Uint8Array(len);
|
|
170
|
+
for (var i = 0; i < len; i++) {
|
|
171
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
172
|
+
}
|
|
173
|
+
return bytes.buffer;
|
|
174
|
+
}
|
|
@@ -55,8 +55,11 @@ export async function generateReport(payload) {
|
|
|
55
55
|
form.getButton("ImageDiagnostics1_af_image").setImage(iconFlagGreen);
|
|
56
56
|
form.getTextField("SystemDiagnostics1").setText("No system-wide issues were detected.");
|
|
57
57
|
}
|
|
58
|
+
if (payload.test.score_deduction) {
|
|
59
|
+
scoreDeduction = payload.test.score_deduction;
|
|
60
|
+
}
|
|
58
61
|
|
|
59
|
-
let systemScorePercentage = 100 - scoreDeduction;
|
|
62
|
+
let systemScorePercentage = +(100 - +(scoreDeduction.toFixed(0)));
|
|
60
63
|
let systemScoreGrade = getGradeFromScore(systemScorePercentage);
|
|
61
64
|
let systemScoreColor = getColorFromGrade(systemScoreGrade);
|
|
62
65
|
|
|
@@ -98,7 +101,7 @@ export async function generateReport(payload) {
|
|
|
98
101
|
form.getTextField('Subcooling').setText(`${textFields.subcooling} °${payload.units.temperature}`);
|
|
99
102
|
form.getTextField('CondenserApproach').setText(`${textFields.approach} °${payload.units.temperature}`);
|
|
100
103
|
form.getTextField('TemperatureSplit').setText(`${textFields.tempSplit} °${payload.units.temperature}`);
|
|
101
|
-
form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp}
|
|
104
|
+
form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp} inH2O`);
|
|
102
105
|
form.getTextField('FilterFaceVelocity').setText(`${textFields.fltrFace} FPM`);
|
|
103
106
|
|
|
104
107
|
// print targets and range icons
|
|
@@ -173,12 +176,12 @@ function getTextFields(payload) {
|
|
|
173
176
|
"city": payload.site.location.city ? payload.site.location.city : "",
|
|
174
177
|
"state": payload.site.location.state ? `, ${payload.site.location.state}` : "",
|
|
175
178
|
"zip": payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
|
|
176
|
-
"superheat": payload.test.data.superheat ? payload.test.data.superheat.toFixed(1) : "--",
|
|
177
|
-
"subcooling": payload.test.data.subcooling ? payload.test.data.subcooling.toFixed(1) : "--",
|
|
178
|
-
"approach": payload.test.data.approach ? payload.test.data.approach.toFixed(1) : "--",
|
|
179
|
-
"tempSplit": payload.test.data.temperature_split ? payload.test.data.temperature_split.toFixed(1) : "--",
|
|
180
|
-
"tesp": payload.test.data.pressure_static_total_external ? payload.test.data.pressure_static_total_external.toFixed(
|
|
181
|
-
"fltrFace": payload.test.data.velocity_face_filter1 ? payload.test.data.velocity_face_filter1.toFixed(1) : "--"
|
|
179
|
+
"superheat": payload.test.data.superheat ? (+payload.test.data.superheat).toFixed(1) : "--",
|
|
180
|
+
"subcooling": payload.test.data.subcooling ? (+payload.test.data.subcooling).toFixed(1) : "--",
|
|
181
|
+
"approach": payload.test.data.approach ? (+payload.test.data.approach).toFixed(1) : "--",
|
|
182
|
+
"tempSplit": payload.test.data.temperature_split ? (+payload.test.data.temperature_split).toFixed(1) : "--",
|
|
183
|
+
"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) : "--"
|
|
182
185
|
}
|
|
183
186
|
}
|
|
184
187
|
|
package/package.json
CHANGED
package/sign-pdf.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PDFDocument } from 'pdf-lib';
|
|
2
|
+
import * as base64 from './graphics.js';
|
|
3
|
+
|
|
4
|
+
export async function signPdf(fillableReportFileName, fillableFieldName, signatureBase64) {
|
|
5
|
+
const formPdfBytes = _base64ToArrayBuffer(base64.icfSmecoSignaturePdfTemplate);
|
|
6
|
+
const pdfDoc = await PDFDocument.load(formPdfBytes);
|
|
7
|
+
const signatureBytes = _base64ToArrayBuffer(signatureBase64);
|
|
8
|
+
const signature = await pdfDoc.embedPng(signatureBytes);
|
|
9
|
+
const form = pdfDoc.getForm();
|
|
10
|
+
form.getButton(fillableFieldName).setImage(signature);
|
|
11
|
+
//form.flatten();
|
|
12
|
+
const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
|
|
13
|
+
return pdfBase64;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function _base64ToArrayBuffer(base64) {
|
|
17
|
+
base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
|
|
18
|
+
var binary_string = window.atob(base64);
|
|
19
|
+
var len = binary_string.length;
|
|
20
|
+
var bytes = new Uint8Array(len);
|
|
21
|
+
for (var i = 0; i < len; i++) {
|
|
22
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
23
|
+
}
|
|
24
|
+
return bytes.buffer;
|
|
25
|
+
}
|