@measurequick/measurequick-report-generator 1.0.97 → 1.0.99

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,23 +1,19 @@
1
- import * as mqReportGenerator from "./jspdf/mq-report-generator.js";
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";
6
- import * as mqStandardReportGenerator from "./mq-standard-report-generator.js";
1
+ import * as mqStandard from "./scripts/mq-standard.js";
2
+ import * as mqVitalsCooling from "./scripts/mq-vitals-cooling.js";
3
+ import * as mqVitalsHeating from "./scripts/mq-vitals-heating.js";
4
+ import * as ptcsHeatPump from "./scripts/ptcs-heat-pump.js";
5
+ import * as fillSignature from "./scripts/fill-signature.js";
7
6
 
8
7
  export function generateReport(reportType, payload) {
9
- if (reportType == "mqStandard") reportType = "mqCooling";
10
8
  switch (reportType) {
11
- case "mqCooling":
12
- case "mqHeating": return mqReportGenerator.generateReport(reportType, payload);
13
- case "mqSystemVitals": return mqSystemVitalsReportGenerator.generateReport(payload);
14
- case "mqSystemVitalsHeating": return mqSystemVitalsHeatingReportGenerator.generateReport(payload);
15
- case "PTCS": return mqPtcsReportGenerator.generateReport(payload);
16
- case "mQ Standard": return mqStandardReportGenerator.generateReport(payload);
17
- default: return false;
9
+ case "mqStandard": return mqStandard.generateReport(reportType, payload);
10
+ case "mqVitalsCooling": return mqVitalsCooling.generateReport(payload);
11
+ case "mqVitalsHeating": return mqVitalsHeating.generateReport(payload);
12
+ case "ptcsHeatPump": return ptcsHeatPump.generateReport(payload);
13
+ default: return false;
18
14
  }
19
15
  }
20
16
 
