├── force-app └── main │ └── default │ ├── lwc │ ├── .eslintrc.json │ └── jsconfig.json │ ├── workflows │ ├── Limit__c.workflow-meta.xml │ └── LimitSnapshot__c.workflow-meta.xml │ ├── classes │ ├── LimitsUtil.cls-meta.xml │ ├── LimitsUtilTest.cls-meta.xml │ ├── LimitsSnapshotSchedule.cls-meta.xml │ ├── LimitsSnapshotSchedule.cls │ ├── LimitsSnapshotScheduleTest.cls-meta.xml │ ├── LimitsSnapshotScheduleTest.cls │ ├── LimitsUtil.cls │ └── LimitsUtilTest.cls │ ├── tabs │ └── Limit__c.tab-meta.xml │ ├── email │ ├── Limit_Monitoring_Templates.emailFolder-meta.xml │ └── Limit_Monitoring_Templates │ │ ├── Limit_Change_Threshold_Exceeded.email-meta.xml │ │ ├── Limit_Value_Threshold_Exceeded.email-meta.xml │ │ ├── Limit_Value_Threshold_Exceeded.email │ │ └── Limit_Change_Threshold_Exceeded.email │ ├── queues │ └── Limit_Notification_Queue.queue-meta.xml │ ├── notificationtypes │ └── Limit_Alert.notiftype-meta.xml │ ├── reports │ ├── LimitsReports.reportFolder-meta.xml │ └── LimitsReports │ │ └── Limit_Snapshot_Trending_ntK.report-meta.xml │ ├── objects │ ├── LimitSnapshot__c │ │ ├── fields │ │ │ ├── PastRetentionPeriod__c.field-meta.xml │ │ │ ├── PercentChangedSinceLastSnapshot__c.field-meta.xml │ │ │ ├── Value__c.field-meta.xml │ │ │ ├── MaximumValue__c.field-meta.xml │ │ │ ├── Limit__c.field-meta.xml │ │ │ └── PercentOfLimit__c.field-meta.xml │ │ └── LimitSnapshot__c.object-meta.xml │ └── Limit__c │ │ ├── listViews │ │ ├── Limit_Notification_Queue_Limit.listView-meta.xml │ │ └── All.listView-meta.xml │ │ ├── fields │ │ ├── MuteAlerts__c.field-meta.xml │ │ ├── LastPercentOfLimit__c.field-meta.xml │ │ ├── AlertThreshold__c.field-meta.xml │ │ ├── Errors__c.field-meta.xml │ │ ├── TemporaryAlertThresholdExpiration__c.field-meta.xml │ │ ├── TemporaryAlertThreshold__c.field-meta.xml │ │ ├── LastSnapshotValue__c.field-meta.xml │ │ ├── NextRetrieveTime__c.field-meta.xml │ │ ├── LimitKey__c.field-meta.xml │ │ ├── ChangeThreshold__c.field-meta.xml │ │ ├── LastRetrieveTime__c.field-meta.xml │ │ ├── RetrieveIntervalHours__c.field-meta.xml │ │ └── SnapshotRetentionDays__c.field-meta.xml │ │ ├── validationRules │ │ ├── LMT002_TemporaryThresholdReqExpiration.validationRule-meta.xml │ │ └── LMT001_TemporaryThresholdReqExpiration.validationRule-meta.xml │ │ └── Limit__c.object-meta.xml │ ├── flows │ ├── Limit_Snapshot_Update_Limit_s_Last_Value_Fields.flow-meta.xml │ ├── Limit_Snapshot_Set_Percent_Changed_Since_Last_Snapshot.flow-meta.xml │ ├── Limits_Clear_Temporary_Alerts_Threshold.flow-meta.xml │ ├── Limit_Snapshot_Notify_if_Percent_Changed_Exceeds_Threshold.flow-meta.xml │ └── Limit_Snapshot_Notify_if_Percent_of_Limit_Exceeds_Threshold.flow-meta.xml │ ├── layouts │ ├── LimitSnapshot__c-Limit Snapshot Layout.layout-meta.xml │ └── Limit__c-Limit Layout.layout-meta.xml │ ├── permissionsets │ └── LimitMonitorPermissions.permissionset-meta.xml │ └── flexipages │ ├── Limit_Snapshot_Record_Page.flexipage-meta.xml │ └── Limit_Record_Page.flexipage-meta.xml ├── config └── project-scratch-def.json ├── .prettierignore ├── .prettierrc ├── .forceignore ├── sfdx-project.json ├── .gitignore ├── LICENSE └── README.md /force-app/main/default/lwc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@salesforce/eslint-config-lwc/recommended"] 3 | } 4 | -------------------------------------------------------------------------------- /config/project-scratch-def.json: -------------------------------------------------------------------------------- 1 | { 2 | "orgName": "limits snapshot", 3 | "edition": "Developer", 4 | "features": [] 5 | } 6 | -------------------------------------------------------------------------------- /force-app/main/default/workflows/Limit__c.workflow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running prettier 2 | # More information: https://prettier.io/docs/en/ignore.html 3 | # 4 | 5 | .sfdx 6 | .localdevserver -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsUtil.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsUtilTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/tabs/Limit__c.tab-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | Custom21: Computer 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsSnapshotSchedule.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsSnapshotSchedule.cls: -------------------------------------------------------------------------------- 1 | global with sharing class LimitsSnapshotSchedule implements Schedulable { 2 | global void execute(SchedulableContext sc) { 3 | LimitsUtil.retrieveLimits(); 4 | LimitsUtil.deleteLimits(); 5 | } 6 | } -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsSnapshotScheduleTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "overrides": [ 4 | { 5 | "files": "**/lwc/**/*.html", 6 | "options": { "parser": "lwc" } 7 | }, 8 | { 9 | "files": "*.{cmp,page,component}", 10 | "options": { "parser": "html" } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsSnapshotScheduleTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public with sharing class LimitsSnapshotScheduleTest { 3 | @isTest 4 | static void testSchedule() { 5 | LimitsSnapshotSchedule lss = new LimitsSnapshotSchedule(); 6 | // Just execute the schedulable class for test coverage 7 | lss.execute(null); 8 | } 9 | } -------------------------------------------------------------------------------- /force-app/main/default/email/Limit_Monitoring_Templates.emailFolder-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Public 4 | Limit Monitoring Templates 5 | ReadOnly 6 | 7 | -------------------------------------------------------------------------------- /force-app/main/default/queues/Limit_Notification_Queue.queue-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | Limit Notification Queue 5 | 6 | Limit__c 7 | 8 | 9 | -------------------------------------------------------------------------------- /force-app/main/default/lwc/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "baseUrl": ".", 5 | "paths": {} 6 | }, 7 | "include": [ 8 | "**/*", 9 | "../../../../.sfdx/typings/lwc/**/*.d.ts" 10 | ], 11 | "typeAcquisition": { 12 | "include": [ 13 | "jest" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /force-app/main/default/notificationtypes/Limit_Alert.notiftype-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Limit Alert 4 | true 5 | Limit Alert 6 | true 7 | false 8 | 9 | -------------------------------------------------------------------------------- /force-app/main/default/reports/LimitsReports.reportFolder-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Manage 5 | test-xrim69vl0ijm@example.com 6 | User 7 | 8 | Limits Reports 9 | 10 | -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/PastRetentionPeriod__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PastRetentionPeriod__c 4 | CreatedDate < (NOW() - BLANKVALUE(Limit__r.SnapshotRetentionDays__c, 0)) 5 | 6 | false 7 | Checkbox 8 | 9 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/listViews/Limit_Notification_Queue_Limit.listView-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Limit_Notification_Queue_Limit 4 | Queue 5 | 6 | Limit_Notification_Queue 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/MuteAlerts__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MuteAlerts__c 4 | false 5 | To stop all alerts, check this box. 6 | 7 | true 8 | false 9 | Checkbox 10 | 11 | -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/PercentChangedSinceLastSnapshot__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PercentChangedSinceLastSnapshot__c 4 | 5 | 16 6 | false 7 | 2 8 | false 9 | Percent 10 | 11 | -------------------------------------------------------------------------------- /force-app/main/default/email/Limit_Monitoring_Templates/Limit_Change_Threshold_Exceeded.email-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | true 5 | ISO-8859-1 6 | Limit Change Threshold Exceeded 7 | 8 | Salesforce Limit Exceeded for 9 | visualforce 10 | Aloha 11 | 12 | -------------------------------------------------------------------------------- /force-app/main/default/email/Limit_Monitoring_Templates/Limit_Value_Threshold_Exceeded.email-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | true 5 | ISO-8859-1 6 | Limit Value Threshold Exceeded 7 | 8 | Salesforce Limit Exceeded for 9 | visualforce 10 | Aloha 11 | 12 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/listViews/All.listView-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | All 4 | NAME 5 | AlertThreshold__c 6 | ChangeThreshold__c 7 | LastPercentOfLimit__c 8 | LastRetrieveTime__c 9 | NextRetrieveTime__c 10 | Everything 11 | 12 | 13 | -------------------------------------------------------------------------------- /.forceignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status 2 | # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm 3 | # 4 | 5 | package.xml 6 | 7 | # LWC configuration files 8 | **/jsconfig.json 9 | **/.eslintrc.json 10 | 11 | # LWC Jest 12 | **/__tests__/** 13 | 14 | # profiles 15 | force-app/main/default/profiles 16 | force-app/main/default/profilePasswordPolicies 17 | force-app/main/default/profileSessionSettings -------------------------------------------------------------------------------- /sfdx-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageDirectories": [ 3 | { 4 | "path": "force-app", 5 | "package": "limits-monitor", 6 | "versionName": "ver 0.2", 7 | "versionNumber": "0.2.0.NEXT", 8 | "default": true 9 | } 10 | ], 11 | "namespace": "", 12 | "sfdcLoginUrl": "https://login.salesforce.com", 13 | "sourceApiVersion": "63.0", 14 | "packageAliases": { 15 | "limits-monitor": "0Ho4O000000CaRHSA0", 16 | "limits-monitor@0.2.0-1": "04t4O000000MjS8QAK" 17 | } 18 | } -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/Value__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Value__c 4 | false 5 | The current value of the limit at the time of the snapshot 6 | 7 | 18 8 | false 9 | 0 10 | false 11 | Number 12 | false 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/LastPercentOfLimit__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LastPercentOfLimit__c 4 | The percent of limit when the last snapshot was taken. 5 | 6 | 16 7 | false 8 | 2 9 | false 10 | false 11 | Percent 12 | 13 | -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/MaximumValue__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MaximumValue__c 4 | false 5 | The maximum value for the org at the time of the snapshot 6 | 7 | 18 8 | false 9 | 0 10 | false 11 | Number 12 | false 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/AlertThreshold__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | AlertThreshold__c 4 | 0.8 5 | If the limit exceeds the threshold, then trigger alerts 6 | 7 | 2 8 | true 9 | 0 10 | true 11 | false 12 | Percent 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/Errors__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Errors__c 4 | false 5 | If there are any errors while retrieving the limit, they will be recorded here. 6 | 7 | 255 8 | false 9 | false 10 | false 11 | Text 12 | false 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/TemporaryAlertThresholdExpiration__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | TemporaryAlertThresholdExpiration__c 4 | When to remove the temporary alert threshold. The Temporary Alert Threshold field will be cleared at this time. 5 | 6 | false 7 | true 8 | false 9 | DateTime 10 | 11 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/TemporaryAlertThreshold__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | TemporaryAlertThreshold__c 4 | If an alert has been triggered and you want to temporarily increase the threshold 5 | 6 | 18 7 | false 8 | 0 9 | true 10 | false 11 | Percent 12 | 13 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/LastSnapshotValue__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LastSnapshotValue__c 4 | false 5 | The value of the last snapshot taken 6 | 7 | 18 8 | false 9 | 0 10 | false 11 | false 12 | Number 13 | false 14 | 15 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/NextRetrieveTime__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NextRetrieveTime__c 4 | LastRetrieveTime__c + (RetrieveIntervalHours__c/24) 5 | BlankAsZero 6 | The next time the limit will be retrieved 7 | 8 | false 9 | false 10 | false 11 | DateTime 12 | 13 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/LimitKey__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LimitKey__c 4 | false 5 | true 6 | The API name of the limit that corresponds to the map in the OrgLimits class 7 | 8 | 80 9 | true 10 | false 11 | false 12 | Text 13 | true 14 | 15 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/ChangeThreshold__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ChangeThreshold__c 4 | 0.2 5 | The threshold for the amount of change from one measurement to the other that should trigger alerts. 6 | 7 | 2 8 | true 9 | 0 10 | true 11 | false 12 | Percent 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/LastRetrieveTime__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LastRetrieveTime__c 4 | The last Date/Time a snapshot was retrieved 5 | 6 | LimitSnapshot__c.CreatedDate 7 | LimitSnapshot__c.Limit__c 8 | max 9 | false 10 | false 11 | Summary 12 | 13 | -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/Limit__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Limit__c 4 | 5 | Limit__c 6 | Limit Snapshots 7 | Limit_Snapshots 8 | 0 9 | false 10 | false 11 | MasterDetail 12 | false 13 | 14 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/RetrieveIntervalHours__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | RetrieveIntervalHours__c 4 | 1 5 | false 6 | How often to retrieve this limit in hours 7 | 8 | 18 9 | false 10 | 2 11 | true 12 | false 13 | Number 14 | false 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used for Git repositories to specify intentionally untracked files that Git should ignore. 2 | # If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore 3 | # For useful gitignore templates see: https://github.com/github/gitignore 4 | 5 | # Salesforce cache 6 | .sfdx/ 7 | .localdevserver/ 8 | .vscode/ 9 | .sf/** 10 | 11 | # Logs 12 | logs 13 | *.log 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Dependency directories 19 | node_modules/ 20 | 21 | # Eslint cache 22 | .eslintcache 23 | 24 | # MacOS system files 25 | .DS_Store 26 | 27 | # Windows system files 28 | Thumbs.db 29 | ehthumbs.db 30 | [Dd]esktop.ini 31 | $RECYCLE.BIN/ -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/fields/PercentOfLimit__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PercentOfLimit__c 4 | IF( 5 | BLANKVALUE(MaximumValue__c, 0) != 0, 6 | BLANKVALUE(Value__c, 0) / MaximumValue__c, 7 | 0 8 | ) 9 | BlankAsZero 10 | The percent of the limit used in the org at time of snapshot 11 | 12 | 18 13 | false 14 | 2 15 | false 16 | Percent 17 | 18 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/fields/SnapshotRetentionDays__c.field-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SnapshotRetentionDays__c 4 | 365 5 | false 6 | The number of days to retain snapshots. Any snapshots older will be deleted. Leave blank to retain all snapshots 7 | 8 | 18 9 | false 10 | 0 11 | false 12 | false 13 | Number 14 | false 15 | 16 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/validationRules/LMT002_TemporaryThresholdReqExpiration.validationRule-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LMT002_TemporaryThresholdReqExpiration 4 | true 5 | When a an expiration date time is entered, temporary threshold is needed 6 | ISBLANK(TemporaryAlertThreshold__c) && NOT(ISBLANK( TemporaryAlertThresholdExpiration__c)) 7 | TemporaryAlertThreshold__c 8 | When a Temporary Alert Threshold Expiration is entered, the Temporary Alert Threshold is needed. [LMT-002] 9 | 10 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/validationRules/LMT001_TemporaryThresholdReqExpiration.validationRule-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LMT001_TemporaryThresholdReqExpiration 4 | true 5 | When a temporary threshold is entered, an expiration date time is needed 6 | NOT(ISBLANK(TemporaryAlertThreshold__c)) && ISBLANK( TemporaryAlertThresholdExpiration__c) 7 | TemporaryAlertThresholdExpiration__c 8 | When a Temporary Alert Threshold is entered, the Temporary Alert Threshold Expiration is needed. [LMT-001] 9 | 10 | -------------------------------------------------------------------------------- /force-app/main/default/workflows/LimitSnapshot__c.workflow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Limit_Change_Threshold_Exceeded 5 | Limit Change Threshold Exceeded 6 | false 7 | 8 | owner 9 | 10 | CurrentUser 11 | 12 | 13 | 14 | Limit_Value_Threshold_Exceeded 15 | Limit Value Threshold Exceeded 16 | false 17 | 18 | owner 19 | 20 | CurrentUser 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Daniel Hoechst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /force-app/main/default/email/Limit_Monitoring_Templates/Limit_Value_Threshold_Exceeded.email: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The limit for {!relatedTo.Limit__r.Name} has exceeded the threshold set.
6 |
7 | Current Value: 8 | 9 | 10 |
11 | Limit: 12 | 13 | 14 |
15 | Percent of Limit: 16 | 17 | 18 |
19 | 20 | Alert Threshold: 21 | 22 | 23 |
24 | 25 | 26 |
27 | 28 | The limit for {!relatedTo.Limit__r.Name} has exceeded the threshold set. 29 | Current Value: {!TEXT(relatedTo.Value__c)} 30 | Limit: {!TEXT(relatedTo.MaximumValue__c)} 31 | Percent of Limit: {!TEXT(relatedTo.PercentOfLimit__c)}% 32 | Alert Threshold: {!TEXT(relatedTo.Limit__r.AlertThreshold__c)}% 33 | 34 |
-------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsUtil.cls: -------------------------------------------------------------------------------- 1 | public with sharing class LimitsUtil { 2 | private static final String INVALID_LIMIT = 'The limit key is invalid. Please check the key and update.'; 3 | 4 | public static void retrieveLimits() { 5 | // get the current org limits 6 | Map limitsMap = OrgLimits.getMap(); 7 | 8 | List snapshots = new List(); 9 | List limitsToUpdate = new List(); 10 | 11 | // Query the limits to track and loop through them to record them. 12 | // Use 2 minutes in the future as the comparison to account for variation in the scheduler. 13 | for (Limit__c lim : [ 14 | SELECT Id, LimitKey__c 15 | FROM Limit__c 16 | WHERE NextRetrieveTime__c = null OR NextRetrieveTime__c < :System.now().addMinutes(2) 17 | ]) { 18 | if (!limitsMap.containsKey(lim.LimitKey__c)) { 19 | lim.Errors__c = INVALID_LIMIT; 20 | limitsToUpdate.add(lim); 21 | } else { 22 | System.OrgLimit orgLimit = limitsMap.get(lim.LimitKey__c); 23 | snapshots.add( 24 | new LimitSnapshot__c( 25 | Limit__c = lim.Id, 26 | MaximumValue__c = orgLimit.getLimit(), 27 | Value__c = orgLimit.getValue() 28 | ) 29 | ); 30 | } 31 | } 32 | 33 | insert snapshots; 34 | update limitsToUpdate; 35 | } 36 | 37 | public static void deleteLimits() { 38 | // Delete all snapshots older than the retention days set on each limit 39 | List snapshots = [ 40 | SELECT Id 41 | FROM LimitSnapshot__c 42 | WHERE 43 | PastRetentionPeriod__c = true 44 | WITH SYSTEM_MODE 45 | ]; 46 | Database.delete(snapshots, System.AccessLevel.SYSTEM_MODE); 47 | } 48 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # salesforce-limit-monitor 2 | App for monitoring Salesforce org limits. This app will send push notifications when you are at 80% (default) of a limit or if it increases 20% (default) or more from one snapshot to the next. By default, it snapshots limits once per hour. All options can be changed on a per limit basis. 3 | 4 | You can also mute notifications for a certain time period or temporarily increase the alert threshold. 5 | 6 | Installation steps 7 | 8 | 1. Clone and deploy using sfdx or as an unlocked package (https://login.salesforce.com/packaging/installPackage.apexp?p0=04tKW0000002BYjYAM) 9 | 2. If you want to send emails people or systems not in Salesforce. Update the [email alerts](https://github.com/dhoechst/salesforce-limit-monitor/blob/master/force-app/main/default/workflows/LimitSnapshot__c.workflow-meta.xml) with the correct email address. 10 | 3. To get emails and push notifications, add users to the Limit Notification Queue. 11 | 4. Add Limits records for limits you want to monitor. Make the owner be the Limit Notification Queue to send an email to all members of the queue. To add all limits, run this in Execute Anonymous: 12 | ```java 13 | Id limitsQueue = [SELECT Id FROM Group WHERE DeveloperName = 'Limit_Notification_Queue'].Id; 14 | Map limitsMap = OrgLimits.getMap(); 15 | 16 | List limits = new List(); 17 | for (String lim : limitsMap.keySet()) { 18 | limits.add(new Limit__c( 19 | OwnerId = limitsQueue, 20 | Name = lim, 21 | LimitKey__c = lim 22 | )); 23 | } 24 | 25 | insert limits; 26 | ``` 27 | 5. Schedule the monitoring job using Execute Anonymous. In this case, it is scheduled to run every 15 minutes: 28 | ```java 29 | System.schedule('Limits Monitor 1', '0 0 * * * ?', new LimitsSnapshotSchedule()); 30 | System.schedule('Limits Monitor 2', '0 15 * * * ?', new LimitsSnapshotSchedule()); 31 | System.schedule('Limits Monitor 3', '0 30 * * * ?', new LimitsSnapshotSchedule()); 32 | System.schedule('Limits Monitor 4', '0 45 * * * ?', new LimitsSnapshotSchedule()); 33 | ``` 34 | -------------------------------------------------------------------------------- /force-app/main/default/email/Limit_Monitoring_Templates/Limit_Change_Threshold_Exceeded.email: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The limit for {!relatedTo.Limit__r.Name} has exceeded the threshold set for percent of change between snapshots.
6 |
7 | Previous Value: 8 | 9 |
10 | Current Value: 11 | 12 | 13 |
14 | Limit: 15 | 16 | 17 |
18 | Percent of Limit: 19 | 20 | 21 |
22 | Percent Changed: 23 | 24 | 25 |
26 | Change Threshold: 27 | 28 | 29 |
30 | 31 | 32 |
33 | 34 | The limit for {!relatedTo.Limit__r.Name} has exceeded the threshold set for percent of change between snapshots. 35 | Previous Value: {!TEXT(relatedTo.Limit__r.LastSnapshotValue__c)} 36 | Current Value: {!TEXT(relatedTo.Value__c)} 37 | Limit: {!TEXT(relatedTo.MaximumValue__c)} 38 | Percent of Limit: {!TEXT(relatedTo.PercentOfLimit__c)}% 39 | Percent Changed: {!TEXT(relatedTo.PercentChangedSinceLastSnapshot__c)}% 40 | Change Threshold: {!TEXT(relatedTo.Limit__r.ChangeThreshold__c)}% 41 | 42 |
-------------------------------------------------------------------------------- /force-app/main/default/classes/LimitsUtilTest.cls: -------------------------------------------------------------------------------- 1 | @isTest 2 | public with sharing class LimitsUtilTest { 3 | @isTest 4 | static void testRetrieveLimits() { 5 | Limit__c testLimit = new Limit__c( 6 | Name = 'API', 7 | LimitKey__c = 'DailyApiRequests', 8 | AlertThreshold__c = .8, 9 | ChangeThreshold__c = .2 10 | ); 11 | insert testLimit; 12 | 13 | Test.startTest(); 14 | LimitsUtil.retrieveLimits(); 15 | Test.stopTest(); 16 | 17 | List snapshots = [ 18 | SELECT Id 19 | FROM LimitSnapshot__c 20 | WHERE Limit__c = :testLimit.Id 21 | ]; 22 | System.assert( 23 | !snapshots.isEmpty(), 24 | 'A limits snapshot should have been recorded' 25 | ); 26 | } 27 | 28 | @isTest 29 | static void testRetrieveLimitsError() { 30 | Limit__c testLimit = new Limit__c( 31 | Name = 'API', 32 | LimitKey__c = 'BadLimitName', 33 | AlertThreshold__c = .8, 34 | ChangeThreshold__c = .2 35 | ); 36 | insert testLimit; 37 | 38 | Test.startTest(); 39 | LimitsUtil.retrieveLimits(); 40 | Test.stopTest(); 41 | 42 | testLimit = [ 43 | SELECT Id, Errors__c, (SELECT Id FROM Limit_Snapshots__r) 44 | FROM Limit__c 45 | WHERE Id = :testLimit.Id 46 | LIMIT 1 47 | ]; 48 | System.assert( 49 | testLimit.Limit_Snapshots__r.isEmpty(), 50 | 'No limits snapshots should have been recorded' 51 | ); 52 | System.assert( 53 | testLimit.Errors__c != null, 54 | 'An error should have been added to the limit record' 55 | ); 56 | } 57 | 58 | @isTest 59 | static void testDeleteLimits() { 60 | Limit__c testLimit = new Limit__c( 61 | Name = 'API', 62 | LimitKey__c = 'DailyApiRequests', 63 | AlertThreshold__c = .8, 64 | ChangeThreshold__c = .2, 65 | SnapshotRetentionDays__c = -1 66 | ); 67 | insert testLimit; 68 | LimitsUtil.retrieveLimits(); 69 | 70 | Test.startTest(); 71 | LimitsUtil.deleteLimits(); 72 | Test.stopTest(); 73 | 74 | List snapshots = [SELECT Id FROM LimitSnapshot__c]; 75 | Assert.isTrue( 76 | snapshots.isEmpty(), 77 | 'All limits snapshots should have been deleted: ' + snapshots 78 | ); 79 | } 80 | } -------------------------------------------------------------------------------- /force-app/main/default/reports/LimitsReports/Limit_Snapshot_Trending_ntK.report-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FFFFFF 5 | #FFFFFF 6 | Diagonal 7 | 8 | Average 9 | y 10 | LimitSnapshot__c.PercentOfLimit__c 11 | 12 | Line 13 | false 14 | true 15 | CHILD_CREATED_DATE 16 | CHART_BOTTOM 17 | true 18 | false 19 | false 20 | false 21 | Medium 22 | Auto 23 | #000000 24 | 12 25 | #000000 26 | 18 27 | 28 | 29 | Sum 30 | LimitSnapshot__c.Value__c 31 | 32 | 33 | Sum 34 | LimitSnapshot__c.MaximumValue__c 35 | 36 | 37 | Average 38 | LimitSnapshot__c.PercentOfLimit__c 39 | 40 | Summary 41 | 42 | CHILD_CREATED_DATE 43 | Asc 44 | 45 | Limit Snapshot Trending 46 | 47 | co 48 | 0 49 | 50 | CustomEntityCustomEntity$Limit__c$LimitSnapshot__c 51 | organization 52 | true 53 | false 54 | true 55 | 56 | Limit__c.LastRetrieveTime__c 57 | INTERVAL_LAST90 58 | 59 | 60 | -------------------------------------------------------------------------------- /force-app/main/default/flows/Limit_Snapshot_Update_Limit_s_Last_Value_Fields.flow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | false 5 | When a Limit Snapshot is created, update its parent Limit's "Last Percent of Limit" and "Last Snapshot Value" fields with data from the current snapshot. 6 | Default 7 | Limit Snapshot: Update Limit's "Last Value" Fields {!$Flow.CurrentDateTime} 8 | 9 | 10 | BuilderType 11 | 12 | LightningFlowBuilder 13 | 14 | 15 | 16 | CanvasMode 17 | 18 | AUTO_LAYOUT_CANVAS 19 | 20 | 21 | 22 | OriginBuilderType 23 | 24 | LightningFlowBuilder 25 | 26 | 27 | AutoLaunchedFlow 28 | 29 | Update_Limits_Last_Values 30 | 31 | 176 32 | 323 33 | 34 | LastPercentOfLimit__c 35 | 36 | $Record.PercentOfLimit__c 37 | 38 | 39 | 40 | LastSnapshotValue__c 41 | 42 | $Record.Value__c 43 | 44 | 45 | $Record.Limit__r 46 | 47 | 48 | 50 49 | 0 50 | 51 | Update_Limits_Last_Values 52 | 53 | LimitSnapshot__c 54 | Create 55 | RecordAfterSave 56 | 57 | Active 58 | 1700 59 | 60 | -------------------------------------------------------------------------------- /force-app/main/default/flows/Limit_Snapshot_Set_Percent_Changed_Since_Last_Snapshot.flow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | false 5 | When a Limit Snapshot is inserted, calculate the "Percent Changed Since Last Snapshot" field. 6 | Default 7 | 8 | percentChanged 9 | Number 10 | {!percentOfLimit} - BLANKVALUE({!$Record.Limit__r.LastPercentOfLimit__c}, 0) 11 | 0 12 | 13 | 14 | percentOfLimit 15 | Number 16 | IF( 17 | BLANKVALUE({!$Record.MaximumValue__c}, 0) != 0, 18 | (BLANKVALUE({!$Record.Value__c}, 0) / {!$Record.MaximumValue__c}) * 100, 19 | 0 20 | ) 21 | 2 22 | 23 | Limit Snapshot: Set Percent Changed Since Last Snapshot {!$Flow.CurrentDateTime} 24 | 25 | 26 | BuilderType 27 | 28 | LightningFlowBuilder 29 | 30 | 31 | 32 | CanvasMode 33 | 34 | AUTO_LAYOUT_CANVAS 35 | 36 | 37 | 38 | OriginBuilderType 39 | 40 | LightningFlowBuilder 41 | 42 | 43 | AutoLaunchedFlow 44 | 45 | Calculate_Percent_Changed_Since_Last_Snapshot 46 | 47 | 176 48 | 287 49 | 50 | PercentChangedSinceLastSnapshot__c 51 | 52 | percentChanged 53 | 54 | 55 | $Record 56 | 57 | 58 | 50 59 | 0 60 | 61 | Calculate_Percent_Changed_Since_Last_Snapshot 62 | 63 | LimitSnapshot__c 64 | Create 65 | RecordBeforeSave 66 | 67 | Active 68 | 69 | -------------------------------------------------------------------------------- /force-app/main/default/flows/Limits_Clear_Temporary_Alerts_Threshold.flow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63.0 4 | false 5 | Once a Limit's "Temporary Alert Threshold" expires, clear the Temporary Alert Threshold details. 6 | Default 7 | Limits: Clear Temporary Alerts Threshold {!$Flow.CurrentDateTime} 8 | 9 | 10 | BuilderType 11 | 12 | LightningFlowBuilder 13 | 14 | 15 | 16 | CanvasMode 17 | 18 | AUTO_LAYOUT_CANVAS 19 | 20 | 21 | 22 | OriginBuilderType 23 | 24 | LightningFlowBuilder 25 | 26 | 27 | AutoLaunchedFlow 28 | 29 | Clear_Temporary_Threshold 30 | 31 | 308 32 | 276 33 | 34 | TemporaryAlertThresholdExpiration__c 35 | 36 | 37 | TemporaryAlertThreshold__c 38 | 39 | $Record 40 | 41 | 42 | 50 43 | 0 44 | and 45 | 46 | TemporaryAlertThresholdExpiration__c 47 | IsNull 48 | 49 | false 50 | 51 | 52 | Limit__c 53 | CreateAndUpdate 54 | 55 | Temporary_Threshold_Expires 56 | 57 | Clear_Temporary_Threshold 58 | 59 | 60 | 0 61 | Minutes 62 | TemporaryAlertThresholdExpiration__c 63 | RecordField 64 | 65 | RecordAfterSave 66 | 67 | Active 68 | 69 | -------------------------------------------------------------------------------- /force-app/main/default/layouts/LimitSnapshot__c-Limit Snapshot Layout.layout-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | false 6 | true 7 | 8 | 9 | 10 | Readonly 11 | Name 12 | 13 | 14 | Required 15 | Limit__c 16 | 17 | 18 | Edit 19 | MaximumValue__c 20 | 21 | 22 | Edit 23 | Value__c 24 | 25 | 26 | Readonly 27 | PercentOfLimit__c 28 | 29 | 30 | Edit 31 | PercentChangedSinceLastSnapshot__c 32 | 33 | 34 | Readonly 35 | PastRetentionPeriod__c 36 | 37 | 38 | 39 | 40 | 41 | 42 | false 43 | false 44 | true 45 | 46 | 47 | 48 | Readonly 49 | CreatedById 50 | 51 | 52 | 53 | 54 | Readonly 55 | LastModifiedById 56 | 57 | 58 | 59 | 60 | 61 | false 62 | false 63 | true 64 | 65 | 66 | 67 | 68 | 69 | false 70 | false 71 | false 72 | false 73 | false 74 | 75 | -------------------------------------------------------------------------------- /force-app/main/default/permissionsets/LimitMonitorPermissions.permissionset-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Users with this permission have access to objects in the salesforce-limit-monitor application 4 | 5 | true 6 | LimitSnapshot__c.MaximumValue__c 7 | true 8 | 9 | 10 | true 11 | LimitSnapshot__c.PercentChangedSinceLastSnapshot__c 12 | true 13 | 14 | 15 | true 16 | LimitSnapshot__c.Value__c 17 | true 18 | 19 | 20 | true 21 | Limit__c.Errors__c 22 | true 23 | 24 | 25 | true 26 | Limit__c.LastPercentOfLimit__c 27 | true 28 | 29 | 30 | true 31 | Limit__c.LastSnapshotValue__c 32 | true 33 | 34 | 35 | true 36 | Limit__c.MuteAlerts__c 37 | true 38 | 39 | 40 | true 41 | Limit__c.RetrieveIntervalHours__c 42 | true 43 | 44 | 45 | true 46 | Limit__c.SnapshotRetentionDays__c 47 | true 48 | 49 | 50 | true 51 | Limit__c.TemporaryAlertThresholdExpiration__c 52 | true 53 | 54 | 55 | true 56 | Limit__c.TemporaryAlertThreshold__c 57 | true 58 | 59 | false 60 | 61 | 62 | true 63 | true 64 | true 65 | true 66 | true 67 | LimitSnapshot__c 68 | true 69 | true 70 | 71 | 72 | true 73 | true 74 | true 75 | true 76 | true 77 | Limit__c 78 | true 79 | true 80 | 81 | 82 | Limit__c 83 | Available 84 | 85 | 86 | -------------------------------------------------------------------------------- /force-app/main/default/flexipages/Limit_Snapshot_Record_Page.flexipage-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | actionNames 8 | 9 | 10 | Delete 11 | 12 | 13 | 14 | 15 | collapsed 16 | false 17 | 18 | 19 | enableActionsConfiguration 20 | true 21 | 22 | 23 | enableActionsInNative 24 | true 25 | 26 | 27 | hideChatterActions 28 | false 29 | 30 | 31 | numVisibleActions 32 | 3 33 | 34 | force:highlightsPanel 35 | force_highlightsPanel 36 | 37 | 38 | Replace 39 | header 40 | Region 41 | 42 | 43 | 44 | 45 | force:detailPanel 46 | force_detailPanel 47 | 48 | 49 | Replace 50 | detailTabContent 51 | Facet 52 | 53 | 54 | 55 | 56 | 57 | active 58 | true 59 | 60 | 61 | body 62 | detailTabContent 63 | 64 | 65 | title 66 | Standard.Tab.detail 67 | 68 | flexipage:tab 69 | detailTab 70 | 71 | 72 | Replace 73 | maintabs 74 | Facet 75 | 76 | 77 | 78 | 79 | 80 | label 81 | Tabs 82 | 83 | 84 | tabs 85 | maintabs 86 | 87 | flexipage:tabset 88 | flexipage_tabset 89 | 90 | 91 | Replace 92 | main 93 | Region 94 | 95 | 96 | Replace 97 | sidebar 98 | Region 99 | 100 | Limit Snapshot Record Page 101 | flexipage__default_rec_L 102 | LimitSnapshot__c 103 | 106 | RecordPage 107 | 108 | -------------------------------------------------------------------------------- /force-app/main/default/layouts/Limit__c-Limit Layout.layout-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Submit 4 | 5 | false 6 | false 7 | true 8 | 9 | 10 | 11 | Required 12 | Name 13 | 14 | 15 | Required 16 | AlertThreshold__c 17 | 18 | 19 | Edit 20 | TemporaryAlertThreshold__c 21 | 22 | 23 | Edit 24 | RetrieveIntervalHours__c 25 | 26 | 27 | Edit 28 | MuteAlerts__c 29 | 30 | 31 | Readonly 32 | LastRetrieveTime__c 33 | 34 | 35 | Edit 36 | OwnerId 37 | 38 | 39 | Edit 40 | LastPercentOfLimit__c 41 | 42 | 43 | 44 | 45 | Required 46 | LimitKey__c 47 | 48 | 49 | Required 50 | ChangeThreshold__c 51 | 52 | 53 | Edit 54 | TemporaryAlertThresholdExpiration__c 55 | 56 | 57 | Edit 58 | SnapshotRetentionDays__c 59 | 60 | 61 | Edit 62 | LastSnapshotValue__c 63 | 64 | 65 | Readonly 66 | NextRetrieveTime__c 67 | 68 | 69 | Edit 70 | Errors__c 71 | 72 | 73 | 74 | 75 | 76 | false 77 | false 78 | true 79 | 80 | 81 | 82 | Readonly 83 | CreatedById 84 | 85 | 86 | 87 | 88 | Readonly 89 | LastModifiedById 90 | 91 | 92 | 93 | 94 | 95 | true 96 | false 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | NAME 106 | CREATED_DATE 107 | Value__c 108 | MaximumValue__c 109 | PercentOfLimit__c 110 | LimitSnapshot__c.Limit__c 111 | 112 | false 113 | false 114 | false 115 | false 116 | false 117 | 118 | 00h21000000s1e6 119 | 4 120 | 0 121 | Default 122 | 123 | 124 | -------------------------------------------------------------------------------- /force-app/main/default/objects/Limit__c/Limit__c.object-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Accept 5 | Default 6 | 7 | 8 | Accept 9 | Large 10 | Default 11 | 12 | 13 | Accept 14 | Small 15 | Default 16 | 17 | 18 | CancelEdit 19 | Default 20 | 21 | 22 | CancelEdit 23 | Large 24 | Default 25 | 26 | 27 | CancelEdit 28 | Small 29 | Default 30 | 31 | 32 | Clone 33 | Default 34 | 35 | 36 | Clone 37 | Large 38 | Default 39 | 40 | 41 | Clone 42 | Small 43 | Default 44 | 45 | 46 | Delete 47 | Default 48 | 49 | 50 | Delete 51 | Large 52 | Default 53 | 54 | 55 | Delete 56 | Small 57 | Default 58 | 59 | 60 | Edit 61 | Default 62 | 63 | 64 | Edit 65 | Large 66 | Default 67 | 68 | 69 | Edit 70 | Small 71 | Default 72 | 73 | 74 | List 75 | Default 76 | 77 | 78 | List 79 | Large 80 | Default 81 | 82 | 83 | List 84 | Small 85 | Default 86 | 87 | 88 | New 89 | Default 90 | 91 | 92 | New 93 | Large 94 | Default 95 | 96 | 97 | New 98 | Small 99 | Default 100 | 101 | 102 | SaveEdit 103 | Default 104 | 105 | 106 | SaveEdit 107 | Large 108 | Default 109 | 110 | 111 | SaveEdit 112 | Small 113 | Default 114 | 115 | 116 | Tab 117 | Default 118 | 119 | 120 | Tab 121 | Large 122 | Default 123 | 124 | 125 | Tab 126 | Small 127 | Default 128 | 129 | 130 | View 131 | Action override created by Lightning App Builder during activation. 132 | Limit_Record_Page 133 | Large 134 | false 135 | Flexipage 136 | 137 | 138 | View 139 | Default 140 | 141 | 142 | View 143 | Small 144 | Default 145 | 146 | false 147 | SYSTEM 148 | Deployed 149 | Used to store details about each limit that should be tracked 150 | false 151 | true 152 | false 153 | true 154 | false 155 | true 156 | true 157 | true 158 | true 159 | Private 160 | 161 | 162 | 163 | false 164 | Text 165 | 166 | Limits 167 | 168 | ReadWrite 169 | Public 170 | 171 | -------------------------------------------------------------------------------- /force-app/main/default/objects/LimitSnapshot__c/LimitSnapshot__c.object-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Accept 5 | Default 6 | 7 | 8 | Accept 9 | Large 10 | Default 11 | 12 | 13 | Accept 14 | Small 15 | Default 16 | 17 | 18 | CancelEdit 19 | Default 20 | 21 | 22 | CancelEdit 23 | Large 24 | Default 25 | 26 | 27 | CancelEdit 28 | Small 29 | Default 30 | 31 | 32 | Clone 33 | Default 34 | 35 | 36 | Clone 37 | Large 38 | Default 39 | 40 | 41 | Clone 42 | Small 43 | Default 44 | 45 | 46 | Delete 47 | Default 48 | 49 | 50 | Delete 51 | Large 52 | Default 53 | 54 | 55 | Delete 56 | Small 57 | Default 58 | 59 | 60 | Edit 61 | Default 62 | 63 | 64 | Edit 65 | Large 66 | Default 67 | 68 | 69 | Edit 70 | Small 71 | Default 72 | 73 | 74 | List 75 | Default 76 | 77 | 78 | List 79 | Large 80 | Default 81 | 82 | 83 | List 84 | Small 85 | Default 86 | 87 | 88 | New 89 | Default 90 | 91 | 92 | New 93 | Large 94 | Default 95 | 96 | 97 | New 98 | Small 99 | Default 100 | 101 | 102 | SaveEdit 103 | Default 104 | 105 | 106 | SaveEdit 107 | Large 108 | Default 109 | 110 | 111 | SaveEdit 112 | Small 113 | Default 114 | 115 | 116 | Tab 117 | Default 118 | 119 | 120 | Tab 121 | Large 122 | Default 123 | 124 | 125 | Tab 126 | Small 127 | Default 128 | 129 | 130 | View 131 | Action override created by Lightning App Builder during activation. 132 | Limit_Snapshot_Record_Page 133 | Large 134 | false 135 | Flexipage 136 | 137 | 138 | View 139 | Action override created by Lightning App Builder during activation. 140 | Limit_Snapshot_Record_Page 141 | Small 142 | false 143 | Flexipage 144 | 145 | 146 | View 147 | Default 148 | 149 | false 150 | SYSTEM 151 | Deployed 152 | Snapshots of each limit 153 | false 154 | true 155 | false 156 | false 157 | false 158 | true 159 | false 160 | true 161 | true 162 | ControlledByParent 163 | 164 | 165 | LS-{0000} 166 | 167 | AutoNumber 168 | 169 | Limit Snapshots 170 | 171 | ControlledByParent 172 | Public 173 | 174 | -------------------------------------------------------------------------------- /force-app/main/default/flexipages/Limit_Record_Page.flexipage-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | actionNames 8 | 9 | 10 | Edit 11 | 12 | 13 | Clone 14 | 15 | 16 | Delete 17 | 18 | 19 | 20 | 21 | collapsed 22 | false 23 | 24 | 25 | enableActionsConfiguration 26 | true 27 | 28 | 29 | enableActionsInNative 30 | true 31 | 32 | 33 | hideChatterActions 34 | false 35 | 36 | 37 | numVisibleActions 38 | 3 39 | 40 | force:highlightsPanel 41 | force_highlightsPanel 42 | 43 | 44 | Replace 45 | header 46 | Region 47 | 48 | 49 | 50 | 51 | 52 | relatedListComponentOverride 53 | NONE 54 | 55 | 56 | rowsToDisplay 57 | 10 58 | 59 | 60 | showActionBar 61 | true 62 | 63 | force:relatedListContainer 64 | force_relatedListContainer 65 | 66 | 67 | Replace 68 | relatedTabContent 69 | Facet 70 | 71 | 72 | 73 | 74 | force:detailPanel 75 | force_detailPanel 76 | 77 | 78 | Replace 79 | detailTabContent 80 | Facet 81 | 82 | 83 | 84 | 85 | 86 | body 87 | relatedTabContent 88 | 89 | 90 | title 91 | Standard.Tab.relatedLists 92 | 93 | flexipage:tab 94 | relatedListsTab 95 | 96 | 97 | 98 | 99 | 100 | active 101 | true 102 | 103 | 104 | body 105 | detailTabContent 106 | 107 | 108 | title 109 | Standard.Tab.detail 110 | 111 | flexipage:tab 112 | detailTab 113 | 114 | 115 | Replace 116 | maintabs 117 | Facet 118 | 119 | 120 | 121 | 122 | 123 | label 124 | Tabs 125 | 126 | 127 | tabs 128 | maintabs 129 | 130 | flexipage:tabset 131 | flexipage_tabset 132 | 133 | 134 | Replace 135 | main 136 | Region 137 | 138 | 139 | 140 | 141 | 142 | cacheAge 143 | 1440 144 | 145 | 146 | reportFilter 147 | CUST_ID 148 | 149 | 150 | reportName 151 | Limit_Snapshot_Trending_ntK 152 | 153 | 154 | showRefreshButton 155 | true 156 | 157 | flexipage:reportChart 158 | flexipage_reportChart 159 | 160 | 161 | Replace 162 | sidebar 163 | Region 164 | 165 | Limit Record Page 166 | flexipage__default_rec_L 167 | Limit__c 168 | 171 | RecordPage 172 | 173 | -------------------------------------------------------------------------------- /force-app/main/default/flows/Limit_Snapshot_Notify_if_Percent_Changed_Exceeds_Threshold.flow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Send_Email_Alert_Limit_Change_Threshold_Exceeded 5 | 6 | 176 7 | 755 8 | LimitSnapshot__c.Limit_Change_Threshold_Exceeded 9 | emailAlert 10 | 11 | Catch_Email_Error 12 | 13 | CurrentTransaction 14 | 15 | SObjectRowId 16 | 17 | $Record.Id 18 | 19 | 20 | LimitSnapshot__c.Limit_Change_Threshold_Exceeded 21 | 0 22 | 23 | 24 | Send_Notification 25 | 26 | 176 27 | 647 28 | customNotificationAction 29 | customNotificationAction 30 | 31 | Send_Email_Alert_Limit_Change_Threshold_Exceeded 32 | 33 | 34 | Catch_Notification_Error 35 | 36 | CurrentTransaction 37 | 38 | customNotifTypeId 39 | 40 | notificationType.Id 41 | 42 | 43 | 44 | recipientIds 45 | 46 | recipientIds 47 | 48 | 49 | 50 | title 51 | 52 | notificationTitle 53 | 54 | 55 | 56 | body 57 | 58 | notificationBody 59 | 60 | 61 | 62 | targetId 63 | 64 | $Record.Id 65 | 66 | 67 | customNotificationAction 68 | 0 69 | 70 | 63.0 71 | false 72 | 73 | Explicitly assigns the flow fault message in an variable for inspection 74 | Subscribers might add their own logging logic here instead. 75 | Catch_Email_Error 76 | 77 | 440 78 | 863 79 | 80 | error 81 | Assign 82 | 83 | $Flow.FaultMessage 84 | 85 | 86 | 87 | 88 | Explicitly assigns the flow fault message in an variable for inspection 89 | Subscribers might add their own logging logic here instead. 90 | Catch_Notification_Error 91 | 92 | 704 93 | 755 94 | 95 | error 96 | Assign 97 | 98 | $Flow.FaultMessage 99 | 100 | 101 | 102 | true 103 | Send_Email_Alert_Limit_Change_Threshold_Exceeded 104 | 105 | 106 | 107 | Set_Recipient_Ids 108 | 109 | 176 110 | 539 111 | 112 | recipientIds 113 | Add 114 | 115 | notificationQueue.Id 116 | 117 | 118 | 119 | Send_Notification 120 | 121 | 122 | When a Limit Snapshot's value exceeds the percentage change thresholds defined by its parent Limit record, send a push notification and email alert to all members of the Limit Notification Queue. 123 | Default 124 | Limit Snapshot: Notify if Percent Changed Exceeds Threshold {!$Flow.CurrentDateTime} 125 | 126 | 127 | BuilderType 128 | 129 | LightningFlowBuilder 130 | 131 | 132 | 133 | CanvasMode 134 | 135 | AUTO_LAYOUT_CANVAS 136 | 137 | 138 | 139 | OriginBuilderType 140 | 141 | LightningFlowBuilder 142 | 143 | 144 | AutoLaunchedFlow 145 | 146 | notificationQueue 147 | 148 | 176 149 | 431 150 | false 151 | 152 | Set_Recipient_Ids 153 | 154 | 155 | true 156 | Catch_Notification_Error 157 | 158 | and 159 | 160 | DeveloperName 161 | EqualTo 162 | 163 | Limit_Notification_Queue 164 | 165 | 166 | 167 | Type 168 | EqualTo 169 | 170 | Queue 171 | 172 | 173 | true 174 | Group 175 | Id 176 | Desc 177 | true 178 | 179 | 180 | notificationType 181 | 182 | 176 183 | 323 184 | false 185 | 186 | notificationQueue 187 | 188 | 189 | true 190 | Catch_Notification_Error 191 | 192 | and 193 | 194 | DeveloperName 195 | EqualTo 196 | 197 | Limit_Alert 198 | 199 | 200 | true 201 | CustomNotificationType 202 | Id 203 | Desc 204 | true 205 | 206 | 207 | 50 208 | 0 209 | 210 | notificationType 211 | 212 | AND( 213 | NOT({!$Record.Limit__r.MuteAlerts__c}), 214 | NOT(ISBLANK({!$Record.Limit__r.LastPercentOfLimit__c})), 215 | BLANKVALUE({!$Record.PercentChangedSinceLastSnapshot__c}, 0) >= BLANKVALUE({!$Record.Limit__r.ChangeThreshold__c}, 0) 216 | ) 217 | LimitSnapshot__c 218 | Create 219 | RecordAfterSave 220 | 221 | Active 222 | 223 | notificationBody 224 | true 225 | The limit for {!$Record.Limit__r.Name} has exceeded the threshold set for percent of change between snapshots. 226 | 227 | Current Value: {!$Record.Value__c} 228 | Previous Value: {!$Record.Limit__r.LastSnapshotValue__c} 229 | Limit: {!$Record.MaximumValue__c} 230 | Percent Changed: {!$Record.PercentChangedSinceLastSnapshot__c}% 231 | Change Threshold: {!$Record.Limit__r.ChangeThreshold__c}% 232 | 233 | 234 | notificationTitle 235 | true 236 | Alert for Limit {!$Record.Limit__r.Name} 237 | 238 | 1500 239 | 240 | error 241 | String 242 | false 243 | false 244 | false 245 | 246 | 247 | recipientIds 248 | String 249 | true 250 | false 251 | false 252 | 253 | 254 | -------------------------------------------------------------------------------- /force-app/main/default/flows/Limit_Snapshot_Notify_if_Percent_of_Limit_Exceeds_Threshold.flow-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Send_Email_Alert_Limit_Value_Threshold_Exceeded 5 | 6 | 176 7 | 755 8 | LimitSnapshot__c.Limit_Value_Threshold_Exceeded 9 | emailAlert 10 | 11 | Catch_Email_Error 12 | 13 | CurrentTransaction 14 | 15 | SObjectRowId 16 | 17 | $Record.Id 18 | 19 | 20 | LimitSnapshot__c.Limit_Value_Threshold_Exceeded 21 | 0 22 | 23 | 24 | Send_Notification 25 | 26 | 176 27 | 647 28 | customNotificationAction 29 | customNotificationAction 30 | 31 | Send_Email_Alert_Limit_Value_Threshold_Exceeded 32 | 33 | 34 | Catch_Notification_Error 35 | 36 | CurrentTransaction 37 | 38 | customNotifTypeId 39 | 40 | notificationType.Id 41 | 42 | 43 | 44 | recipientIds 45 | 46 | recipientIds 47 | 48 | 49 | 50 | title 51 | 52 | notificationTitle 53 | 54 | 55 | 56 | body 57 | 58 | notificationBody 59 | 60 | 61 | 62 | targetId 63 | 64 | $Record.Id 65 | 66 | 67 | customNotificationAction 68 | 0 69 | 70 | 63.0 71 | false 72 | 73 | Explicitly assigns the flow fault message in an variable for inspection 74 | Subscribers might add their own logging logic here instead. 75 | Catch_Email_Error 76 | 77 | 440 78 | 863 79 | 80 | error 81 | Assign 82 | 83 | $Flow.FaultMessage 84 | 85 | 86 | 87 | 88 | Explicitly assigns the flow fault message in an variable for inspection 89 | Subscribers might add their own logging logic here instead. 90 | Catch_Notification_Error 91 | 92 | 704 93 | 755 94 | 95 | error 96 | Assign 97 | 98 | $Flow.FaultMessage 99 | 100 | 101 | 102 | true 103 | Send_Email_Alert_Limit_Value_Threshold_Exceeded 104 | 105 | 106 | 107 | Set_Recipient_Ids 108 | 109 | 176 110 | 539 111 | 112 | recipientIds 113 | Add 114 | 115 | notificationQueue.Id 116 | 117 | 118 | 119 | Send_Notification 120 | 121 | 122 | When a Limit Snapshot's value exceeds the raw thresholds defined by its parent Limit record, send a push notification and email alert to all members of the Limit Notification Queue. 123 | Default 124 | Limit Snapshot: Notify if Percent of Limit Exceeds Threshold {!$Flow.CurrentDateTime} 125 | 126 | 127 | BuilderType 128 | 129 | LightningFlowBuilder 130 | 131 | 132 | 133 | CanvasMode 134 | 135 | AUTO_LAYOUT_CANVAS 136 | 137 | 138 | 139 | OriginBuilderType 140 | 141 | LightningFlowBuilder 142 | 143 | 144 | AutoLaunchedFlow 145 | 146 | notificationQueue 147 | 148 | 176 149 | 431 150 | false 151 | 152 | Set_Recipient_Ids 153 | 154 | 155 | true 156 | Catch_Notification_Error 157 | 158 | and 159 | 160 | DeveloperName 161 | EqualTo 162 | 163 | Limit_Notification_Queue 164 | 165 | 166 | 167 | Type 168 | EqualTo 169 | 170 | Queue 171 | 172 | 173 | true 174 | Group 175 | Id 176 | Desc 177 | true 178 | 179 | 180 | notificationType 181 | 182 | 176 183 | 323 184 | false 185 | 186 | notificationQueue 187 | 188 | 189 | true 190 | Catch_Notification_Error 191 | 192 | and 193 | 194 | DeveloperName 195 | EqualTo 196 | 197 | Limit_Alert 198 | 199 | 200 | true 201 | CustomNotificationType 202 | Id 203 | Desc 204 | true 205 | 206 | 207 | 50 208 | 0 209 | 210 | notificationType 211 | 212 | AND( 213 | NOT({!$Record.Limit__r.MuteAlerts__c}), 214 | BLANKVALUE({!$Record.PercentOfLimit__c}, 0) >= BLANKVALUE({!$Record.Limit__r.TemporaryAlertThreshold__c}, BLANKVALUE({!$Record.Limit__r.AlertThreshold__c}, 0)) 215 | ) 216 | LimitSnapshot__c 217 | Create 218 | RecordAfterSave 219 | 220 | Active 221 | 222 | notificationBody 223 | true 224 | The limit for {!$Record.Limit__r.Name} has exceeded the threshold set. 225 | 226 | Current Value: {!$Record.Value__c} 227 | Limit: {!$Record.MaximumValue__c} 228 | Percent of Limit: {!$Record.PercentOfLimit__c}% 229 | Alert Threshold: {!$Record.Limit__r.AlertThreshold__c} 230 | Current Value: {!$Record.Value__c} 231 | Previous Value: {!$Record.Limit__r.LastSnapshotValue__c} 232 | Limit: {!$Record.MaximumValue__c} 233 | Percent Changed: {!$Record.PercentChangedSinceLastSnapshot__c}% 234 | Change Threshold: {!$Record.Limit__r.ChangeThreshold__c}% 235 | 236 | 237 | notificationTitle 238 | true 239 | Alert for Limit {!$Record.Limit__r.Name} 240 | 241 | 500 242 | 243 | error 244 | String 245 | false 246 | false 247 | false 248 | 249 | 250 | recipientIds 251 | String 252 | true 253 | false 254 | false 255 | 256 | 257 | --------------------------------------------------------------------------------