diff --git a/app.js b/app.js index 3c6e7a9a..2bdf57a1 100644 --- a/app.js +++ b/app.js @@ -196,4 +196,27 @@ app.use((request, _response, next) => { debug(request.url); next(createError(404, `File not found: ${request.url}`)); }); +/* + * INITIALIZE PDF BROWSERS (Proactive installation for reliability) + */ +// Only initialize if we're not in a startup test +if (!process.env.STARTUP_TEST) { + // Import PDF helpers dynamically to avoid circular dependencies + void (async () => { + try { + const { initializePdfBrowsers } = await import('./helpers/pdf.helpers.js'); + const success = await initializePdfBrowsers(); + if (success) { + debug('PDF browsers initialized successfully during startup'); + } + else { + debug('PDF browser initialization completed with some failures'); + } + } + catch (error) { + debug('Error during PDF browser initialization:', error); + // Don't fail startup for PDF issues + } + })(); +} export default app; diff --git a/config.js b/config.js new file mode 100644 index 00000000..1cdd4d6a --- /dev/null +++ b/config.js @@ -0,0 +1,4 @@ +export const config = { + 'application.useTestDatabases': true, + 'settings.printPdf.browser': 'chrome' +}; diff --git a/docs/pdf-reliability-improvements.md b/docs/pdf-reliability-improvements.md new file mode 100644 index 00000000..6de4da4d --- /dev/null +++ b/docs/pdf-reliability-improvements.md @@ -0,0 +1,148 @@ +# PDF Generation Reliability Improvements + +This document describes the comprehensive improvements made to increase the reliability of Puppeteer installations and PDF generation in Sunrise CMS, addressing issue #18. + +## Problem Statement + +Users were experiencing internal server errors when generating PDFs due to: +- "No fallback system browsers available" errors +- Browser installation only happening AFTER the first failure (reactive approach) +- Limited error handling and retry logic +- No validation that browsers were successfully installed +- Poor error messages for debugging + +## Solution Overview + +The improvements move from a **reactive** to a **proactive** browser management approach with comprehensive error handling and retry logic. + +## Key Improvements + +### 1. Proactive Browser Installation + +**Before**: Browsers were only installed after the first PDF generation failure. +**After**: Browsers are installed during application startup. + +- New `browserManager.helpers.ts` handles all browser-related operations +- Application startup includes `initializePdfBrowsers()` call +- Browsers are validated to ensure they actually work + +### 2. Enhanced Configuration Options + +New configuration settings in `configDefaults.ts`: + +```typescript +'settings.printPdf.maxRetries': 3, // Number of retry attempts +'settings.printPdf.installBothBrowsers': true, // Install both Chrome and Firefox +'settings.printPdf.forceReinstallOnStartup': false, // Force reinstall on every startup +'settings.printPdf.reinstallAfterDays': 30, // Reinstall after N days +'settings.printPdf.proactiveInstallation': true, // Enable proactive installation +``` + +### 3. Comprehensive Error Handling and Retry Logic + +**Before**: Single attempt, then recursive retry if installation hadn't been attempted. +**After**: Configurable retry attempts with exponential backoff and intelligent error recovery. + +- Up to 3 retry attempts by default (configurable) +- Exponential backoff between retries (1s, 2s, 4s, max 5s) +- Smart error detection for browser-related issues +- Automatic browser reinstallation during error recovery +- Detailed error messages including attempt numbers + +### 4. Browser Validation and Availability Checking + +New functions to ensure browsers actually work: + +- `validateBrowserAvailability()` - Tests browser by generating a minimal PDF +- `getBestAvailableBrowser()` - Finds the best working browser +- `ensureBrowsersAvailable()` - Installs and validates browsers + +### 5. Improved PDF Generation Process + +Enhanced `generatePdf()` function: + +```typescript +// New process: +1. Get or create PdfPuppeteer instance with best available browser +2. Try PDF generation (up to maxRetries times) +3. On failure: analyze error, attempt recovery, retry +4. Provide detailed error messages with attempt counts +``` + +### 6. Database Settings Tracking + +New settings stored in database: +- `pdfPuppeteer.lastSuccessfulBrowser` - Tracks last working browser +- `pdfPuppeteer.lastInstallationDate` - Tracks when browsers were installed +- Enhanced `pdfPuppeteer.browserInstallAttempted` logic + +## File Changes + +### New Files +- `helpers/browserManager.helpers.ts` - Comprehensive browser management +- `test/pdf-reliability.test.js` - Tests for reliability improvements +- `test/config-improvements.test.js` - Tests for configuration + +### Modified Files +- `helpers/pdf.helpers.ts` - Enhanced PDF generation with retry logic +- `app.ts` - Added proactive browser initialization at startup +- `data/configDefaults.ts` - Added new configuration options +- `types/setting.types.ts` - Added new database settings + +## Benefits + +1. **Proactive Installation**: Browsers installed at startup, not after first failure +2. **Better User Experience**: Users don't experience errors on first PDF attempt +3. **Improved Reliability**: Multiple retry attempts with intelligent recovery +4. **Better Debugging**: Detailed error messages and logging +5. **Configurable Behavior**: Administrators can tune retry counts, installation behavior +6. **Graceful Degradation**: Application continues to work even if browser installation fails + +## Testing + +The improvements were tested with: +1. Configuration validation tests (all pass) +2. PDF generation reliability tests (show improved error handling) +3. Startup tests (application starts successfully with new initialization) + +Example test output showing improvements: +``` +Max retries configured: 3 +Proactive installation enabled: true +Error: Error generating PDF for Work Order Field Sheet after 3 attempts. Last error: No browsers available and installation failed +✓ Error message includes retry information - improvement working +``` + +## Migration Notes + +The improvements are backward compatible: +- Existing configurations continue to work +- Default values maintain current behavior where applicable +- New features are opt-in through configuration + +## Monitoring and Debugging + +Enhanced logging includes: +- Browser installation attempts and results +- PDF generation attempt numbers +- Error recovery actions +- Browser validation results + +All debug output is under the `sunrise:helpers:browserManager` and `sunrise:helpers:pdf` namespaces. + +## Configuration Examples + +To disable proactive installation (keep old behavior): +```javascript +config.settings.printPdf.proactiveInstallation = false +``` + +To increase retry attempts for problematic environments: +```javascript +config.settings.printPdf.maxRetries = 5 +``` + +To force browser reinstallation on every startup: +```javascript +config.settings.printPdf.forceReinstallOnStartup = true +``` \ No newline at end of file diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo new file mode 100644 index 00000000..a7dc5085 --- /dev/null +++ b/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./app.ts","./cypress.config.ts","./debug.config.ts","./eslint.config.ts","./prettier.config.ts","./version.ts","./windowsService-install.ts","./windowsService-uninstall.ts","./windowsService.ts","./bin/www.ts","./bin/wwwProcess.ts","./cypress/e2e/01-admin/burialSiteTypeManagement.cy.ts","./cypress/e2e/01-admin/configTables.cy.ts","./cypress/e2e/01-admin/contractTypeManagement.cy.ts","./cypress/e2e/01-admin/database.cy.ts","./cypress/e2e/01-admin/feeManagement.cy.ts","./cypress/e2e/01-admin/settings.cy.ts","./cypress/e2e/02-update/0.cemeteries.cy.ts","./cypress/e2e/02-update/1.burialSites.cy.ts","./cypress/e2e/02-update/3.funeralHomes.cy.ts","./cypress/e2e/02-update/4.contracts.cy.ts","./cypress/e2e/02-update/5.workOrders.cy.ts","./cypress/e2e/02-update/updateUser.cy.ts","./cypress/e2e/03-readOnly/readOnlyUser.cy.ts","./cypress/e2e/03-readOnly/reports.cy.ts","./cypress/e2e/03-readOnly/workOrderMilestoneCalendar.cy.ts","./cypress/e2e/03-readOnly/workOrderOutlook.cy.ts","./cypress/e2e/xx-other/keepAlive.cy.ts","./cypress/e2e/xx-other/loginPage.cy.ts","./cypress/support/index.ts","./data/config.ts","./data/configDefaults.ts","./data/dataLists.ts","./data/testing.config.ts","./data/partialConfigs/ontario.partialConfig.ts","./data/partialConfigs/partialConfig.ts","./data/partialConfigs/ssm.ontario.partialConfig.ts","./database/addBurialSite.ts","./database/addBurialSiteComment.ts","./database/addBurialSiteType.ts","./database/addBurialSiteTypeField.ts","./database/addCemetery.ts","./database/addCommittalType.ts","./database/addContract.ts","./database/addContractAttachment.ts","./database/addContractComment.ts","./database/addContractFee.ts","./database/addContractFeeCategory.ts","./database/addContractInterment.ts","./database/addContractTransaction.ts","./database/addContractType.ts","./database/addContractTypeField.ts","./database/addContractTypePrint.ts","./database/addFee.ts","./database/addFeeCategory.ts","./database/addFuneralHome.ts","./database/addIntermentContainerType.ts","./database/addOrUpdateBurialSiteField.ts","./database/addOrUpdateContractField.ts","./database/addRecord.ts","./database/addRelatedContract.ts","./database/addUser.ts","./database/addWorkOrder.ts","./database/addWorkOrderBurialSite.ts","./database/addWorkOrderComment.ts","./database/addWorkOrderContract.ts","./database/addWorkOrderMilestone.ts","./database/backupDatabase.ts","./database/cleanupDatabase.ts","./database/closeWorkOrder.ts","./database/completeWorkOrderMilestone.ts","./database/copyContract.ts","./database/deleteBurialSite.ts","./database/deleteBurialSiteField.ts","./database/deleteCemetery.ts","./database/deleteConsingoCloudContractMetadata.ts","./database/deleteContract.ts","./database/deleteContractFee.ts","./database/deleteContractField.ts","./database/deleteContractInterment.ts","./database/deleteContractMetadata.ts","./database/deleteContractTransaction.ts","./database/deleteContractTypePrint.ts","./database/deleteFuneralHome.ts","./database/deleteRecord.ts","./database/deleteRelatedContract.ts","./database/deleteUser.ts","./database/deleteWorkOrderBurialSite.ts","./database/deleteWorkOrderContract.ts","./database/getApiKeys.ts","./database/getBurialSite.ts","./database/getBurialSiteComments.ts","./database/getBurialSiteDirectionsOfArrival.ts","./database/getBurialSiteFields.ts","./database/getBurialSiteInterments.ts","./database/getBurialSiteNamesByRange.ts","./database/getBurialSiteStatusSummary.ts","./database/getBurialSiteStatuses.ts","./database/getBurialSiteTypeFields.ts","./database/getBurialSiteTypeSummary.ts","./database/getBurialSiteTypes.ts","./database/getBurialSites.ts","./database/getCemeteries.ts","./database/getCemetery.ts","./database/getCemeteryDirectionsOfArrival.ts","./database/getCommittalTypes.ts","./database/getConsignoCloudContractMetadata.ts","./database/getContract.ts","./database/getContractAttachment.ts","./database/getContractAttachments.ts","./database/getContractComments.ts","./database/getContractFees.ts","./database/getContractFields.ts","./database/getContractInterments.ts","./database/getContractMetadata.ts","./database/getContractMetadataByContractId.ts","./database/getContractTransactions.ts","./database/getContractTypeFields.ts","./database/getContractTypePrints.ts","./database/getContractTypes.ts","./database/getContracts.ts","./database/getFee.ts","./database/getFeeCategories.ts","./database/getFees.ts","./database/getFuneralHome.ts","./database/getFuneralHomes.ts","./database/getIntermentContainerTypes.ts","./database/getNextBurialSiteId.ts","./database/getNextCemeteryId.ts","./database/getNextContractId.ts","./database/getNextFuneralHome.ts","./database/getNextWorkOrderNumber.ts","./database/getPreviousBurialSiteId.ts","./database/getPreviousCemeteryId.ts","./database/getPreviousContractId.ts","./database/getPreviousFuneralHomeId.ts","./database/getRecordUpdateLog.ts","./database/getReportData.ts","./database/getSettings.ts","./database/getUser.ts","./database/getUserSettings.ts","./database/getUsers.ts","./database/getWorkOrder.ts","./database/getWorkOrderComments.ts","./database/getWorkOrderMilestoneTypes.ts","./database/getWorkOrderMilestones.ts","./database/getWorkOrderTypes.ts","./database/getWorkOrders.ts","./database/initializeDatabase.ts","./database/moveBurialSiteTypeField.ts","./database/moveContractTypeField.ts","./database/moveContractTypePrintDown.ts","./database/moveContractTypePrintUp.ts","./database/moveFee.ts","./database/moveRecord.ts","./database/purgeBurialSite.ts","./database/rebuildBurialSiteNames.ts","./database/reopenWorkOrder.ts","./database/reopenWorkOrderMilestone.ts","./database/restoreBurialSite.ts","./database/restoreFuneralHome.ts","./database/updateBurialSite.ts","./database/updateBurialSiteComment.ts","./database/updateBurialSiteType.ts","./database/updateBurialSiteTypeField.ts","./database/updateCemetery.ts","./database/updateCemeteryDirectionsOfArrival.ts","./database/updateConsignoCloudMetadata.ts","./database/updateConsignoCloudUserSettings.ts","./database/updateContract.ts","./database/updateContractComment.ts","./database/updateContractFeeQuantity.ts","./database/updateContractInterment.ts","./database/updateContractMetadata.ts","./database/updateContractTransaction.ts","./database/updateContractType.ts","./database/updateContractTypeField.ts","./database/updateFee.ts","./database/updateFeeCategory.ts","./database/updateFuneralHome.ts","./database/updateIntermentContainerType.ts","./database/updateRecord.ts","./database/updateRecordOrderNumber.ts","./database/updateSetting.ts","./database/updateUser.ts","./database/updateUserSetting.ts","./database/updateWorkOrder.ts","./database/updateWorkOrderComment.ts","./database/updateWorkOrderMilestone.ts","./database/updateWorkOrderMilestoneTime.ts","./handlers/permissions.ts","./handlers/admin-get/burialSiteTypes.ts","./handlers/admin-get/contractTypes.ts","./handlers/admin-get/database.ts","./handlers/admin-get/fees.ts","./handlers/admin-get/settings.ts","./handlers/admin-get/tables.ts","./handlers/admin-get/users.ts","./handlers/admin-post/doAddBurialSiteStatus.ts","./handlers/admin-post/doAddBurialSiteType.ts","./handlers/admin-post/doAddBurialSiteTypeField.ts","./handlers/admin-post/doAddCommittalType.ts","./handlers/admin-post/doAddContractType.ts","./handlers/admin-post/doAddContractTypeField.ts","./handlers/admin-post/doAddContractTypePrint.ts","./handlers/admin-post/doAddFee.ts","./handlers/admin-post/doAddFeeCategory.ts","./handlers/admin-post/doAddIntermentContainerType.ts","./handlers/admin-post/doAddUser.ts","./handlers/admin-post/doAddWorkOrderMilestoneType.ts","./handlers/admin-post/doAddWorkOrderType.ts","./handlers/admin-post/doBackupDatabase.ts","./handlers/admin-post/doCleanupDatabase.ts","./handlers/admin-post/doDeleteBurialSiteStatus.ts","./handlers/admin-post/doDeleteBurialSiteType.ts","./handlers/admin-post/doDeleteBurialSiteTypeField.ts","./handlers/admin-post/doDeleteCommittalType.ts","./handlers/admin-post/doDeleteContractType.ts","./handlers/admin-post/doDeleteContractTypeField.ts","./handlers/admin-post/doDeleteContractTypePrint.ts","./handlers/admin-post/doDeleteFee.ts","./handlers/admin-post/doDeleteFeeCategory.ts","./handlers/admin-post/doDeleteIntermentContainerType.ts","./handlers/admin-post/doDeleteUser.ts","./handlers/admin-post/doDeleteWorkOrderMilestoneType.ts","./handlers/admin-post/doDeleteWorkOrderType.ts","./handlers/admin-post/doMoveBurialSiteStatusDown.ts","./handlers/admin-post/doMoveBurialSiteStatusUp.ts","./handlers/admin-post/doMoveBurialSiteTypeDown.ts","./handlers/admin-post/doMoveBurialSiteTypeFieldDown.ts","./handlers/admin-post/doMoveBurialSiteTypeFieldUp.ts","./handlers/admin-post/doMoveBurialSiteTypeUp.ts","./handlers/admin-post/doMoveCommittalTypeDown.ts","./handlers/admin-post/doMoveCommittalTypeUp.ts","./handlers/admin-post/doMoveContractTypeDown.ts","./handlers/admin-post/doMoveContractTypeFieldDown.ts","./handlers/admin-post/doMoveContractTypeFieldUp.ts","./handlers/admin-post/doMoveContractTypePrintDown.ts","./handlers/admin-post/doMoveContractTypePrintUp.ts","./handlers/admin-post/doMoveContractTypeUp.ts","./handlers/admin-post/doMoveFeeCategoryDown.ts","./handlers/admin-post/doMoveFeeCategoryUp.ts","./handlers/admin-post/doMoveFeeDown.ts","./handlers/admin-post/doMoveFeeUp.ts","./handlers/admin-post/doMoveIntermentContainerTypeDown.ts","./handlers/admin-post/doMoveIntermentContainerTypeUp.ts","./handlers/admin-post/doMoveWorkOrderMilestoneTypeDown.ts","./handlers/admin-post/doMoveWorkOrderMilestoneTypeUp.ts","./handlers/admin-post/doMoveWorkOrderTypeDown.ts","./handlers/admin-post/doMoveWorkOrderTypeUp.ts","./handlers/admin-post/doToggleUserPermission.ts","./handlers/admin-post/doUpdateBurialSiteStatus.ts","./handlers/admin-post/doUpdateBurialSiteType.ts","./handlers/admin-post/doUpdateBurialSiteTypeField.ts","./handlers/admin-post/doUpdateCommittalType.ts","./handlers/admin-post/doUpdateContractType.ts","./handlers/admin-post/doUpdateContractTypeField.ts","./handlers/admin-post/doUpdateFee.ts","./handlers/admin-post/doUpdateFeeAmount.ts","./handlers/admin-post/doUpdateFeeCategory.ts","./handlers/admin-post/doUpdateIntermentContainerType.ts","./handlers/admin-post/doUpdateSetting.ts","./handlers/admin-post/doUpdateUser.ts","./handlers/admin-post/doUpdateWorkOrderMilestoneType.ts","./handlers/admin-post/doUpdateWorkOrderType.ts","./handlers/api-get/milestoneICS.ts","./handlers/burialSites-get/creator.ts","./handlers/burialSites-get/edit.ts","./handlers/burialSites-get/gpsCapture.ts","./handlers/burialSites-get/new.ts","./handlers/burialSites-get/next.ts","./handlers/burialSites-get/previous.ts","./handlers/burialSites-get/search.ts","./handlers/burialSites-get/view.ts","./handlers/burialSites-post/doAddBurialSiteComment.ts","./handlers/burialSites-post/doCreateBurialSite.ts","./handlers/burialSites-post/doDeleteBurialSite.ts","./handlers/burialSites-post/doDeleteBurialSiteComment.ts","./handlers/burialSites-post/doGetBurialSiteNamesByRange.ts","./handlers/burialSites-post/doGetBurialSiteTypeFields.ts","./handlers/burialSites-post/doRestoreBurialSite.ts","./handlers/burialSites-post/doSearchBurialSites.ts","./handlers/burialSites-post/doSearchBurialSitesForGPS.ts","./handlers/burialSites-post/doUpdateBurialSite.ts","./handlers/burialSites-post/doUpdateBurialSiteComment.ts","./handlers/burialSites-post/doUpdateBurialSiteLatitudeLongitude.ts","./handlers/cemeteries-get/edit.ts","./handlers/cemeteries-get/new.ts","./handlers/cemeteries-get/next.ts","./handlers/cemeteries-get/previous.ts","./handlers/cemeteries-get/search.ts","./handlers/cemeteries-get/view.ts","./handlers/cemeteries-post/doCreateCemetery.ts","./handlers/cemeteries-post/doDeleteCemetery.ts","./handlers/cemeteries-post/doUpdateCemetery.ts","./handlers/contracts-get/attachment.ts","./handlers/contracts-get/edit.ts","./handlers/contracts-get/new.ts","./handlers/contracts-get/next.ts","./handlers/contracts-get/previous.ts","./handlers/contracts-get/search.ts","./handlers/contracts-get/view.ts","./handlers/contracts-post/doAddContractComment.ts","./handlers/contracts-post/doAddContractFee.ts","./handlers/contracts-post/doAddContractFeeCategory.ts","./handlers/contracts-post/doAddContractInterment.ts","./handlers/contracts-post/doAddContractTransaction.ts","./handlers/contracts-post/doAddRelatedContract.ts","./handlers/contracts-post/doCopyContract.ts","./handlers/contracts-post/doCreateContract.ts","./handlers/contracts-post/doDeleteContract.ts","./handlers/contracts-post/doDeleteContractComment.ts","./handlers/contracts-post/doDeleteContractFee.ts","./handlers/contracts-post/doDeleteContractInterment.ts","./handlers/contracts-post/doDeleteContractTransaction.ts","./handlers/contracts-post/doDeleteRelatedContract.ts","./handlers/contracts-post/doGetBurialSiteDirectionsOfArrival.ts","./handlers/contracts-post/doGetContractDetailsForConsignoCloud.ts","./handlers/contracts-post/doGetContractTypeFields.ts","./handlers/contracts-post/doGetDynamicsGPDocument.ts","./handlers/contracts-post/doGetFees.ts","./handlers/contracts-post/doGetPossibleRelatedContracts.ts","./handlers/contracts-post/doSearchContracts.ts","./handlers/contracts-post/doStartConsignoCloudWorkflow.ts","./handlers/contracts-post/doUpdateContract.ts","./handlers/contracts-post/doUpdateContractComment.ts","./handlers/contracts-post/doUpdateContractFeeQuantity.ts","./handlers/contracts-post/doUpdateContractInterment.ts","./handlers/contracts-post/doUpdateContractTransaction.ts","./handlers/dashboard-get/dashboard.ts","./handlers/dashboard-get/updateLog.ts","./handlers/dashboard-get/userSettings.ts","./handlers/dashboard-post/doGetRecordUpdateLog.ts","./handlers/dashboard-post/doUpdateConsignoCloudUserSettings.ts","./handlers/funeralHomes-get/edit.ts","./handlers/funeralHomes-get/new.ts","./handlers/funeralHomes-get/next.ts","./handlers/funeralHomes-get/previous.ts","./handlers/funeralHomes-get/search.ts","./handlers/funeralHomes-get/view.ts","./handlers/funeralHomes-post/doCreateFuneralHome.ts","./handlers/funeralHomes-post/doDeleteFuneralHome.ts","./handlers/funeralHomes-post/doRestoreFuneralHome.ts","./handlers/funeralHomes-post/doUpdateFuneralHome.ts","./handlers/print-get/pdf.ts","./handlers/print-get/screen.ts","./handlers/reports-get/reportName.ts","./handlers/reports-get/search.ts","./handlers/workOrders-get/byWorkOrderNumber.ts","./handlers/workOrders-get/edit.ts","./handlers/workOrders-get/milestoneCalendar.ts","./handlers/workOrders-get/new.ts","./handlers/workOrders-get/outlook.ts","./handlers/workOrders-get/search.ts","./handlers/workOrders-get/view.ts","./handlers/workOrders-get/workday.ts","./handlers/workOrders-post/doAddWorkOrderBurialSite.ts","./handlers/workOrders-post/doAddWorkOrderComment.ts","./handlers/workOrders-post/doAddWorkOrderContract.ts","./handlers/workOrders-post/doAddWorkOrderMilestone.ts","./handlers/workOrders-post/doCloseWorkOrder.ts","./handlers/workOrders-post/doCloseWorkdayWorkOrder.ts","./handlers/workOrders-post/doCompleteWorkOrderMilestone.ts","./handlers/workOrders-post/doCompleteWorkdayWorkOrderMilestone.ts","./handlers/workOrders-post/doCreateWorkOrder.ts","./handlers/workOrders-post/doDeleteWorkOrder.ts","./handlers/workOrders-post/doDeleteWorkOrderBurialSite.ts","./handlers/workOrders-post/doDeleteWorkOrderComment.ts","./handlers/workOrders-post/doDeleteWorkOrderContract.ts","./handlers/workOrders-post/doDeleteWorkOrderMilestone.ts","./handlers/workOrders-post/doGetWorkOrderMilestones.ts","./handlers/workOrders-post/doGetWorkdayReport.ts","./handlers/workOrders-post/doReopenWorkOrder.ts","./handlers/workOrders-post/doReopenWorkOrderMilestone.ts","./handlers/workOrders-post/doReopenWorkdayWorkOrderMilestone.ts","./handlers/workOrders-post/doSearchWorkOrders.ts","./handlers/workOrders-post/doUpdateBurialSiteStatus.ts","./handlers/workOrders-post/doUpdateWorkOrder.ts","./handlers/workOrders-post/doUpdateWorkOrderComment.ts","./handlers/workOrders-post/doUpdateWorkOrderMilestone.ts","./handlers/workOrders-post/doUpdateWorkdayWorkOrderMilestoneTime.ts","./helpers/api.helpers.ts","./helpers/attachments.helpers.ts","./helpers/authentication.helpers.ts","./helpers/barcode.helpers.ts","./helpers/browserManager.helpers.ts","./helpers/burialSites.helpers.ts","./helpers/cache.helpers.ts","./helpers/config.helpers.ts","./helpers/contracts.helpers.ts","./helpers/customizations.helpers.ts","./helpers/database.helpers.ts","./helpers/functions.fee.ts","./helpers/functions.sqlFilters.ts","./helpers/images.helpers.ts","./helpers/pdf.helpers.ts","./helpers/print.helpers.ts","./helpers/settings.helpers.ts","./helpers/user.helpers.ts","./helpers/cache/apiKeys.cache.ts","./helpers/cache/burialSiteStatuses.cache.ts","./helpers/cache/burialSiteTypes.cache.ts","./helpers/cache/committalTypes.cache.ts","./helpers/cache/contractTypes.cache.ts","./helpers/cache/intermentContainerTypes.cache.ts","./helpers/cache/settings.cache.ts","./helpers/cache/workOrderMilestoneTypes.cache.ts","./helpers/cache/workOrderTypes.cache.ts","./integrations/consignoCloud/helpers.ts","./integrations/consignoCloud/pollWorkflow.ts","./integrations/consignoCloud/startWorkflow.ts","./integrations/consignoCloud/updateWorkflows.task.ts","./integrations/dynamicsGp/helpers.ts","./integrations/dynamicsGp/types.ts","./integrations/ntfy/helpers.ts","./integrations/ntfy/types.ts","./routes/admin.ts","./routes/api.ts","./routes/burialSites.ts","./routes/cemeteries.ts","./routes/contracts.ts","./routes/dashboard.ts","./routes/funeralHomes.ts","./routes/login.ts","./routes/print.ts","./routes/reports.ts","./routes/workOrders.ts","./test/0.initializeDatabase.test.ts","./test/1.serverCypress.test.ts","./test/_globals.ts","./test/functions.sqlFilters.test.ts","./test/helpers.burialSites.test.ts","./test/helpers.cache.test.ts","./test/helpers.pdf.test.ts","./test/helpers.user.test.ts","./test/version.test.ts","./types/application.types.ts","./types/config.types.ts","./types/contractMetadata.types.ts","./types/record.types.ts","./types/setting.types.ts","./types/user.types.ts"],"errors":true,"version":"5.7.3"} \ No newline at end of file diff --git a/types/setting.types.d.ts b/types/setting.types.d.ts index 0b00d79a..d41be821 100644 --- a/types/setting.types.d.ts +++ b/types/setting.types.d.ts @@ -1,4 +1,4 @@ -export type SettingKey = 'aliases.externalReceiptNumber' | 'aliases.workOrderCloseDate' | 'aliases.workOrderOpenDate' | 'burialSiteTypes.bodyCapacityMaxDefault' | 'burialSiteTypes.crematedCapacityMaxDefault' | 'pdfPuppeteer.browserInstallAttempted' | 'workOrder.workDay.0.endHour' | 'workOrder.workDay.0.startHour' | 'workOrder.workDay.1.endHour' | 'workOrder.workDay.1.startHour' | 'workOrder.workDay.2.endHour' | 'workOrder.workDay.2.startHour' | 'workOrder.workDay.3.endHour' | 'workOrder.workDay.3.startHour' | 'workOrder.workDay.4.endHour' | 'workOrder.workDay.4.startHour' | 'workOrder.workDay.5.endHour' | 'workOrder.workDay.5.startHour' | 'workOrder.workDay.6.endHour' | 'workOrder.workDay.6.startHour'; +export type SettingKey = 'aliases.externalReceiptNumber' | 'aliases.workOrderCloseDate' | 'aliases.workOrderOpenDate' | 'burialSiteTypes.bodyCapacityMaxDefault' | 'burialSiteTypes.crematedCapacityMaxDefault' | 'pdfPuppeteer.browserInstallAttempted' | 'pdfPuppeteer.lastSuccessfulBrowser' | 'pdfPuppeteer.lastInstallationDate' | 'workOrder.workDay.0.endHour' | 'workOrder.workDay.0.startHour' | 'workOrder.workDay.1.endHour' | 'workOrder.workDay.1.startHour' | 'workOrder.workDay.2.endHour' | 'workOrder.workDay.2.startHour' | 'workOrder.workDay.3.endHour' | 'workOrder.workDay.3.startHour' | 'workOrder.workDay.4.endHour' | 'workOrder.workDay.4.startHour' | 'workOrder.workDay.5.endHour' | 'workOrder.workDay.5.startHour' | 'workOrder.workDay.6.endHour' | 'workOrder.workDay.6.startHour'; export interface SettingProperties { settingKey: SettingKey; settingName: string; diff --git a/types/setting.types.ts b/types/setting.types.ts index e991b28a..3502cae9 100644 --- a/types/setting.types.ts +++ b/types/setting.types.ts @@ -8,6 +8,8 @@ export type SettingKey = | 'burialSiteTypes.bodyCapacityMaxDefault' | 'burialSiteTypes.crematedCapacityMaxDefault' | 'pdfPuppeteer.browserInstallAttempted' + | 'pdfPuppeteer.lastSuccessfulBrowser' + | 'pdfPuppeteer.lastInstallationDate' | 'workOrder.workDay.0.endHour' | 'workOrder.workDay.0.startHour' | 'workOrder.workDay.1.endHour' @@ -174,5 +176,19 @@ export const settingProperties: SettingProperties[] = [ description: 'Whether the PDF Puppeteer browser installation was attempted.', type: 'boolean', defaultValue: 'false' + }, + { + settingKey: 'pdfPuppeteer.lastSuccessfulBrowser', + settingName: 'PDF Puppeteer - Last Successful Browser', + description: 'The last browser that was successfully used for PDF generation.', + type: 'string', + defaultValue: '' + }, + { + settingKey: 'pdfPuppeteer.lastInstallationDate', + settingName: 'PDF Puppeteer - Last Installation Date', + description: 'The date when browsers were last successfully installed.', + type: 'string', + defaultValue: '' } ]