21
- export async function addSignatureToFillableReport(fillableReportFileName, fillableFieldName, signatureBase64) {
22
- return await pdfSigner.signPdf(fillableReportFileName, fillableFieldName, signatureBase64);
17
+ export async function signReport(fillableReportFileName, fillableFieldName, signatureBase64) {
18
+ return await fillSignature.signReport(fillableReportFileName, fillableFieldName, signatureBase64);
23
19
  }
@@ -2,31 +2,199 @@ import { PDFDocument } from 'pdf-lib';
2
2
  import * as base64 from './graphics.js';
3
3
 
4
4
  export async function generateReport(payload) {
5
+
6
+ // fetch and load form
5
7
  const formPdfBytes = _base64ToArrayBuffer(base64.mqStandardPdfTemplate);
6
8
  const pdfDoc = await PDFDocument.load(formPdfBytes);
7
- const photoBytes = _base64ToArrayBuffer(base64);
8
- const image = await pdfDoc.embedJpg(photoBytes);
9
+
10
+ let numCols = payload.project.numReportColumns;
11
+
12
+ // remove 2 of 3 photo pages
13
+ if (numCols !== 4) pdfDoc.removePage(13); // 4-column measurement page
14
+ if (numCols !== 2) pdfDoc.removePage(12); // 2-column measurement page
15
+ if (numCols !== 3) pdfDoc.removePage(11); // 3-column measurement page
16
+
17
+ let numPhotos = 0;
18
+
19
+ // remove 2 of 3 measurement pages
20
+ if (numPhotos >= 2) pdfDoc.removePage(8); // 2-photo page
21
+ if (numPhotos >= 4) pdfDoc.removePage(7); // 4-photo page
22
+ if (numPhotos === 0) pdfDoc.removePage(6); // 6-photo page
23
+
24
+ // fetch resources
25
+ const iconRangeGreenBytes = _base64ToArrayBuffer(base64.iconRangeGreen);
26
+ const iconRangeRedBytes = _base64ToArrayBuffer(base64.iconRangeRed);
27
+ const iconFlagBlackBytes = _base64ToArrayBuffer(base64.iconFlagBlack);
28
+ const iconFlagGreenBytes = _base64ToArrayBuffer(base64.iconFlagGreen);
29
+ const iconFlagRedBytes = _base64ToArrayBuffer(base64.iconFlagRed);
30
+ const iconFlagYellowBytes = _base64ToArrayBuffer(base64.iconFlagYellow);
31
+ const iconStabilityBytes = _base64ToArrayBuffer(base64.iconStability);
32
+ const iconThumbprintGreenBytes = _base64ToArrayBuffer(base64.iconThumbprintGreen);
33
+ const iconThumbprintRedBytes = _base64ToArrayBuffer(base64.iconThumbprintRed);
34
+
35
+ // load resources
36
+ const iconRangeGreen = await pdfDoc.embedPng(iconRangeGreenBytes);
37
+ const iconRangeRed = await pdfDoc.embedPng(iconRangeRedBytes);
38
+ const iconFlagBlack = await pdfDoc.embedPng(iconFlagBlackBytes);
39
+ const iconFlagGreen = await pdfDoc.embedPng(iconFlagGreenBytes);
40
+ const iconFlagRed = await pdfDoc.embedPng(iconFlagRedBytes);
41
+ const iconFlagYellow = await pdfDoc.embedPng(iconFlagYellowBytes);
42
+ const iconStability = await pdfDoc.embedPng(iconStabilityBytes);
43
+ const iconThumbprintGreen = await pdfDoc.embedPng(iconThumbprintGreenBytes);
44
+ const iconThumbprintRed = await pdfDoc.embedPng(iconThumbprintRedBytes);
45
+
46
+ // get form for filling
9
47
  const form = pdfDoc.getForm();
10
48
 
11
49
  // cover page
12
-
50
+ form.getTextField("Report Title").setText();
51
+ form.getTextField("Technician Name").setText();
52
+ form.getTextField("Date of Service Cover").setText();
53
+ form.getTextField("Time of Service Cover").setText();
13
54
 
14
- // vitals page
55
+ // vitals report
56
+ let scoreDeduction = 0;
57
+ if (payload.test.diagnostics.multi_point_analysis && payload.test.diagnostics.multi_point_analysis.length > 0) {
58
+ for (let i = 0; i < 9; i++) {
59
+ let d = payload.test.diagnostics.multi_point_analysis[i];
60
+ if (d) {
61
+ let diagnosticIcon = iconFlagBlack;
62
+ if (d.type === 'stability')
63
+ diagnosticIcon = iconStability;
64
+ else if (d.score > 1 && d.score < 10) {
65
+ diagnosticIcon = iconFlagRed;
66
+ scoreDeduction += d.score;
67
+ } else if (d.score >= 10 && d.score < 15)
68
+ diagnosticIcon = iconFlagYellow;
69
+ form.getButton(`ImageDiagnostics${i+1}_af_image`).setImage(diagnosticIcon);
70
+ form.getTextField(`SystemDiagnostics${i+1}`).setText(`${d.title}`);
71
+ form.getTextField(`SystemDiagnostics${i+1}a`).setText(`${d.score}`);
72
+ }
73
+ }
74
+ } else {
75
+ form.getButton("ImageDiagnostics1_af_image").setImage(iconFlagGreen);
76
+ form.getTextField("SystemDiagnostics1").setText("No system-wide issues were detected.");
77
+ }
78
+ if (payload.test.score_deduction) {
79
+ scoreDeduction = payload.test.score_deduction;
80
+ }
15
81
 
82
+ let systemScorePercentage = +(100 - +(scoreDeduction.toFixed(0)));
83
+ let systemScoreGrade = getGradeFromScore(systemScorePercentage);
84
+ let systemScoreColor = getColorFromGrade(systemScoreGrade);
16
85
 
17
- // score page
86
+ // get text fields
87
+ let textFields = getTextFields(payload);
18
88
 
89
+ // print customer data
90
+ let dateTimePlacement = "Upper";
91
+ let e = "";
92
+ let d = "";
19
93
 
20
- // equipment information page
94
+ let date = new Date();
95
+ if (textFields.cName && textFields.address && textFields.city && textFields.state && textFields.zip) {
96
+ dateTimePlacement = "Lower";
97
+ form.getTextField('Name').setText(`${textFields.cName}`);
98
+ form.getTextField('Address1').setText(`${textFields.address}`);
99
+ if (textFields.address2) {
100
+ form.getTextField('Address2').setText(`${textFields.address2}`);
101
+ form.getTextField('CityStateZip').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
102
+ } else form.getTextField('Address2').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
103
+ form.getTextField('DateOfServiceLabelUpper').setText("");
104
+ form.getTextField('TimeOfServiceLabelUpper').setText("");
105
+ form.getTextField('DateOfServiceLabelLower').setText("Date of Service:");
106
+ form.getTextField('TimeOfServiceLabelLower').setText("Time of Service:");
107
+ form.getTextField('DateOfServiceLower').setText(date.toLocaleDateString("en-US"));
108
+ form.getTextField('TimeOfServiceLower').setText(date.toLocaleTimeString("en-US"));
109
+ } else {
110
+ form.getTextField('DateOfServiceLabelLower').setText("");
111
+ form.getTextField('TimeOfServiceLabelLower').setText("");
112
+ form.getTextField('DateOfServiceLabelUpper').setText("Date of Service:");
113
+ form.getTextField('TimeOfServiceLabelUpper').setText("Time of Service:");
114
+ form.getTextField('DateOfServiceUpper').setText(date.toLocaleDateString("en-US"));
115
+ form.getTextField('TimeOfServiceUpper').setText(date.toLocaleTimeString("en-US"));
116
+ }
21
117
 
118
+ // print measurement data (first page)
119
+ form.getTextField(`YourSystemScore${systemScoreColor}`).setText(`${systemScorePercentage}% ${systemScoreGrade}`);
120
+ form.getTextField('Superheat').setText(`${textFields.superheat} °${payload.units.temperature}`);
121
+ form.getTextField('Subcooling').setText(`${textFields.subcooling} °${payload.units.temperature}`);
122
+ form.getTextField('CondenserApproach').setText(`${textFields.approach} °${payload.units.temperature}`);
123
+ form.getTextField('TemperatureSplit').setText(`${textFields.tempSplit} °${payload.units.temperature}`);
124
+ form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp} inH2O`);
125
+ form.getTextField('FilterFaceVelocity').setText(`${textFields.fltrFace} FPM`);
22
126
 
23
- // system review page
127
+ // print losses data (second page)
128
+ let lossColor = textFields.ageLosses < 3 ? "Green" : "Red";
129
+ form.getTextField(`AgeLosses${lossColor}`).setText(`- ${textFields.ageLosses}`);
130
+ lossColor = textFields.tempSplitLosses < 3 ? "Green" : "Red";
131
+ form.getTextField(`TemperatureSplitLosses${lossColor}`).setText(`- ${textFields.tempSplitLosses}`);
132
+ lossColor = textFields.staticLosses < 3 ? "Green" : "Red";
133
+ form.getTextField(`StaticPressureLosses${lossColor}`).setText(`- ${textFields.staticLosses}`);
134
+ lossColor = textFields.approachLosses < 3 ? "Green" : "Red";
135
+ form.getTextField(`ApproachLosses${lossColor}`).setText(`- ${textFields.approachLosses}`);
136
+ lossColor = textFields.refChargeLosses < 3 ? "Green" : "Red";
137
+ form.getTextField(`RefrigerantChargeIssues${lossColor}`).setText(`- ${textFields.refChargeLosses}`);
138
+ form.getTextField('YourSystemScorePage2').setText(`${systemScorePercentage}% ${systemScoreGrade}`);
24
139
 
140
+ // print targets and range icons
141
+ const measureLabels = ["Superheat", "Subcooling", "Condenser", "TempSplit", "Tesp", "FilterFace"];
142
+ const targetKeys = ["superheat", "subcooling", "approach", "temperature_split", "pressure_static_total_external", "velocity_face_filter1"];
143
+ for (let i = 0; i < measureLabels.length; i++) {
144
+ let iconPlacement = "Mid";
145
+ let icon = iconRangeRed;
146
+ let actual = +payload.test.data[targetKeys[i]];
147
+ let mid = +payload.test.targets[targetKeys[i]];
148
+ let low = +payload.test.targets[`${targetKeys[i]}_ideal_low`];
149
+ let high = +payload.test.targets[`${targetKeys[i]}_ideal_high`];
150
+ low = mid - low;
151
+ high = mid + high;
152
+ if (targetKeys[i] == "pressure_static_total_external") high = mid * 1.4;
153
+ else if (targetKeys[i] == "velocity_face_filter1") high = 500;
154
+ if (actual < low && targetKeys[i] != "velocity_face_filter1") iconPlacement = "Low";
155
+ else if (actual > high) iconPlacement = "High";
156
+ else icon = iconRangeGreen;
157
+ form.getButton(`Image${measureLabels[i]}${iconPlacement}_af_image`).setImage(icon);
158
+ let targetZone = "";
159
+ if (targetKeys[i] == "pressure_static_total_external" || targetKeys[i] == "velocity_face_filter1") targetZone = `(< ${high})`;
160
+ else if (!isNaN(low) && low != "NaN" && !isNaN(high) && high != "NaN" ) targetZone = `(${low.toFixed(1)} - ${high.toFixed(1)})`;
161
+ form.getTextField(`${measureLabels[i]}Target`).setText(targetZone);
162
+ }
25
163
 
26
- // measurement details page
164
+ // print pass fail measures
165
+ let passFails = ["electrical_system_pass_fail", "air_distribution_system_pass_fail", "air_filtration_system_pass_fail", "condensate_drain_system_pass_fail", "refrigerant_charge_pass_fail", "outdoor_equipment_pass_fail", "indoor_equipment_pass_fail", "cooling_capacity_pass_fail", "cooling_electrical_efficiency_pass_fail"];
166
+ for (let i = 1; i <= passFails.length; i++) {
167
+ let meas = payload.test[passFails[i - 1]];
168
+ let icon = meas == "Pass" || meas == "High" || meas == "Mid" ? iconRangeGreen : iconRangeRed;
169
+ form.getButton(`ImageSubsystem${i}_af_image`).setImage(icon);
170
+ }
27
171
 
172
+ // equipment information page
173
+ form.getTextField(`EI Title 1`).setText();
174
+ form.getTextField(`EI Title 2`).setText();
175
+ form.getTextField(`EI Title 3`).setText();
176
+ for (let fieldNum = 1; fieldNum <= 41; fieldNum++) {
177
+ form.getTextField(`Equip_Info-Field ${fieldNum}a`).setText();
178
+ form.getTextField(`Equip_Info-Field ${fieldNum}b`).setText();
179
+ }
180
+
181
+ // system review page
182
+ for (let catNum = 1; catNum <= 10; catNum++) {
183
+ for (let fieldNum = 1; fieldNum <= 5; fieldNum++) {
184
+ form.getTextField(`SR Title ${catNum}`).setText();
185
+ form.getTextField(`Category ${catNum} Field ${fieldNum}a`).setText();
186
+ form.getTextField(`Category ${catNum} Field ${fieldNum}b`).setText();
187
+ }
188
+ }
189
+
190
+ // measurement details page
191
+ for (let rowNum = 1; rowNum <= 35; rowNum++) {
192
+ for (let colNum = 1; colNum <= numCols; colNum++) {
193
+ form.getTextField(`MD${numCols} ${rowNum}${colNum}`).setText();
194
+ }
195
+ }
28
196
 
29
- // photos page
197
+ // photos page: take code from standard report
30
198
 
31
199
 
32
200
  form.flatten();
@@ -34,6 +202,53 @@ export async function generateReport(payload) {
34
202
  return pdfBase64;
35
203
  }
36
204
 
205
+
206
+ function getGradeFromScore(score) {
207
+ let grade = "F";
208
+ if (score == 100) return "A+";
209
+ else if (score >= 94) return "A";
210
+ else if (score >= 90) return "A-";
211
+ else if (score >= 87) return "B+";
212
+ else if (score >= 84) return "B";
213
+ else if (score >= 80) return "B-";
214
+ else if (score >= 77) return "C+";
215
+ else if (score >= 74) return "C";
216
+ else if (score >= 70) return "C-";
217
+ else if (score >= 67) return "D+";
218
+ else if (score >= 64) return "D";
219
+ else if (score >= 60) return "D-";
220
+ else return "F";
221
+ }
222
+
223
+ function getColorFromGrade(grade) {
224
+ if (grade.includes("A")) return "Green";
225
+ else if (grade.includes("B")) return "Yellow";
226
+ else if (grade.includes("C")) return "Orange";
227
+ else return "Red";
228
+ }
229
+
230
+ function getTextFields(payload) {
231
+ return {
232
+ "cName": payload.site.customer.first_name && payload.site.customer.last_name ? `${payload.site.customer.first_name} ${payload.site.customer.last_name}` : "",
233
+ "address": payload.site.location.address ? payload.site.location.address : "",
234
+ "address2": payload.site.location.address2 ? payload.site.location.address2 : "",
235
+ "city": payload.site.location.city ? payload.site.location.city : "",
236
+ "state": payload.site.location.state ? `, ${payload.site.location.state}` : "",
237
+ "zip": payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
238
+ "superheat": payload.test.data.superheat ? (+payload.test.data.superheat).toFixed(1) : "--",
239
+ "subcooling": payload.test.data.subcooling ? (+payload.test.data.subcooling).toFixed(1) : "--",
240
+ "approach": payload.test.data.approach ? (+payload.test.data.approach).toFixed(1) : "--",
241
+ "tempSplit": payload.test.data.temperature_split ? (+payload.test.data.temperature_split).toFixed(1) : "--",
242
+ "tesp": payload.test.data.pressure_static_total_external ? (+payload.test.data.pressure_static_total_external).toFixed(2) : "--",
243
+ "fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--",
244
+ "ageLosses": payload.test.data.age_loss ? (+payload.test.data.age_loss).toFixed(0) : 0,
245
+ "tempSplitLosses": payload.test.data.temp_split_loss ? (+payload.test.data.temp_split_loss).toFixed(0) : 0,
246
+ "staticLosses": payload.test.data.static_loss ? (+payload.test.data.static_loss).toFixed(0) : 0,
247
+ "approachLosses": payload.test.data.approach_loss ? (+payload.test.data.approach_loss).toFixed(0) : 0,
248
+ "refChargeLosses": payload.test.data.refrigerant_charge_loss ? (+payload.test.data.refrigerant_charge_loss).toFixed(0) : 0
249
+ }
250
+ }
251
+
37
252
  function _base64ToArrayBuffer(base64) {
38
253
  if (!base64) return "";
39
254
  base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measurequick/measurequick-report-generator",
3
- "version": "1.0.97",
3
+ "version": "1.0.99",
4
4
  "description": "Generates PDF documents for various MeasureQuick applications.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,28 @@
1
+ import { PDFDocument } from 'pdf-lib';
2
+ import * as pdf from '../templates/base-64/bge-fill-signature.js';
3
+ import * as pdf from '../templates/base-64/smeco-fill-signature.js';
4
+
5
+ export async function signReport(fillableReportFileName, fillableFieldName, signatureBase64) {
6
+ let fillablePdfTemplateFile = base64.icfSmecoSignaturePdfTemplate;
7
+ if (fillableReportFileName == 'bge_terms.pdf') fillablePdfTemplateFile = base64.icfBgeSignaturePdfTemplate;
8
+ const formPdfBytes = _base64ToArrayBuffer(fillablePdfTemplateFile);
9
+ const pdfDoc = await PDFDocument.load(formPdfBytes);
10
+ const signatureBytes = _base64ToArrayBuffer(signatureBase64);
11
+ const signature = await pdfDoc.embedPng(signatureBytes);
12
+ const form = pdfDoc.getForm();
13
+ form.getButton(fillableFieldName).setImage(signature);
14
+ form.flatten();
15
+ const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
16
+ return pdfBase64;
17
+ }
18
+
19
+ function _base64ToArrayBuffer(base64) {
20
+ base64 = base64.replace(/^[^,]+,/, '').replace(/\s/g, '');
21
+ var binary_string = window.atob(base64);
22
+ var len = binary_string.length;
23
+ var bytes = new Uint8Array(len);
24
+ for (var i = 0; i < len; i++) {
25
+ bytes[i] = binary_string.charCodeAt(i);
26
+ }
27
+ return bytes.buffer;
28
+ }
@@ -0,0 +1,274 @@
1
+ import { PDFDocument } from 'pdf-lib';
2
+ import * as base64 from '../graphics.js';
3
+ import * as pdf from '../templates/base-64/mq-standard.js';
4
+
5
+ export async function generateReport(payload) {
6
+
7
+ const pdfDoc = await PDFDocument.load(_base64ToArrayBuffer(pdf.base64));
8
+
9
+ let numCols = payload.project.numReportColumns;
10
+
11
+ // pages[1, 2, 3, 12]: Cooling Specific Pages
12
+ // pages[4, 5, 6, 13]: Heating Specific Pages
13
+ // pages[9, 10, 11]: MD 2 Columns, MD 3 Columns, MD 4 Columns
14
+ // pages[14, 15, 16]: 6 Photos, 4 Photos, 2 Photos
15
+
16
+ // remove 2 of 3 photo pages
17
+ if (numCols !== 4) pdfDoc.removePage(13); // 4-column measurement page
18
+ if (numCols !== 2) pdfDoc.removePage(12); // 2-column measurement page
19
+ if (numCols !== 3) pdfDoc.removePage(11); // 3-column measurement page
20
+
21
+ let numPhotos = 0;
22
+
23
+ // remove 2 of 3 measurement pages
24
+ if (numPhotos >= 2) pdfDoc.removePage(8); // 2-photo page
25
+ if (numPhotos >= 4) pdfDoc.removePage(7); // 4-photo page
26
+ if (numPhotos === 0) pdfDoc.removePage(6); // 6-photo page
27
+
28
+ // fetch resources
29
+ const iconRangeGreenBytes = _base64ToArrayBuffer(base64.iconRangeGreen);
30
+ const iconRangeRedBytes = _base64ToArrayBuffer(base64.iconRangeRed);
31
+ const iconFlagBlackBytes = _base64ToArrayBuffer(base64.iconFlagBlack);
32
+ const iconFlagGreenBytes = _base64ToArrayBuffer(base64.iconFlagGreen);
33
+ const iconFlagRedBytes = _base64ToArrayBuffer(base64.iconFlagRed);
34
+ const iconFlagYellowBytes = _base64ToArrayBuffer(base64.iconFlagYellow);
35
+ const iconStabilityBytes = _base64ToArrayBuffer(base64.iconStability);
36
+ const iconThumbprintGreenBytes = _base64ToArrayBuffer(base64.iconThumbprintGreen);
37
+ const iconThumbprintRedBytes = _base64ToArrayBuffer(base64.iconThumbprintRed);
38
+
39
+ // load resources
40
+ const iconRangeGreen = await pdfDoc.embedPng(iconRangeGreenBytes);
41
+ const iconRangeRed = await pdfDoc.embedPng(iconRangeRedBytes);
42
+ const iconFlagBlack = await pdfDoc.embedPng(iconFlagBlackBytes);
43
+ const iconFlagGreen = await pdfDoc.embedPng(iconFlagGreenBytes);
44
+ const iconFlagRed = await pdfDoc.embedPng(iconFlagRedBytes);
45
+ const iconFlagYellow = await pdfDoc.embedPng(iconFlagYellowBytes);
46
+ const iconStability = await pdfDoc.embedPng(iconStabilityBytes);
47
+ const iconThumbprintGreen = await pdfDoc.embedPng(iconThumbprintGreenBytes);
48
+ const iconThumbprintRed = await pdfDoc.embedPng(iconThumbprintRedBytes);
49
+
50
+ // get form for filling
51
+ const form = pdfDoc.getForm();
52
+
53
+ // cover page
54
+ form.getTextField("Report Title").setText();
55
+ form.getTextField("Technician Name").setText();
56
+ form.getTextField("Date of Service Cover").setText();
57
+ form.getTextField("Time of Service Cover").setText();
58
+
59
+ // vitals report
60
+ let scoreDeduction = 0;
61
+ if (payload.test.diagnostics.multi_point_analysis && payload.test.diagnostics.multi_point_analysis.length > 0) {
62
+ for (let i = 0; i < 9; i++) {
63
+ let d = payload.test.diagnostics.multi_point_analysis[i];
64
+ if (d) {
65
+ let diagnosticIcon = iconFlagBlack;
66
+ if (d.type === 'stability')
67
+ diagnosticIcon = iconStability;
68
+ else if (d.score > 1 && d.score < 10) {
69
+ diagnosticIcon = iconFlagRed;
70
+ scoreDeduction += d.score;
71
+ } else if (d.score >= 10 && d.score < 15)
72
+ diagnosticIcon = iconFlagYellow;
73
+ form.getButton(`ImageDiagnostics${i+1}_af_image`).setImage(diagnosticIcon);
74
+ form.getTextField(`SystemDiagnostics${i+1}`).setText(`${d.title}`);
75
+ form.getTextField(`SystemDiagnostics${i+1}a`).setText(`${d.score}`);
76
+ }
77
+ }
78
+ } else {
79
+ form.getButton("ImageDiagnostics1_af_image").setImage(iconFlagGreen);
80
+ form.getTextField("SystemDiagnostics1").setText("No system-wide issues were detected.");
81
+ }
82
+ if (payload.test.score_deduction) {
83
+ scoreDeduction = payload.test.score_deduction;
84
+ }
85
+
86
+ let systemScorePercentage = +(100 - +(scoreDeduction.toFixed(0)));
87
+ let systemScoreGrade = getGradeFromScore(systemScorePercentage);
88
+ let systemScoreColor = getColorFromGrade(systemScoreGrade);
89
+
90
+ // get text fields
91
+ let textFields = getTextFields(payload);
92
+
93
+ // print customer data
94
+ let dateTimePlacement = "Upper";
95
+ let e = "";
96
+ let d = "";
97
+
98
+ let date = new Date();
99
+ if (textFields.cName && textFields.address && textFields.city && textFields.state && textFields.zip) {
100
+ dateTimePlacement = "Lower";
101
+ form.getTextField('Name').setText(`${textFields.cName}`);
102
+ form.getTextField('Address1').setText(`${textFields.address}`);
103
+ if (textFields.address2) {
104
+ form.getTextField('Address2').setText(`${textFields.address2}`);
105
+ form.getTextField('CityStateZip').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
106
+ } else form.getTextField('Address2').setText(`${textFields.city}${textFields.state}${textFields.zip}`);
107
+ form.getTextField('DateOfServiceLabelUpper').setText("");
108
+ form.getTextField('TimeOfServiceLabelUpper').setText("");
109
+ form.getTextField('DateOfServiceLabelLower').setText("Date of Service:");
110
+ form.getTextField('TimeOfServiceLabelLower').setText("Time of Service:");
111
+ form.getTextField('DateOfServiceLower').setText(date.toLocaleDateString("en-US"));
112
+ form.getTextField('TimeOfServiceLower').setText(date.toLocaleTimeString("en-US"));
113
+ } else {
114
+ form.getTextField('DateOfServiceLabelLower').setText("");
115
+ form.getTextField('TimeOfServiceLabelLower').setText("");
116
+ form.getTextField('DateOfServiceLabelUpper').setText("Date of Service:");
117
+ form.getTextField('TimeOfServiceLabelUpper').setText("Time of Service:");
118
+ form.getTextField('DateOfServiceUpper').setText(date.toLocaleDateString("en-US"));
119
+ form.getTextField('TimeOfServiceUpper').setText(date.toLocaleTimeString("en-US"));
120
+ }
121
+
122
+ // print measurement data (first page)
123
+ form.getTextField(`YourSystemScore${systemScoreColor}`).setText(`${systemScorePercentage}% ${systemScoreGrade}`);
124
+ form.getTextField('Superheat').setText(`${textFields.superheat} °${payload.units.temperature}`);
125
+ form.getTextField('Subcooling').setText(`${textFields.subcooling} °${payload.units.temperature}`);
126
+ form.getTextField('CondenserApproach').setText(`${textFields.approach} °${payload.units.temperature}`);
127
+ form.getTextField('TemperatureSplit').setText(`${textFields.tempSplit} °${payload.units.temperature}`);
128
+ form.getTextField('TotalExternalStaticPressure').setText(`${textFields.tesp} inH2O`);
129
+ form.getTextField('FilterFaceVelocity').setText(`${textFields.fltrFace} FPM`);
130
+
131
+ // print losses data (second page)
132
+ let lossColor = textFields.ageLosses < 3 ? "Green" : "Red";
133
+ form.getTextField(`AgeLosses${lossColor}`).setText(`- ${textFields.ageLosses}`);
134
+ lossColor = textFields.tempSplitLosses < 3 ? "Green" : "Red";
135
+ form.getTextField(`TemperatureSplitLosses${lossColor}`).setText(`- ${textFields.tempSplitLosses}`);
136
+ lossColor = textFields.staticLosses < 3 ? "Green" : "Red";
137
+ form.getTextField(`StaticPressureLosses${lossColor}`).setText(`- ${textFields.staticLosses}`);
138
+ lossColor = textFields.approachLosses < 3 ? "Green" : "Red";
139
+ form.getTextField(`ApproachLosses${lossColor}`).setText(`- ${textFields.approachLosses}`);
140
+ lossColor = textFields.refChargeLosses < 3 ? "Green" : "Red";
141
+ form.getTextField(`RefrigerantChargeIssues${lossColor}`).setText(`- ${textFields.refChargeLosses}`);
142
+ form.getTextField('YourSystemScorePage2').setText(`${systemScorePercentage}% ${systemScoreGrade}`);
143
+
144
+ // print targets and range icons
145
+ const measureLabels = ["Superheat", "Subcooling", "Condenser", "TempSplit", "Tesp", "FilterFace"];
146
+ const targetKeys = ["superheat", "subcooling", "approach", "temperature_split", "pressure_static_total_external", "velocity_face_filter1"];
147
+ for (let i = 0; i < measureLabels.length; i++) {
148
+ let iconPlacement = "Mid";
149
+ let icon = iconRangeRed;
150
+ let actual = +payload.test.data[targetKeys[i]];
151
+ let mid = +payload.test.targets[targetKeys[i]];
152
+ let low = +payload.test.targets[`${targetKeys[i]}_ideal_low`];
153
+ let high = +payload.test.targets[`${targetKeys[i]}_ideal_high`];
154
+ low = mid - low;
155
+ high = mid + high;
156
+ if (targetKeys[i] == "pressure_static_total_external") high = mid * 1.4;
157
+ else if (targetKeys[i] == "velocity_face_filter1") high = 500;
158
+ if (actual < low && targetKeys[i] != "velocity_face_filter1") iconPlacement = "Low";
159
+ else if (actual > high) iconPlacement = "High";
160
+ else icon = iconRangeGreen;
161
+ form.getButton(`Image${measureLabels[i]}${iconPlacement}_af_image`).setImage(icon);
162
+ let targetZone = "";
163
+ if (targetKeys[i] == "pressure_static_total_external" || targetKeys[i] == "velocity_face_filter1") targetZone = `(< ${high})`;
164
+ else if (!isNaN(low) && low != "NaN" && !isNaN(high) && high != "NaN" ) targetZone = `(${low.toFixed(1)} - ${high.toFixed(1)})`;
165
+ form.getTextField(`${measureLabels[i]}Target`).setText(targetZone);
166
+ }
167
+
168
+ // print pass fail measures
169
+ let passFails = ["electrical_system_pass_fail", "air_distribution_system_pass_fail", "air_filtration_system_pass_fail", "condensate_drain_system_pass_fail", "refrigerant_charge_pass_fail", "outdoor_equipment_pass_fail", "indoor_equipment_pass_fail", "cooling_capacity_pass_fail", "cooling_electrical_efficiency_pass_fail"];
170
+ for (let i = 1; i <= passFails.length; i++) {
171
+ let meas = payload.test[passFails[i - 1]];
172
+ let icon = meas == "Pass" || meas == "High" || meas == "Mid" ? iconRangeGreen : iconRangeRed;
173
+ form.getButton(`ImageSubsystem${i}_af_image`).setImage(icon);
174
+ }
175
+
176
+ // equipment information page
177
+ form.getTextField(`EI Title 1`).setText();
178
+ form.getTextField(`EI Title 2`).setText();
179
+ form.getTextField(`EI Title 3`).setText();
180
+ for (let fieldNum = 1; fieldNum <= 41; fieldNum++) {
181
+ form.getTextField(`Equip_Info-Field ${fieldNum}a`).setText();
182
+ form.getTextField(`Equip_Info-Field ${fieldNum}b`).setText();
183
+ }
184
+
185
+ // system review page
186
+ for (let catNum = 1; catNum <= 10; catNum++) {
187
+ for (let fieldNum = 1; fieldNum <= 5; fieldNum++) {
188
+ form.getTextField(`SR Title ${catNum}`).setText();
189
+ form.getTextField(`Category ${catNum} Field ${fieldNum}a`).setText();
190
+ form.getTextField(`Category ${catNum} Field ${fieldNum}b`).setText();
191
+ }
192
+ }
193
+
194
+ // measurement details page
195
+ for (let rowNum = 1; rowNum <= 35; rowNum++) {
196
+ for (let colNum = 1; colNum <= numCols; colNum++) {
197
+ form.getTextField(`MD${numCols} ${rowNum}${colNum}`).setText();
198
+ }
199
+ }
200
+
201
+ // photos page: take code from standard report
202
+
203
+
204
+ form.flatten();
205
+ const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });
206
+ return pdfBase64;
207
+ }
208
+
209
+
210
+ function getGradeFromScore(score) {
211
+ let grade = "F";
212
+ if (score == 100) return "A+";
213
+ else if (score >= 94) return "A";
214
+ else if (score >= 90) return "A-";
215
+ else if (score >= 87) return "B+";
216
+ else if (score >= 84) return "B";
217
+ else if (score >= 80) return "B-";
218
+ else if (score >= 77) return "C+";
219
+ else if (score >= 74) return "C";
220
+ else if (score >= 70) return "C-";
221
+ else if (score >= 67) return "D+";
222
+ else if (score >= 64) return "D";
223
+ else if (score >= 60) return "D-";
224
+ else return "F";
225
+ }
226
+
227
+ function getColorFromGrade(grade) {
228
+ if (grade.includes("A")) return "Green";
229
+ else if (grade.includes("B")) return "Yellow";
230
+ else if (grade.includes("C")) return "Orange";
231
+ else return "Red";
232
+ }
233
+
234
+ function getTextFields(payload) {
235
+ return {
236
+ "cName": payload.site.customer.first_name && payload.site.customer.last_name ? `${payload.site.customer.first_name} ${payload.site.customer.last_name}` : "",
237
+ "address": payload.site.location.address ? payload.site.location.address : "",
238
+ "address2": payload.site.location.address2 ? payload.site.location.address2 : "",
239
+ "city": payload.site.location.city ? payload.site.location.city : "",
240
+ "state": payload.site.location.state ? `, ${payload.site.location.state}` : "",
241
+ "zip": payload.site.location.zip ? ` ${payload.site.location.zip}` : "",
242
+ "superheat": payload.test.data.superheat ? (+payload.test.data.superheat).toFixed(1) : "--",
243
+ "subcooling": payload.test.data.subcooling ? (+payload.test.data.subcooling).toFixed(1) : "--",
244
+ "approach": payload.test.data.approach ? (+payload.test.data.approach).toFixed(1) : "--",
245
+ "tempSplit": payload.test.data.temperature_split ? (+payload.test.data.temperature_split).toFixed(1) : "--",
246
+ "tesp": payload.test.data.pressure_static_total_external ? (+payload.test.data.pressure_static_total_external).toFixed(2) : "--",
247
+ "fltrFace": payload.test.data.velocity_face_filter1 ? (+payload.test.data.velocity_face_filter1).toFixed(1) : "--",
248
+ "ageLosses": payload.test.data.age_loss ? (+payload.test.data.age_loss).toFixed(0) : 0,
249
+ "tempSplitLosses": payload.test.data.temp_split_loss ? (+payload.test.data.temp_split_loss).toFixed(0) : 0,
250
+ "staticLosses": payload.test.data.static_loss ? (+payload.test.data.static_loss).toFixed(0) : 0,
251
+ "approachLosses": payload.test.data.approach_loss ? (+payload.test.data.approach_loss).toFixed(0) : 0,
252
+ "refChargeLosses": payload.test.data.refrigerant_charge_loss ? (+payload.test.data.refrigerant_charge_loss).toFixed(0) : 0
253
+ }
254
+ }
255
+
256
+ async function formPdfBytes() {
257
+ let response = await fetch('/templates/pdf/mq-standard.pdf');
258
+ let data = await response.blob();
259
+ let metadata = {
260
+ type: 'application/pdf'
261
+ };
262
+ let file = new File([data], "mq-standard.pdf", metadata);
263
+ var reader = new FileReader();
264
+ reader.readAsArrayBuffer(file);
265
+ reader.onload = function () {
266
+ console.log("reader.onload: ", reader.result);
267
+ return reader.result;
268
+ };
269
+ reader.onerror = function (error) {
270
+ console.log("reader.onerror: ", error);
271
+ return false;
272
+ };
273
+
274
+ }