From 1c476219cac1c3863ab68c13395dd0c545e95971 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:18:53 +0000 Subject: [PATCH 01/56] Setting up GitHub Classroom Feedback From 8ba6efa38fbdf59e50706461d0fb6f835f822cce Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Thu, 10 Oct 2024 19:51:29 -0400 Subject: [PATCH 02/56] Blank Template --- .forceignore | 12 ++++++ .gitignore | 45 ++++++++++++++++++++++ .husky/pre-commit | 4 ++ .prettierignore | 11 ++++++ .prettierrc | 17 ++++++++ .vscode/extensions.json | 9 +++++ .vscode/launch.json | 16 ++++++++ .vscode/settings.json | 7 ++++ README.md | 18 +++++++++ config/project-scratch-def.json | 13 +++++++ force-app/main/default/aura/.eslintrc.json | 8 ++++ force-app/main/default/lwc/.eslintrc.json | 14 +++++++ jest.config.js | 6 +++ package.json | 41 ++++++++++++++++++++ scripts/apex/hello.apex | 10 +++++ scripts/soql/account.soql | 6 +++ sfdx-project.json | 12 ++++++ 17 files changed, 249 insertions(+) create mode 100644 .forceignore create mode 100644 .gitignore create mode 100644 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 config/project-scratch-def.json create mode 100644 force-app/main/default/aura/.eslintrc.json create mode 100644 force-app/main/default/lwc/.eslintrc.json create mode 100644 jest.config.js create mode 100644 package.json create mode 100644 scripts/apex/hello.apex create mode 100644 scripts/soql/account.soql create mode 100644 sfdx-project.json diff --git a/.forceignore b/.forceignore new file mode 100644 index 0000000..7b5b5a7 --- /dev/null +++ b/.forceignore @@ -0,0 +1,12 @@ +# List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status +# More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm +# + +package.xml + +# LWC configuration files +**/jsconfig.json +**/.eslintrc.json + +# LWC Jest +**/__tests__/** \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f5f33eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# This file is used for Git repositories to specify intentionally untracked files that Git should ignore. +# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore +# For useful gitignore templates see: https://github.com/github/gitignore + +# Salesforce cache +.sf/ +.sfdx/ +.localdevserver/ +deploy-options.json + +# LWC VSCode autocomplete +**/lwc/jsconfig.json + +# LWC Jest coverage reports +coverage/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Dependency directories +node_modules/ + +# Eslint cache +.eslintcache + +# MacOS system files +.DS_Store + +# Windows system files +Thumbs.db +ehthumbs.db +[Dd]esktop.ini +$RECYCLE.BIN/ + +# Local environment variables +.env + +# Python Salesforce Functions +**/__pycache__/ +**/.venv/ +**/venv/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..feac116 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run precommit \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..8cccc6e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +# List files or directories below to ignore them when running prettier +# More information: https://prettier.io/docs/en/ignore.html +# + +**/staticresources/** +.localdevserver +.sfdx +.sf +.vscode + +coverage/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..18039a0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,17 @@ +{ + "trailingComma": "none", + "plugins": [ + "prettier-plugin-apex", + "@prettier/plugin-xml" + ], + "overrides": [ + { + "files": "**/lwc/**/*.html", + "options": { "parser": "lwc" } + }, + { + "files": "*.{cmp,page,component}", + "options": { "parser": "html" } + } + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7e6cb10 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "salesforce.salesforcedx-vscode", + "redhat.vscode-xml", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "financialforce.lana" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e07e391 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Apex Replay Debugger", + "type": "apex-replay", + "request": "launch", + "logFile": "${command:AskForLogFileName}", + "stopOnEntry": true, + "trace": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..76decfb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/.sfdx": true + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..afcda4a --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Salesforce DX Project: Next Steps + +Now that you’ve created a Salesforce DX project, what’s next? Here are some documentation resources to get you started. + +## How Do You Plan to Deploy Your Changes? + +Do you want to deploy a set of changes, or create a self-contained application? Choose a [development model](https://developer.salesforce.com/tools/vscode/en/user-guide/development-models). + +## Configure Your Salesforce DX Project + +The `sfdx-project.json` file contains useful configuration information for your project. See [Salesforce DX Project Configuration](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_config.htm) in the _Salesforce DX Developer Guide_ for details about this file. + +## Read All About It + +- [Salesforce Extensions Documentation](https://developer.salesforce.com/tools/vscode/) +- [Salesforce CLI Setup Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_intro.htm) +- [Salesforce DX Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro.htm) +- [Salesforce CLI Command Reference](https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference.htm) diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json new file mode 100644 index 0000000..bb72192 --- /dev/null +++ b/config/project-scratch-def.json @@ -0,0 +1,13 @@ +{ + "orgName": "Demo company", + "edition": "Developer", + "features": ["EnableSetPasswordInApi"], + "settings": { + "lightningExperienceSettings": { + "enableS1DesktopEnabled": true + }, + "mobileSettings": { + "enableS1EncryptedStoragePref2": false + } + } +} diff --git a/force-app/main/default/aura/.eslintrc.json b/force-app/main/default/aura/.eslintrc.json new file mode 100644 index 0000000..226a5a2 --- /dev/null +++ b/force-app/main/default/aura/.eslintrc.json @@ -0,0 +1,8 @@ +{ + "plugins": ["@salesforce/eslint-plugin-aura"], + "extends": ["plugin:@salesforce/eslint-plugin-aura/recommended"], + "rules": { + "vars-on-top": "off", + "no-unused-expressions": "off" + } +} diff --git a/force-app/main/default/lwc/.eslintrc.json b/force-app/main/default/lwc/.eslintrc.json new file mode 100644 index 0000000..a82e76d --- /dev/null +++ b/force-app/main/default/lwc/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "extends": ["@salesforce/eslint-config-lwc/recommended"], + "overrides": [ + { + "files": ["*.test.js"], + "rules": { + "@lwc/lwc/no-unexpected-wire-adapter-usages": "off" + }, + "env": { + "node": true + } + } + ] +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..f5a9fed --- /dev/null +++ b/jest.config.js @@ -0,0 +1,6 @@ +const { jestConfig } = require('@salesforce/sfdx-lwc-jest/config'); + +module.exports = { + ...jestConfig, + modulePathIgnorePatterns: ['/.localdevserver'] +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e36ff2b --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "salesforce-app", + "private": true, + "version": "1.0.0", + "description": "Salesforce App", + "scripts": { + "lint": "eslint **/{aura,lwc}/**/*.js", + "test": "npm run test:unit", + "test:unit": "sfdx-lwc-jest", + "test:unit:watch": "sfdx-lwc-jest --watch", + "test:unit:debug": "sfdx-lwc-jest --debug", + "test:unit:coverage": "sfdx-lwc-jest --coverage", + "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "postinstall": "husky install", + "precommit": "lint-staged" + }, + "devDependencies": { + "@lwc/eslint-plugin-lwc": "^1.1.2", + "@prettier/plugin-xml": "^3.2.2", + "@salesforce/eslint-config-lwc": "^3.2.3", + "@salesforce/eslint-plugin-aura": "^2.0.0", + "@salesforce/eslint-plugin-lightning": "^1.0.0", + "@salesforce/sfdx-lwc-jest": "^5.1.0", + "eslint": "^9.9.1", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^28.8.1", + "husky": "^9.1.5", + "lint-staged": "^15.1.0", + "prettier": "^3.1.0", + "prettier-plugin-apex": "^2.0.1" + }, + "lint-staged": { + "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ + "prettier --write" + ], + "**/{aura,lwc}/**/*.js": [ + "eslint" + ] + } +} diff --git a/scripts/apex/hello.apex b/scripts/apex/hello.apex new file mode 100644 index 0000000..1fba732 --- /dev/null +++ b/scripts/apex/hello.apex @@ -0,0 +1,10 @@ +// Use .apex files to store anonymous Apex. +// You can execute anonymous Apex in VS Code by selecting the +// apex text and running the command: +// SFDX: Execute Anonymous Apex with Currently Selected Text +// You can also execute the entire file by running the command: +// SFDX: Execute Anonymous Apex with Editor Contents + +string tempvar = 'Enter_your_name_here'; +System.debug('Hello World!'); +System.debug('My name is ' + tempvar); \ No newline at end of file diff --git a/scripts/soql/account.soql b/scripts/soql/account.soql new file mode 100644 index 0000000..10d4b9c --- /dev/null +++ b/scripts/soql/account.soql @@ -0,0 +1,6 @@ +// Use .soql files to store SOQL queries. +// You can execute queries in VS Code by selecting the +// query text and running the command: +// SFDX: Execute SOQL Query with Currently Selected Text + +SELECT Id, Name FROM Account diff --git a/sfdx-project.json b/sfdx-project.json new file mode 100644 index 0000000..e29a7d5 --- /dev/null +++ b/sfdx-project.json @@ -0,0 +1,12 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "name": "job-application-tracker-oldv2-apex-innovators", + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "62.0" +} From e5e3676c970b6ef5657cf1db433cf4270ea1f523 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Fri, 11 Oct 2024 09:19:34 -0400 Subject: [PATCH 03/56] org package.xml update --- .../Job_Application__c.object-meta.xml | 166 +++++++++++ manifest/package.xml | 262 ++++++++++++++++++ sfdx-project.json | 2 +- 3 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml create mode 100644 manifest/package.xml diff --git a/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml new file mode 100644 index 0000000..4dee391 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml @@ -0,0 +1,166 @@ + + + + Accept + Default + + + Accept + Large + Default + + + Accept + Small + Default + + + CancelEdit + Default + + + CancelEdit + Large + Default + + + CancelEdit + Small + Default + + + Clone + Default + + + Clone + Large + Default + + + Clone + Small + Default + + + Delete + Default + + + Delete + Large + Default + + + Delete + Small + Default + + + Edit + Default + + + Edit + Large + Default + + + Edit + Small + Default + + + List + Default + + + List + Large + Default + + + List + Small + Default + + + New + Default + + + New + Large + Default + + + New + Small + Default + + + SaveEdit + Default + + + SaveEdit + Large + Default + + + SaveEdit + Small + Default + + + Tab + Default + + + Tab + Large + Default + + + Tab + Small + Default + + + View + Default + + + View + Large + Default + + + View + Small + Default + + true + SYSTEM + Deployed + true + true + false + true + false + true + true + true + true + Private + + + + false + Text + + Job Applications + + ReadWrite + Public + diff --git a/manifest/package.xml b/manifest/package.xml new file mode 100644 index 0000000..ca42557 --- /dev/null +++ b/manifest/package.xml @@ -0,0 +1,262 @@ + + + + Account + AccountCleanInfo + AccountContactRole + Activity + Address + AlternativePaymentMethod + ApiAnomalyEventStore + AppointmentCategory + AppointmentInvitation + AppointmentInvitee + AppointmentScheduleLog + AppointmentTopicTimeSlot + Asset + AssetAction + AssetActionSource + AssetRelationship + AssetStatePeriod + AssignedResource + AssistantProgress + AssociatedLocation + AuthorizationForm + AuthorizationFormConsent + AuthorizationFormDataUse + AuthorizationFormText + BusinessBrand + BuyerGroup + Campaign + CampaignMember + CardPaymentMethod + CartCheckoutSession + CartDeliveryGroup + CartDeliveryGroupMethod + CartItem + CartItemPriceAdjustment + CartRelatedItem + CartTax + CartValidationOutput + Case + CaseContactRole + CaseMilestone + CaseRelatedIssue + ChangeRequest + ChangeRequestRelatedIssue + ChangeRequestRelatedItem + ChatterActivity + CollaborationGroup + CollaborationGroupMember + CommSubscription + CommSubscriptionChannelType + CommSubscriptionConsent + CommSubscriptionTiming + ConsumptionRate + ConsumptionSchedule + Contact + ContactCleanInfo + ContactPointAddress + ContactPointConsent + ContactPointEmail + ContactPointPhone + ContactPointTypeConsent + ContactRequest + ContentVersion + Contract + ContractContactRole + ContractLineItem + Coupon + CouponCodeRedemption + CredentialStuffingEventStore + CreditMemo + CreditMemoInvApplication + CreditMemoLine + Customer + DandBCompany + DataKitDeploymentLog + DataUseLegalBasis + DataUsePurpose + DigitalWallet + DuplicateRecordItem + DuplicateRecordSet + EmailMessage + EngagementChannelType + EngagementChannelWorkType + Entitlement + EntitlementContact + EntityMilestone + Event + ExchangeUserMapping + ExpressionFilter + ExpressionFilterCriteria + ExternalEventMapping + FeedItem + FinanceBalanceSnapshot + FinanceTransaction + FlowOrchestrationInstance + FlowOrchestrationStageInstance + FlowOrchestrationStepInstance + FlowOrchestrationWorkItem + FulfillmentOrder + FulfillmentOrderItemAdjustment + FulfillmentOrderItemTax + FulfillmentOrderLineItem + GuestUserAnomalyEventStore + Idea + Image + Incident + IncidentRelatedItem + Individual + InventoryItemReservation + InventoryReservation + Invoice + InvoiceLine + Job_Application__c + Lead + LeadCleanInfo + LearningAssignment + LearningAssignmentProgress + LearningItem + LearningLinkProgress + LegalEntity + Location + LocationGroup + LocationGroupAssignment + MLModel + MLModelFactor + MLModelFactorComponent + Macro + MacroAction + MacroInstruction + MacroUsage + MessagingEndUser + MessagingSession + OperatingHours + OperatingHoursHoliday + Opportunity + OpportunityCompetitor + OpportunityContactRole + OpportunityLineItem + OpportunityRelatedDeleteLog + Order + OrderItem + OrgDeleteRequest + OrgMetricScanResult + OrgMetricScanSummary + PartnerRole + PartyConsent + Payment + PaymentAuthAdjustment + PaymentAuthorization + PaymentGateway + PaymentGroup + PaymentLineInvoice + PaymentMethod + Pricebook2 + PricebookEntry + PrivacyJobSession + PrivacyPolicy + PrivacyRTBFRequest + Problem + ProblemIncident + ProblemRelatedItem + ProcessException + Product2 + ProductAttribute + ProductAttributeSetProduct + ProductCatalog + ProductCategory + ProductCategoryProduct + ProductConsumptionSchedule + Promotion + PromotionLineItemRule + PromotionMarketSegment + PromotionQualifier + PromotionSegment + PromotionSegmentBuyerGroup + PromotionSegmentSalesStore + PromotionTarget + PromotionTier + PromptAction + PromptError + QuickText + QuickTextUsage + Recommendation + RecordAction + RecordMergeHistory + Refund + RefundLinePayment + ReportAnomalyEventStore + ResourceAbsence + ResourcePreference + ReturnOrder + ReturnOrderItemAdjustment + ReturnOrderItemTax + ReturnOrderLineItem + SalesStore + Scorecard + ScorecardAssociation + ScorecardMetric + Seller + ServiceAppointment + ServiceAppointmentAttendee + ServiceContract + ServiceResource + ServiceResourceSkill + ServiceTerritory + ServiceTerritoryMember + ServiceTerritoryWorkType + SessionHijackingEventStore + Shift + ShiftEngagementChannel + ShiftWorkTopic + Shipment + ShipmentItem + ShippingCarrier + ShippingCarrierMethod + ShippingConfigurationSet + ShippingRateArea + ShippingRateGroup + Site + SkillRequirement + SocialPersona + Solution + StandardShippingRate + StreamActivityAccess + StreamingChannel + TableauHostMapping + Task + TimeSlot + Topic + TopicAssignment + User + UserExternalCredential + UserPrioritizedRecord + UserProvisioningRequest + VoiceCall + Waitlist + WaitlistParticipant + WaitlistServiceResource + WaitlistWorkType + WebCart + WebCartAdjustmentBasis + WebCartAdjustmentGroup + WebStore + WebStoreBuyerGroup + WebStoreCatalog + WebStoreInventorySource + WorkOrder + WorkOrderLineItem + WorkPlan + WorkPlanTemplate + WorkPlanTemplateEntry + WorkStep + WorkStepTemplate + WorkType + WorkTypeGroup + WorkTypeGroupMember + CustomObject + + 60.0 + \ No newline at end of file diff --git a/sfdx-project.json b/sfdx-project.json index e29a7d5..9cacf28 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,5 +8,5 @@ "name": "job-application-tracker-oldv2-apex-innovators", "namespace": "", "sfdcLoginUrl": "https://login.salesforce.com", - "sourceApiVersion": "62.0" + "sourceApiVersion": "58.0" } From 14481e0c8065e3bd39918943561cd2a4266180b4 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Fri, 11 Oct 2024 10:56:07 -0400 Subject: [PATCH 04/56] removed package.xml file from .forceignore --- .forceignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.forceignore b/.forceignore index 7b5b5a7..c267c60 100644 --- a/.forceignore +++ b/.forceignore @@ -2,7 +2,6 @@ # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm # -package.xml # LWC configuration files **/jsconfig.json From 204d51651593f60abf984f1129fd2a5111db9547 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Fri, 11 Oct 2024 11:13:41 -0400 Subject: [PATCH 05/56] file for job app custom object --- .../Job_Application__c/Job_Application__c.object-meta.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml index 4dee391..d298169 100644 --- a/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml +++ b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml @@ -1,5 +1,5 @@ - + Accept Default From 9bd634c3210314bf9ae79c8f7bcd69e84bbee760 Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Fri, 11 Oct 2024 16:36:48 -0400 Subject: [PATCH 06/56] Added updated api version for .json file, added JobApplicationHelper, TriggerHandler, and JobApplicationTrigger --- .../default/classes/JobApplicationHelper.cls | 5 + .../classes/JobApplicationHelper.cls-meta.xml | 5 + .../classes/JobApplicationTriggerHandler.cls | 13 + .../JobApplicationTriggerHandler.cls-meta.xml | 5 + .../main/default/classes/TriggerHandler.cls | 269 ++++++++++++++++++ .../classes/TriggerHandler.cls-meta.xml | 5 + .../triggers/JobApplicationTrigger.trigger | 3 + .../JobApplicationTrigger.trigger-meta.xml | 5 + sfdx-project.json | 2 +- 9 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 force-app/main/default/classes/JobApplicationHelper.cls create mode 100644 force-app/main/default/classes/JobApplicationHelper.cls-meta.xml create mode 100644 force-app/main/default/classes/JobApplicationTriggerHandler.cls create mode 100644 force-app/main/default/classes/JobApplicationTriggerHandler.cls-meta.xml create mode 100644 force-app/main/default/classes/TriggerHandler.cls create mode 100644 force-app/main/default/classes/TriggerHandler.cls-meta.xml create mode 100644 force-app/main/default/triggers/JobApplicationTrigger.trigger create mode 100644 force-app/main/default/triggers/JobApplicationTrigger.trigger-meta.xml diff --git a/force-app/main/default/classes/JobApplicationHelper.cls b/force-app/main/default/classes/JobApplicationHelper.cls new file mode 100644 index 0000000..dc777e3 --- /dev/null +++ b/force-app/main/default/classes/JobApplicationHelper.cls @@ -0,0 +1,5 @@ +public with sharing class JobApplicationHelper { + public JobApplicationHelper() { + + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/JobApplicationHelper.cls-meta.xml b/force-app/main/default/classes/JobApplicationHelper.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/JobApplicationHelper.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls new file mode 100644 index 0000000..8d4e8f5 --- /dev/null +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -0,0 +1,13 @@ +public with sharing class JobApplicationTriggerHandler extends TriggerHandler { + private List newJobAppList; + private Map newJobAppMap; + private List oldJobAppList; + private Map oldJobAppMap; + + public JobApplicationTriggerHandler() { + this.newJobAppList = (List) Trigger.new; + this.newJobAppMap = (Map) Trigger.newMap; + this.oldJobAppList = (List) Trigger.old; + this.oldJobAppMap = (Map) Trigger.oldMap; + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls-meta.xml b/force-app/main/default/classes/JobApplicationTriggerHandler.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/classes/TriggerHandler.cls b/force-app/main/default/classes/TriggerHandler.cls new file mode 100644 index 0000000..32e5619 --- /dev/null +++ b/force-app/main/default/classes/TriggerHandler.cls @@ -0,0 +1,269 @@ +/* + * This is a general-purpose Trigger Framework designed to handle various trigger contexts like + * before insert, after insert, before update, etc. + * This framework provides a structured way to handle these operations and is designed to be + * extensible, so developers can add more functionalities as needed. + * + * IMPORTANT: This file is a foundational piece of code. It should NOT be edited directly. + * Instead, extend this class to add more specific trigger functionalities. + * + * Once the framework on your local machine, save and deploy this file into your Salesforce org. + * + * Source: https://github.com/kevinohara80/sfdc-trigger-framework/tree/master + */ +public virtual class TriggerHandler { + + // Keeps track of how many times the run() method was invoked for each handler + private static Map loopCountMap; + + // List of handler names that should not be executed + private static Set bypassedHandlers; + + // Represents the current context in which the trigger is executing (e.g., before insert, after update, etc.) + @TestVisible + private TriggerContext context; + + // Indicates if the trigger is currently executing + @TestVisible + private Boolean isTriggerExecuting; + + // Initialization of static variables + static { + loopCountMap = new Map(); + bypassedHandlers = new Set(); + } + + // Constructor initializes the trigger context + public TriggerHandler() { + this.setTriggerContext(); + } + + /*************************************** + * public instance methods + ***************************************/ + + // Main method that handles the trigger execution + public void run() { + + + // Check if the trigger should continue execution + if(!validateRun()) { + return; + } + + // Increment the count of how many times this handler has run + addToLoopCount(); + + // Dispatch execution to the appropriate handler method based on the trigger context + switch on this.context { + when BEFORE_INSERT { + this.beforeInsert(); + } + when BEFORE_UPDATE { + this.beforeUpdate(); + } + when BEFORE_DELETE { + this.beforeDelete(); + } + when AFTER_INSERT { + this.afterInsert(); + } + when AFTER_UPDATE { + this.afterUpdate(); + } + when AFTER_DELETE { + this.afterDelete(); + } + when AFTER_UNDELETE { + this.afterUndelete(); + } + } + } + + // Set the maximum number of times the handler can run + public void setMaxLoopCount(Integer max) { + String handlerName = getHandlerName(); + if(!TriggerHandler.loopCountMap.containsKey(handlerName)) { + TriggerHandler.loopCountMap.put(handlerName, new LoopCount(max)); + } else { + TriggerHandler.loopCountMap.get(handlerName).setMax(max); + } + } + + // Clear the maximum loop count for the handler + public void clearMaxLoopCount() { + this.setMaxLoopCount(-1); + } + + /*************************************** + * public static methods + ***************************************/ + + // Bypass a particular handler from execution + public static void bypass(String handlerName) { + TriggerHandler.bypassedHandlers.add(handlerName); + } + + // Allow a previously bypassed handler to execute + public static void clearBypass(String handlerName) { + TriggerHandler.bypassedHandlers.remove(handlerName); + } + + // Check if a handler is bypassed + public static Boolean isBypassed(String handlerName) { + return TriggerHandler.bypassedHandlers.contains(handlerName); + } + + // Clear all bypassed handlers + public static void clearAllBypasses() { + TriggerHandler.bypassedHandlers.clear(); + } + + /*************************************** + * private instancemethods + ***************************************/ + + // Set the trigger's execution context + @TestVisible + private void setTriggerContext() { + this.setTriggerContext(null, false); + } + + // Detailed method to determine and set the trigger's execution context + @TestVisible + private void setTriggerContext(String ctx, Boolean testMode) { + if(!Trigger.isExecuting && !testMode) { + this.isTriggerExecuting = false; + return; + } else { + this.isTriggerExecuting = true; + } + + if((Trigger.isExecuting && Trigger.isBefore && Trigger.isInsert) || + (ctx != null && ctx == 'before insert')) { + this.context = TriggerContext.BEFORE_INSERT; + } else if((Trigger.isExecuting && Trigger.isBefore && Trigger.isUpdate) || + (ctx != null && ctx == 'before update')){ + this.context = TriggerContext.BEFORE_UPDATE; + } else if((Trigger.isExecuting && Trigger.isBefore && Trigger.isDelete) || + (ctx != null && ctx == 'before delete')) { + this.context = TriggerContext.BEFORE_DELETE; + } else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isInsert) || + (ctx != null && ctx == 'after insert')) { + this.context = TriggerContext.AFTER_INSERT; + } else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isUpdate) || + (ctx != null && ctx == 'after update')) { + this.context = TriggerContext.AFTER_UPDATE; + } else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isDelete) || + (ctx != null && ctx == 'after delete')) { + this.context = TriggerContext.AFTER_DELETE; + } else if((Trigger.isExecuting && Trigger.isAfter && Trigger.isUndelete) || + (ctx != null && ctx == 'after undelete')) { + this.context = TriggerContext.AFTER_UNDELETE; + } + } + + // Increment how many times the handler has been run + @TestVisible + private void addToLoopCount() { + String handlerName = getHandlerName(); + if(TriggerHandler.loopCountMap.containsKey(handlerName)) { + Boolean exceeded = TriggerHandler.loopCountMap.get(handlerName).increment(); + if(exceeded) { + Integer max = TriggerHandler.loopCountMap.get(handlerName).max; + throw new TriggerHandlerException('Maximum loop count of ' + String.valueOf(max) + ' reached in ' + handlerName); + } + } + } + + // Verify that the trigger should execute + @TestVisible + private Boolean validateRun() { + if(!this.isTriggerExecuting || this.context == null) { + throw new TriggerHandlerException('Trigger handler called outside of Trigger execution'); + } + return !TriggerHandler.bypassedHandlers.contains(getHandlerName()); + } + + // Get the name of the handler that's currently executing + @TestVisible + private String getHandlerName() { + return String.valueOf(this).substring(0,String.valueOf(this).indexOf(':')); + } + + /*************************************** + * context methods + ***************************************/ + + // These are virtual methods that can be overridden in child classes + // to provide specific functionalities for different trigger contexts. + @TestVisible + protected virtual void beforeInsert(){} + @TestVisible + protected virtual void beforeUpdate(){} + @TestVisible + protected virtual void beforeDelete(){} + @TestVisible + protected virtual void afterInsert(){} + @TestVisible + protected virtual void afterUpdate(){} + @TestVisible + protected virtual void afterDelete(){} + @TestVisible + protected virtual void afterUndelete(){} + + /*************************************** + * inner classes + ***************************************/ + + // LoopCount manages how many times a handler is allowed to run. + // This is to prevent infinite loops or excessive operations that could hit governor limits. + @TestVisible + private class LoopCount { + private Integer max; + private Integer count; + + public LoopCount() { + this.max = 5; + this.count = 0; + } + + public LoopCount(Integer max) { + this.max = max; + this.count = 0; + } + + public Boolean increment() { + this.count++; + return this.exceeded(); + } + + public Boolean exceeded() { + return this.max >= 0 && this.count > this.max; + } + + public Integer getMax() { + return this.max; + } + + public Integer getCount() { + return this.count; + } + + public void setMax(Integer max) { + this.max = max; + } + } + + // This enum represents possible trigger contexts, making it easier to identify the current operation. + @TestVisible + private enum TriggerContext { + BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE, + AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, + AFTER_UNDELETE + } + + // Custom exception to handle specific errors related to the trigger handler. + public class TriggerHandlerException extends Exception {} + + } \ No newline at end of file diff --git a/force-app/main/default/classes/TriggerHandler.cls-meta.xml b/force-app/main/default/classes/TriggerHandler.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/TriggerHandler.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/triggers/JobApplicationTrigger.trigger b/force-app/main/default/triggers/JobApplicationTrigger.trigger new file mode 100644 index 0000000..e1612cf --- /dev/null +++ b/force-app/main/default/triggers/JobApplicationTrigger.trigger @@ -0,0 +1,3 @@ +trigger JobApplicationTrigger on SOBJECT (before insert) { + +} \ No newline at end of file diff --git a/force-app/main/default/triggers/JobApplicationTrigger.trigger-meta.xml b/force-app/main/default/triggers/JobApplicationTrigger.trigger-meta.xml new file mode 100644 index 0000000..5ca7aa3 --- /dev/null +++ b/force-app/main/default/triggers/JobApplicationTrigger.trigger-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/sfdx-project.json b/sfdx-project.json index e29a7d5..9cacf28 100644 --- a/sfdx-project.json +++ b/sfdx-project.json @@ -8,5 +8,5 @@ "name": "job-application-tracker-oldv2-apex-innovators", "namespace": "", "sfdcLoginUrl": "https://login.salesforce.com", - "sourceApiVersion": "62.0" + "sourceApiVersion": "58.0" } From e083422a340f12cd737d575e5c7670eb05a411f1 Mon Sep 17 00:00:00 2001 From: Deval Date: Sat, 12 Oct 2024 18:33:12 -0400 Subject: [PATCH 07/56] Job Application Fields --- manifest/package.xml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/manifest/package.xml b/manifest/package.xml index ca42557..433515b 100644 --- a/manifest/package.xml +++ b/manifest/package.xml @@ -1,5 +1,20 @@ - + + + Job_Application__c.Application_Date__c + Job_Application__c.Company_Name__c + Job_Application__c.Description__c + Job_Application__c.Follow_up_date__c + Job_Application__c.Job_Application_Status__c + Job_Application__c.Job_Position__c + Job_Application__c.Location__c + Job_Application__c.Notes__c + Job_Application__c.Primary_Contact__c + Job_Application__c.Rating__c + Job_Application__c.Salary__c + Job_Application__c.URL__c + CustomField + Account AccountCleanInfo From f131e10ab3552e026fb052e2c2e84977f297ec5b Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Sat, 12 Oct 2024 18:36:19 -0400 Subject: [PATCH 08/56] Added TaskManager, updated Helper and TriggerHandler --- .../default/classes/JobApplicationHelper.cls | 33 ++++++++++++++++++- .../classes/JobApplicationTriggerHandler.cls | 4 +++ .../main/default/classes/TaskManager.cls | 22 +++++++++++++ .../default/classes/TaskManager.cls-meta.xml | 5 +++ .../triggers/JobApplicationTrigger.trigger | 2 +- 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 force-app/main/default/classes/TaskManager.cls create mode 100644 force-app/main/default/classes/TaskManager.cls-meta.xml diff --git a/force-app/main/default/classes/JobApplicationHelper.cls b/force-app/main/default/classes/JobApplicationHelper.cls index dc777e3..7ac8ff7 100644 --- a/force-app/main/default/classes/JobApplicationHelper.cls +++ b/force-app/main/default/classes/JobApplicationHelper.cls @@ -1,5 +1,36 @@ public with sharing class JobApplicationHelper { - public JobApplicationHelper() { + public static void processJobApplications(List jobApplications) { + List tasksToInsert = new List(); + for (Job_Application__c application : jobApplications) { + switch on application.Job_Application_Status__c { + when 'Saved' { + // Logic for Saved + } + when 'Applying' { + // Logic for Applying + } + when 'Applied' { + // Logic for Applied + } + when 'Interviewing' { + // Logic for Interviewing + } + when 'Negotiating' { + // Logic for Negotiating + } + when 'Accepted' { + // Logic for Accepted + } + when 'Closed' { + // Logic for Closed + } + when else { + // Other situations not covered + } + } + } + + TaskManager.createTasksForApplication(tasksToInsert); } } \ No newline at end of file diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls index 8d4e8f5..0e345ce 100644 --- a/force-app/main/default/classes/JobApplicationTriggerHandler.cls +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -10,4 +10,8 @@ public with sharing class JobApplicationTriggerHandler extends TriggerHandler { this.oldJobAppList = (List) Trigger.old; this.oldJobAppMap = (Map) Trigger.oldMap; } + + public override void afterUpdate() { + JobApplicationHelper.processJobApplications(newJobAppList); + } } \ No newline at end of file diff --git a/force-app/main/default/classes/TaskManager.cls b/force-app/main/default/classes/TaskManager.cls new file mode 100644 index 0000000..1f71855 --- /dev/null +++ b/force-app/main/default/classes/TaskManager.cls @@ -0,0 +1,22 @@ +public with sharing class TaskManager { + public static void createTasksForApplication (List tasks) { + try { + if (!tasks.isEmpty()) { + insert newTask; + } + } catch (DmlException e) { + System.debug('Error creating tasks: ' + e.getMessage()); + } + } + + public static void prepareTasks(Job_Application__c app, String subject, Date dueDate, String priority) { + Task newTask = new Task( + Subject = subject, + ActivityDate = dueDate, + Priority = priority, + OwnerId = app.OwnerId, + WhatId = app.Id, + Status = 'Not Started' + ); + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/TaskManager.cls-meta.xml b/force-app/main/default/classes/TaskManager.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/TaskManager.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/triggers/JobApplicationTrigger.trigger b/force-app/main/default/triggers/JobApplicationTrigger.trigger index e1612cf..ad17d36 100644 --- a/force-app/main/default/triggers/JobApplicationTrigger.trigger +++ b/force-app/main/default/triggers/JobApplicationTrigger.trigger @@ -1,3 +1,3 @@ -trigger JobApplicationTrigger on SOBJECT (before insert) { +trigger JobApplicationTrigger on Job_Application__c (after update) { } \ No newline at end of file From bd1678e8bff57162d2070a61f79d1f20503b2262 Mon Sep 17 00:00:00 2001 From: Deval Date: Sat, 12 Oct 2024 18:53:56 -0400 Subject: [PATCH 09/56] Job Applications Fields --- .../Job_Application__c.object-meta.xml | 8 ++-- .../fields/Application_Date__c.field-meta.xml | 10 ++++ .../fields/Company_Name__c.field-meta.xml | 12 +++++ .../fields/Description__c.field-meta.xml | 11 +++++ .../fields/Follow_up_date__c.field-meta.xml | 10 ++++ .../Job_Application_Status__c.field-meta.xml | 46 +++++++++++++++++++ .../fields/Job_Position__c.field-meta.xml | 12 +++++ .../fields/Location__c.field-meta.xml | 31 +++++++++++++ .../fields/Notes__c.field-meta.xml | 11 +++++ .../fields/Primary_Contact__c.field-meta.xml | 15 ++++++ .../fields/Rating__c.field-meta.xml | 41 +++++++++++++++++ .../fields/Salary__c.field-meta.xml | 13 ++++++ .../fields/URL__c.field-meta.xml | 10 ++++ 13 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Application_Date__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Company_Name__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Description__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Follow_up_date__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Job_Position__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Location__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Notes__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Primary_Contact__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Rating__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/Salary__c.field-meta.xml create mode 100644 force-app/main/default/objects/Job_Application__c/fields/URL__c.field-meta.xml diff --git a/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml index d298169..7455d3d 100644 --- a/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml +++ b/force-app/main/default/objects/Job_Application__c/Job_Application__c.object-meta.xml @@ -1,5 +1,5 @@ - + Accept Default @@ -149,17 +149,17 @@ true false true - true + false true true Private - + false Text - Job Applications + Job Application ReadWrite Public diff --git a/force-app/main/default/objects/Job_Application__c/fields/Application_Date__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Application_Date__c.field-meta.xml new file mode 100644 index 0000000..ef65ca8 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Application_Date__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Application_Date__c + false + + false + false + false + Date + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Company_Name__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Company_Name__c.field-meta.xml new file mode 100644 index 0000000..fd4c6ef --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Company_Name__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Company_Name__c + false + + 20 + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Description__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Description__c.field-meta.xml new file mode 100644 index 0000000..edc28f7 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Description__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Description__c + false + + 32768 + false + false + LongTextArea + 3 + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Follow_up_date__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Follow_up_date__c.field-meta.xml new file mode 100644 index 0000000..f4d3759 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Follow_up_date__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Follow_up_date__c + false + + false + false + false + Date + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml new file mode 100644 index 0000000..e0f689d --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml @@ -0,0 +1,46 @@ + + + Job_Application_Status__c + false + + false + false + false + Picklist + + true + + false + + Submitted + false + + + + Under Review + false + + + + Interview + false + + + + Rejected + false + + + + Offer Made + false + + + + Hired + false + + + + + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Job_Position__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Job_Position__c.field-meta.xml new file mode 100644 index 0000000..d1198d9 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Job_Position__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Job_Position__c + false + + 20 + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Location__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Location__c.field-meta.xml new file mode 100644 index 0000000..fa48805 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Location__c.field-meta.xml @@ -0,0 +1,31 @@ + + + Location__c + false + + false + false + false + Picklist + + true + + false + + Remote + false + + + + Hybrid + false + + + + Onsite + false + + + + + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Notes__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Notes__c.field-meta.xml new file mode 100644 index 0000000..84bca29 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Notes__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Notes__c + false + + 32768 + false + false + Html + 25 + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Primary_Contact__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Primary_Contact__c.field-meta.xml new file mode 100644 index 0000000..f861b43 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Primary_Contact__c.field-meta.xml @@ -0,0 +1,15 @@ + + + Primary_Contact__c + SetNull + Main point of contact for the role + false + + Contact + Job Application + Job_Application + false + false + false + Lookup + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Rating__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Rating__c.field-meta.xml new file mode 100644 index 0000000..165c046 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Rating__c.field-meta.xml @@ -0,0 +1,41 @@ + + + Rating__c + false + + false + false + false + Picklist + + true + + false + + 1 + false + + + + 2 + false + + + + 3 + false + + + + 4 + false + + + + 5 + false + + + + + diff --git a/force-app/main/default/objects/Job_Application__c/fields/Salary__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Salary__c.field-meta.xml new file mode 100644 index 0000000..47233d5 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/Salary__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Salary__c + false + + 18 + false + 0 + false + false + Number + false + diff --git a/force-app/main/default/objects/Job_Application__c/fields/URL__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/URL__c.field-meta.xml new file mode 100644 index 0000000..4f80983 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/fields/URL__c.field-meta.xml @@ -0,0 +1,10 @@ + + + URL__c + false + + false + false + false + Url + From a28c6bd4b742e7d67ce14603755ba824f1a8845b Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Mon, 14 Oct 2024 11:42:12 -0400 Subject: [PATCH 10/56] Updated Helper, TaskManager, TriggerHandler, and Trigger --- .../default/classes/JobApplicationHelper.cls | 34 ++++++++++++++----- .../classes/JobApplicationTriggerHandler.cls | 14 ++++++-- .../main/default/classes/TaskManager.cls | 13 ++++--- .../triggers/JobApplicationTrigger.trigger | 2 +- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/force-app/main/default/classes/JobApplicationHelper.cls b/force-app/main/default/classes/JobApplicationHelper.cls index 7ac8ff7..263172f 100644 --- a/force-app/main/default/classes/JobApplicationHelper.cls +++ b/force-app/main/default/classes/JobApplicationHelper.cls @@ -5,28 +5,46 @@ public with sharing class JobApplicationHelper { for (Job_Application__c application : jobApplications) { switch on application.Job_Application_Status__c { when 'Saved' { - // Logic for Saved + tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Normal', 'Check if the job description aligns with your interests and values')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Normal', 'Review the highlighted skills to see if the role is a good fit')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Low', 'Research the company or role and mark your excitement level')); } when 'Applying' { - // Logic for Applying + tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Find and research someone who works at the company and add them as a contact')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Set up an informational interview to learn more about the role/company')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Identify potential referrals to help get your application on the top of the pile')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'Normal', 'Customize your work achievements using the job description keywords')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'High', 'Submit your application on the company website if possible')); } when 'Applied' { - // Logic for Applied + tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'High', 'Reach out to the hiring manager or recruiter')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'Normal', 'Follow up on your application via email weekly')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Low', 'Continue identifying and saving similar job opportunities')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'Normal', 'Set up weekly networking calls to explore similar companies/roles')); } when 'Interviewing' { - // Logic for Interviewing + tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Prepare your blurb or “tell me about yourself” response')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'Normal', 'Practice answering behavioral interview questions')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'Normal', 'Research the company and your interviewers')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Set up your virtual interview space and test your tech')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Send thank you emails within 24 hours')); } when 'Negotiating' { - // Logic for Negotiating + tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'Normal', 'Research your market value and know your numbers')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'Normal', 'Prepare your negotiation scripts')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'High', 'Evaluate your offer and decline or accept')); } when 'Accepted' { - // Logic for Accepted + tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Normal', 'Plan your resignation if applicable')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Low', 'Take some time to relax and recharge')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Normal', 'Prepare for your first day of onboarding')); } when 'Closed' { - // Logic for Closed + tasksToInsert.add(TaskManager.prepareTask(application, 'Email', 'Normal', 'Send a follow-up email thanking the interviewer and asking for feedback')); + tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Low', 'Review your notes and reflect on areas of improvement')); } when else { - // Other situations not covered + System.debug('No tasks created for unrecognized status: ' + application.Job_Application_Status__c); } } } diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls index 0e345ce..de773d9 100644 --- a/force-app/main/default/classes/JobApplicationTriggerHandler.cls +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -12,6 +12,16 @@ public with sharing class JobApplicationTriggerHandler extends TriggerHandler { } public override void afterUpdate() { - JobApplicationHelper.processJobApplications(newJobAppList); - } + if (newJobAppList == null || newJobAppList.isEmpty()) { + return; + } + + for(Job_Application__c application : newJobAppList) { + Job_Application__c oldApp = oldJobAppMap.get(application.Id); + if (application.Job_Application_Status__c != oldApp.Job_Application_Status__c) { + JobApplicationHelper.processJobApplications(newJobAppList); + break; + } + } + } } \ No newline at end of file diff --git a/force-app/main/default/classes/TaskManager.cls b/force-app/main/default/classes/TaskManager.cls index 1f71855..71da8e0 100644 --- a/force-app/main/default/classes/TaskManager.cls +++ b/force-app/main/default/classes/TaskManager.cls @@ -2,21 +2,24 @@ public with sharing class TaskManager { public static void createTasksForApplication (List tasks) { try { if (!tasks.isEmpty()) { - insert newTask; + insert tasks; } } catch (DmlException e) { System.debug('Error creating tasks: ' + e.getMessage()); } } - public static void prepareTasks(Job_Application__c app, String subject, Date dueDate, String priority) { + public static Task prepareTask(Job_Application__c app, String subject, String priority, String description) { Task newTask = new Task( Subject = subject, - ActivityDate = dueDate, + ActivityDate = Date.today().addDays(7), Priority = priority, OwnerId = app.OwnerId, WhatId = app.Id, - Status = 'Not Started' - ); + Status = 'Not Started', + Description = description + ); + + return newTask; } } \ No newline at end of file diff --git a/force-app/main/default/triggers/JobApplicationTrigger.trigger b/force-app/main/default/triggers/JobApplicationTrigger.trigger index ad17d36..fae777b 100644 --- a/force-app/main/default/triggers/JobApplicationTrigger.trigger +++ b/force-app/main/default/triggers/JobApplicationTrigger.trigger @@ -1,3 +1,3 @@ trigger JobApplicationTrigger on Job_Application__c (after update) { - + new JobApplicationTriggerHandler().run(); } \ No newline at end of file From 67eb251c324147aebe3808a950685ffd155928a3 Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Mon, 14 Oct 2024 11:52:25 -0400 Subject: [PATCH 11/56] Update picklist values in status field. Added All.listView-meta.xml file --- .../Job_Application_Status__c.field-meta.xml | 60 ++++++++++++++++--- .../listViews/All.listView-meta.xml | 6 ++ 2 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 force-app/main/default/objects/Job_Application__c/listViews/All.listView-meta.xml diff --git a/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml b/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml index e0f689d..82527ae 100644 --- a/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml +++ b/force-app/main/default/objects/Job_Application__c/fields/Job_Application_Status__c.field-meta.xml @@ -1,9 +1,10 @@ Job_Application_Status__c + Active false - false + true false false Picklist @@ -12,34 +13,75 @@ false - Submitted + Saved false - + - Under Review + Applying false - + + + + Applied + false + + + + Interviewing + false + + + + Negotiating + false + + + + Accepted + false + + + + Closed + false + + + + Hired + false + false + Interview false + false + + Offer Made + false + false + + Rejected false + false - Offer Made + Submitted false - + false + - Hired + Under Review false - + false + diff --git a/force-app/main/default/objects/Job_Application__c/listViews/All.listView-meta.xml b/force-app/main/default/objects/Job_Application__c/listViews/All.listView-meta.xml new file mode 100644 index 0000000..d505851 --- /dev/null +++ b/force-app/main/default/objects/Job_Application__c/listViews/All.listView-meta.xml @@ -0,0 +1,6 @@ + + + All + Everything + + From ca0013efa32b9acad9a76ffcad787d82b8513053 Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Mon, 14 Oct 2024 13:16:12 -0400 Subject: [PATCH 12/56] Updated afterUpdate method in Handler to avoid DML statement inside for loop --- .../classes/JobApplicationTriggerHandler.cls | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls index de773d9..da77ff9 100644 --- a/force-app/main/default/classes/JobApplicationTriggerHandler.cls +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -12,16 +12,17 @@ public with sharing class JobApplicationTriggerHandler extends TriggerHandler { } public override void afterUpdate() { - if (newJobAppList == null || newJobAppList.isEmpty()) { - return; - } + List changedJobApplications = new List(); - for(Job_Application__c application : newJobAppList) { + for (Job_Application__c application : newJobAppList) { Job_Application__c oldApp = oldJobAppMap.get(application.Id); if (application.Job_Application_Status__c != oldApp.Job_Application_Status__c) { - JobApplicationHelper.processJobApplications(newJobAppList); - break; + changedJobApplications.add(application); } } + + if(!changedJobApplications.isEmpty()) { + JobApplicationHelper.processJobApplications(changedJobApplications); + } } } \ No newline at end of file From 11fe617b515ae5c7085eb1d57a0af56616d78c35 Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Mon, 14 Oct 2024 17:26:56 -0400 Subject: [PATCH 13/56] Moved logic in handler to helper class, added CRUD validation to DML statement in TaskManager --- .../default/classes/JobApplicationHelper.cls | 96 ++++++++++--------- .../classes/JobApplicationTriggerHandler.cls | 13 +-- .../main/default/classes/TaskManager.cls | 8 +- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/force-app/main/default/classes/JobApplicationHelper.cls b/force-app/main/default/classes/JobApplicationHelper.cls index 263172f..51c9758 100644 --- a/force-app/main/default/classes/JobApplicationHelper.cls +++ b/force-app/main/default/classes/JobApplicationHelper.cls @@ -1,52 +1,56 @@ public with sharing class JobApplicationHelper { - public static void processJobApplications(List jobApplications) { + public static void processJobApplications(List newJobAppList, Map oldJobAppMap) { List tasksToInsert = new List(); - for (Job_Application__c application : jobApplications) { - switch on application.Job_Application_Status__c { - when 'Saved' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Normal', 'Check if the job description aligns with your interests and values')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Normal', 'Review the highlighted skills to see if the role is a good fit')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Low', 'Research the company or role and mark your excitement level')); - } - when 'Applying' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Find and research someone who works at the company and add them as a contact')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Set up an informational interview to learn more about the role/company')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'High', 'Identify potential referrals to help get your application on the top of the pile')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'Normal', 'Customize your work achievements using the job description keywords')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'High', 'Submit your application on the company website if possible')); - } - when 'Applied' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'High', 'Reach out to the hiring manager or recruiter')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Application Process', 'Normal', 'Follow up on your application via email weekly')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Research', 'Low', 'Continue identifying and saving similar job opportunities')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Networking', 'Normal', 'Set up weekly networking calls to explore similar companies/roles')); - } - when 'Interviewing' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Prepare your blurb or “tell me about yourself” response')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'Normal', 'Practice answering behavioral interview questions')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'Normal', 'Research the company and your interviewers')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Set up your virtual interview space and test your tech')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Interview Preparation', 'High', 'Send thank you emails within 24 hours')); - } - when 'Negotiating' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'Normal', 'Research your market value and know your numbers')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'Normal', 'Prepare your negotiation scripts')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Offer Negotiation', 'High', 'Evaluate your offer and decline or accept')); - } - when 'Accepted' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Normal', 'Plan your resignation if applicable')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Low', 'Take some time to relax and recharge')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Normal', 'Prepare for your first day of onboarding')); - } - when 'Closed' { - tasksToInsert.add(TaskManager.prepareTask(application, 'Email', 'Normal', 'Send a follow-up email thanking the interviewer and asking for feedback')); - tasksToInsert.add(TaskManager.prepareTask(application, 'Onboarding & Reflection', 'Low', 'Review your notes and reflect on areas of improvement')); - } - when else { - System.debug('No tasks created for unrecognized status: ' + application.Job_Application_Status__c); - } - } + for (Job_Application__c newApplication : newJobAppList) { + Job_Application__c oldApp = oldJobAppMap.get(newApplication.Id); + + if (newApplication.Job_Application_Status__c != oldApp.Job_Application_Status__c) { + switch on newApplication.Job_Application_Status__c { + when 'Saved' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Check if the job description aligns with your interests and values')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Review the highlighted skills to see if the role is a good fit')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Research the company or role and mark your excitement level')); + } + when 'Applying' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Find and research someone who works at the company and add them as a contact')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Set up an informational interview to learn more about the role/company')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Identify potential referrals to help get your application on the top of the pile')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Customize your work achievements using the job description keywords')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Submit your application on the company website if possible')); + } + when 'Applied' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Reach out to the hiring manager or recruiter')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Follow up on your application via email weekly')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Continue identifying and saving similar job opportunities')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'Normal', 'Set up weekly networking calls to explore similar companies/roles')); + } + when 'Interviewing' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Prepare your blurb or “tell me about yourself” response')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Practice answering behavioral interview questions')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Research the company and your interviewers')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Set up your virtual interview space and test your tech')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Send thank you emails within 24 hours')); + } + when 'Negotiating' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Research your market value and know your numbers')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Prepare your negotiation scripts')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'High', 'Evaluate your offer and decline or accept')); + } + when 'Accepted' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Plan your resignation if applicable')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Take some time to relax and recharge')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Prepare for your first day of onboarding')); + } + when 'Closed' { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Email', 'Normal', 'Send a follow-up email thanking the interviewer and asking for feedback')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Review your notes and reflect on areas of improvement')); + } + when else { + System.debug('No tasks created for unrecognized status: ' + newApplication.Job_Application_Status__c); + } + } + } } TaskManager.createTasksForApplication(tasksToInsert); diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls index da77ff9..d689490 100644 --- a/force-app/main/default/classes/JobApplicationTriggerHandler.cls +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -12,17 +12,6 @@ public with sharing class JobApplicationTriggerHandler extends TriggerHandler { } public override void afterUpdate() { - List changedJobApplications = new List(); - - for (Job_Application__c application : newJobAppList) { - Job_Application__c oldApp = oldJobAppMap.get(application.Id); - if (application.Job_Application_Status__c != oldApp.Job_Application_Status__c) { - changedJobApplications.add(application); - } - } - - if(!changedJobApplications.isEmpty()) { - JobApplicationHelper.processJobApplications(changedJobApplications); - } + JobApplicationHelper.processJobApplications(newJobAppList, oldJobAppMap); } } \ No newline at end of file diff --git a/force-app/main/default/classes/TaskManager.cls b/force-app/main/default/classes/TaskManager.cls index 71da8e0..b43d5bf 100644 --- a/force-app/main/default/classes/TaskManager.cls +++ b/force-app/main/default/classes/TaskManager.cls @@ -2,10 +2,14 @@ public with sharing class TaskManager { public static void createTasksForApplication (List tasks) { try { if (!tasks.isEmpty()) { - insert tasks; + if (Schema.SObjectType.Task.isCreateable()) { + insert tasks; + } else { + System.debug('User does not have permission to create Task records.'); + } } } catch (DmlException e) { - System.debug('Error creating tasks: ' + e.getMessage()); + System.debug('Error creating tasks: ' + e.getMessage() + ' | Tasks: ' + tasks); } } From 42341da5b5b117dc0eacce3d27ea922e8f19287b Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Mon, 14 Oct 2024 21:32:04 -0400 Subject: [PATCH 14/56] paycheck calculator component --- ...tningService_UtilityBar.flexipage-meta.xml | 25 ++++ .../__tests__/paycheckCalculator.test.js | 25 ++++ .../paycheckCalculator.html | 39 ++++++ .../paycheckCalculator/paycheckCalculator.js | 119 ++++++++++++++++++ .../paycheckCalculator.js-meta.xml | 11 ++ .../__tests__/salaryBreakdownItem.test.js | 25 ++++ .../salaryBreakdownItem.html | 22 ++++ .../salaryBreakdownItem.js | 6 + .../salaryBreakdownItem.js-meta.xml | 5 + 9 files changed, 277 insertions(+) create mode 100644 force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml create mode 100644 force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js create mode 100644 force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.html create mode 100644 force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js create mode 100644 force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js-meta.xml create mode 100644 force-app/main/default/lwc/salaryBreakdownItem/__tests__/salaryBreakdownItem.test.js create mode 100644 force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.html create mode 100644 force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js create mode 100644 force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js-meta.xml diff --git a/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml b/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml new file mode 100644 index 0000000..358e29d --- /dev/null +++ b/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml @@ -0,0 +1,25 @@ + + + The default utility bar for the Service Console application. + + + + console:history + console_history + + + + + notes:utilityBarNoteList + notes_utilityBarNoteList + + + utilityItems + Region + + Service Console App Utility Bar + + UtilityBar + diff --git a/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js b/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js new file mode 100644 index 0000000..3f230ed --- /dev/null +++ b/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js @@ -0,0 +1,25 @@ +import { createElement } from 'lwc'; +import PaycheckCalculator from 'c/paycheckCalculator'; + +describe('c-paycheck-calculator', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + it('TODO: test case generated by CLI command, please fill in test logic', () => { + // Arrange + const element = createElement('c-paycheck-calculator', { + is: PaycheckCalculator + }); + + // Act + document.body.appendChild(element); + + // Assert + // const div = element.shadowRoot.querySelector('div'); + expect(1).toBe(1); + }); +}); \ No newline at end of file diff --git a/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.html b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.html new file mode 100644 index 0000000..766edc0 --- /dev/null +++ b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.html @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js new file mode 100644 index 0000000..aee9708 --- /dev/null +++ b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js @@ -0,0 +1,119 @@ +import { LightningElement, track } from 'lwc'; + +export default class PaycheckCalculator extends LightningElement { + + annualSalary = 0; + monthlyGrossSalary = 0; + biWeeklyGrossSalary = 0; + monthlyNetSalary = 0; + biWeeklyNetSalary = 0; + + @track federalIncomeTax = 0; + @track socialSecurityTax = 0; + @track medicareWithholding = 0; + @track takeHomePay = 0; + + federalTaxBrackets = [ + { limit: 11000, rate: 0.1 }, + { limit: 44725, rate: 0.12 }, + { limit: 95375, rate: 0.22 }, + { limit: 182100, rate: 0.24 }, + { limit: 231250, rate: 0.32 }, + { limit: 578125, rate: 0.35 }, + { limit: Infinity, rate: 0.37 } + ]; + + // Columns for Salary Breakdown + salaryColumns = [ + { label: 'Salary Type', fieldName: 'label' }, + { label: 'Amount', fieldName: 'value', type: 'currency' } + ]; + + // Columns for Tax Information + taxColumns = [ + { label: 'Taxes Taken Out', fieldName: 'label' }, + { label: 'Amount', fieldName: 'value', type: 'currency' }, + { + label: 'Info', + type: 'button-icon', + fieldName: 'info', // Info field to trigger the tooltip + typeAttributes: { + iconName: 'utility:info', + alternativeText: { fieldName: 'alternativeText' }, // hover text + variant: 'border-filled', + size: 'xx-small', + iconPosition: 'right' + } + } + ]; + + handleChange(event) { + this.annualSalary = Number(event.target.value); + this.calculateBreakdown(); + } + + // Calculate salary intervals and tax liabilities + calculateBreakdown() { + // Calculate gross salary before deductions + this.monthlyGrossSalary = (this.annualSalary / 12).toFixed(2); + this.biWeeklyGrossSalary = (this.annualSalary / 26).toFixed(2); + + // Calculate tax liabilities and net salary + this.calculateTaxLiabilities(); + } + + // Calculate tax-related amounts and take-home pay + calculateTaxLiabilities() { + this.federalIncomeTax = this.calculateFederalIncomeTax(this.annualSalary).toFixed(2); + this.socialSecurityTax = (this.annualSalary * 0.062).toFixed(2); + this.medicareWithholding = (this.annualSalary * 0.0145).toFixed(2); + + // Calculate total deductions + const totalDeductions = parseFloat(this.federalIncomeTax) + parseFloat(this.socialSecurityTax) + parseFloat(this.medicareWithholding); + + // Calculate take-home pay after deductions (net annual) + this.takeHomePay = (this.annualSalary - totalDeductions).toFixed(2); + + // Calculate monthly and bi-weekly pay after deductions (net) + this.monthlyNetSalary = (this.takeHomePay / 12).toFixed(2); // net monthly pay after deductions + this.biWeeklyNetSalary = (this.takeHomePay / 26).toFixed(2); // net bi-weekly pay after deductions + } + + // Calculate Federal Income Tax based on brackets + calculateFederalIncomeTax(income) { + let tax = 0; + let remainingIncome = income; + + for (let bracket of this.federalTaxBrackets) { + if (remainingIncome > bracket.limit) { + tax += bracket.limit * bracket.rate; + remainingIncome -= bracket.limit; + } else { + tax += remainingIncome * bracket.rate; + break; + } + } + + return tax; + } + + // List for salary breakdown (for first section) + get salaryBreakdown() { + return [ + { label: 'Gross Monthly Salary', value: this.monthlyGrossSalary }, + { label: 'Net Monthly Salary (After Deductions)', value: this.monthlyNetSalary }, + { label: 'Gross Bi-Weekly Salary', value: this.biWeeklyGrossSalary }, + { label: 'Net Bi-Weekly Salary (After Deductions)', value: this.biWeeklyNetSalary }, + { label: 'Estimated Take-Home Pay (Annual)', value: this.takeHomePay } + ]; + } + + // List for tax-related breakdown (for second section) + get taxBreakdown() { + return [ + { label: 'Federal Income Tax', value: this.federalIncomeTax, alternativeText: 'Federal income tax is calculated based on tax brackets.' }, + { label: 'Social Security Tax', value: this.socialSecurityTax, alternativeText: 'Social Security tax is 6.2% of your salary.' }, + { label: 'Medicare Withholding', value: this.medicareWithholding, alternativeText: 'Medicare tax is 1.45% of your salary.' } + ]; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js-meta.xml b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js-meta.xml new file mode 100644 index 0000000..44a075f --- /dev/null +++ b/force-app/main/default/lwc/paycheckCalculator/paycheckCalculator.js-meta.xml @@ -0,0 +1,11 @@ + + + 62.0 + true + + lightning__HomePage + lightning__RecordPage + lightning__AppPage + lightning__FlowScreen + + \ No newline at end of file diff --git a/force-app/main/default/lwc/salaryBreakdownItem/__tests__/salaryBreakdownItem.test.js b/force-app/main/default/lwc/salaryBreakdownItem/__tests__/salaryBreakdownItem.test.js new file mode 100644 index 0000000..eeda381 --- /dev/null +++ b/force-app/main/default/lwc/salaryBreakdownItem/__tests__/salaryBreakdownItem.test.js @@ -0,0 +1,25 @@ +import { createElement } from 'lwc'; +import SalaryBreakdownItem from 'c/salaryBreakdownItem'; + +describe('c-salary-breakdown-item', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + it('TODO: test case generated by CLI command, please fill in test logic', () => { + // Arrange + const element = createElement('c-salary-breakdown-item', { + is: SalaryBreakdownItem + }); + + // Act + document.body.appendChild(element); + + // Assert + // const div = element.shadowRoot.querySelector('div'); + expect(1).toBe(1); + }); +}); \ No newline at end of file diff --git a/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.html b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.html new file mode 100644 index 0000000..d8ca984 --- /dev/null +++ b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.html @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js new file mode 100644 index 0000000..ec05906 --- /dev/null +++ b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js @@ -0,0 +1,6 @@ +import { LightningElement, api } from 'lwc'; + +export default class SalaryBreakdownItem extends LightningElement { + @api label; + @api value; +} \ No newline at end of file diff --git a/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js-meta.xml b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js-meta.xml new file mode 100644 index 0000000..353961e --- /dev/null +++ b/force-app/main/default/lwc/salaryBreakdownItem/salaryBreakdownItem.js-meta.xml @@ -0,0 +1,5 @@ + + + 62.0 + false + \ No newline at end of file From aab0a72d2bfb32f3366abf1629983f62ddf47575 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Tue, 15 Oct 2024 19:37:47 -0400 Subject: [PATCH 15/56] resolved errors on files, http->https, updated import header --- .../flexipages/LightningService_UtilityBar.flexipage-meta.xml | 2 +- .../paycheckCalculator/__tests__/paycheckCalculator.test.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml b/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml index 358e29d..3f4204c 100644 --- a/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml +++ b/force-app/main/default/flexipages/LightningService_UtilityBar.flexipage-meta.xml @@ -1,5 +1,5 @@ - + The default utility bar for the Service Console application. diff --git a/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js b/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js index 3f230ed..b84c970 100644 --- a/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js +++ b/force-app/main/default/lwc/paycheckCalculator/__tests__/paycheckCalculator.test.js @@ -1,4 +1,5 @@ -import { createElement } from 'lwc'; +import { createElement } from '@lwc/engine-dom'; + import PaycheckCalculator from 'c/paycheckCalculator'; describe('c-paycheck-calculator', () => { From bed108b1e6124dd398615ec9fbe08c46f47ca050 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Wed, 16 Oct 2024 20:29:56 -0400 Subject: [PATCH 16/56] job board beginnings.... --- .../lwc/jobList/__tests__/jobList.test.js | 25 +++++++ .../main/default/lwc/jobList/jobList.css | 24 +++++++ .../main/default/lwc/jobList/jobList.html | 36 ++++++++++ force-app/main/default/lwc/jobList/jobList.js | 68 +++++++++++++++++++ .../default/lwc/jobList/jobList.js-meta.xml | 11 +++ 5 files changed, 164 insertions(+) create mode 100644 force-app/main/default/lwc/jobList/__tests__/jobList.test.js create mode 100644 force-app/main/default/lwc/jobList/jobList.css create mode 100644 force-app/main/default/lwc/jobList/jobList.html create mode 100644 force-app/main/default/lwc/jobList/jobList.js create mode 100644 force-app/main/default/lwc/jobList/jobList.js-meta.xml diff --git a/force-app/main/default/lwc/jobList/__tests__/jobList.test.js b/force-app/main/default/lwc/jobList/__tests__/jobList.test.js new file mode 100644 index 0000000..250843b --- /dev/null +++ b/force-app/main/default/lwc/jobList/__tests__/jobList.test.js @@ -0,0 +1,25 @@ +import { createElement } from 'lwc'; +import JobList from 'c/jobList'; + +describe('c-job-list', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + it('TODO: test case generated by CLI command, please fill in test logic', () => { + // Arrange + const element = createElement('c-job-list', { + is: JobList + }); + + // Act + document.body.appendChild(element); + + // Assert + // const div = element.shadowRoot.querySelector('div'); + expect(1).toBe(1); + }); +}); \ No newline at end of file diff --git a/force-app/main/default/lwc/jobList/jobList.css b/force-app/main/default/lwc/jobList/jobList.css new file mode 100644 index 0000000..6382ac7 --- /dev/null +++ b/force-app/main/default/lwc/jobList/jobList.css @@ -0,0 +1,24 @@ +.slds-scrollable_y { + overflow-y: auto; + max-height: 300px; +} + +.custom-card { + --sds-c-card-heading-font-weight: bold; +} + +.custom-title { + font-size: 40px; + line-height: 1.25; +} + +table { + table-layout: auto; + width: 100%; +} + +.slds-table th, .slds-table td { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/force-app/main/default/lwc/jobList/jobList.html b/force-app/main/default/lwc/jobList/jobList.html new file mode 100644 index 0000000..f883a94 --- /dev/null +++ b/force-app/main/default/lwc/jobList/jobList.html @@ -0,0 +1,36 @@ + diff --git a/force-app/main/default/lwc/jobList/jobList.js b/force-app/main/default/lwc/jobList/jobList.js new file mode 100644 index 0000000..1f08166 --- /dev/null +++ b/force-app/main/default/lwc/jobList/jobList.js @@ -0,0 +1,68 @@ +import { LightningElement, track } from 'lwc'; + +export default class JobList extends LightningElement { + @track keywords = ''; + @track location = ''; + @track jobs = []; + + // columns for the table + columns = [ + { label: 'Job Title', fieldName: 'title', sortable: true }, + { label: 'Company', fieldName: 'company', sortable: true }, + { label: 'Location', fieldName: 'location', sortable: true }, + { label: 'Salary', fieldName: 'salary', sortable: true }, + { label: 'Date Posted', fieldName: 'datePosted', sortable: true }, + { label: 'Action', fieldName: 'action', sortable: true , + type: 'button', + typeAttributes: { + label: 'Save', + name: 'save', + variant: 'neutral' + } + } + ]; + + // check if there are any jobs + get hasJobs() { + return this.jobs.length > 0; + } + + // Handle changes to the keyword input + handleKeywordChange(event) { + this.keywords = event.target.value; + } + + // Handle changes to the location input + handleLocationChange(event) { + this.location = event.target.value; + } + + // Handle the search button click + handleSearch() { + // Simulate job search results based on keywords (replace with actual API call later) + if (this.keywords.toLowerCase().includes('salesforce')) { + // Simulate matching jobs + this.jobs = [ + { id: 1, title: 'Salesforce Developer', company: 'Company A', location: 'New York', datePosted: '2024-10-01', salary: '$100,000' }, + { id: 2, title: 'Salesforce Admin', company: 'Company B', location: 'San Francisco', datePosted: '2024-09-20', salary: '$90,000' }, + { id: 3, title: 'Salesforce Architect', company: 'Company C', location: 'Austin', datePosted: '2024-08-15', salary: '$120,000' } + ]; + } else { + // No matching jobs for the provided keywords + this.jobs = []; + } + } + + // Handle saving job application; will need to save to custom object Job_Application__c + handleSave(event) { + const jobId = event.detail.row.id; // Accessing the ID of the clicked job + console.log(`Saving job with ID: ${jobId}`); + } + + // Handle resetting the search form + handleReset() { + this.keywords = ''; // Clear the keyword input + this.location = ''; // Clear the location input + this.jobs = []; // Clear the jobs array + } +} diff --git a/force-app/main/default/lwc/jobList/jobList.js-meta.xml b/force-app/main/default/lwc/jobList/jobList.js-meta.xml new file mode 100644 index 0000000..44a075f --- /dev/null +++ b/force-app/main/default/lwc/jobList/jobList.js-meta.xml @@ -0,0 +1,11 @@ + + + 62.0 + true + + lightning__HomePage + lightning__RecordPage + lightning__AppPage + lightning__FlowScreen + + \ No newline at end of file From 60747ebacbeec3081ac1798cd6c244be30d36910 Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Wed, 16 Oct 2024 20:36:59 -0400 Subject: [PATCH 17/56] added custom page that has the lwcs on it --- .../LWCs_Test_HomePage.flexipage-meta.xml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 force-app/main/default/flexipages/LWCs_Test_HomePage.flexipage-meta.xml diff --git a/force-app/main/default/flexipages/LWCs_Test_HomePage.flexipage-meta.xml b/force-app/main/default/flexipages/LWCs_Test_HomePage.flexipage-meta.xml new file mode 100644 index 0000000..917c45c --- /dev/null +++ b/force-app/main/default/flexipages/LWCs_Test_HomePage.flexipage-meta.xml @@ -0,0 +1,32 @@ + + + + + + jobList + c_jobList + + + region1 + Region + + + + + paycheckCalculator + c_paycheckCalculator + + + region2 + Region + + + region3 + Region + + LWCs Test HomePage + + HomePage + From c05df4ebbee5df131c5ea1380ee012145ee60b7a Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Thu, 17 Oct 2024 20:23:23 -0400 Subject: [PATCH 18/56] Added updated Task Automation for Code Review --- .../main/default/classes/CustomException.cls | 1 + .../classes/CustomException.cls-meta.xml | 5 + .../default/classes/JobApplicationHelper.cls | 79 ++- .../classes/JobApplicationHelperTest.cls | 589 ++++++++++++++++++ .../JobApplicationHelperTest.cls-meta.xml | 5 + .../classes/JobApplicationTriggerHandler.cls | 6 +- .../main/default/classes/TestDataFactory.cls | 68 ++ .../classes/TestDataFactory.cls-meta.xml | 5 + .../main/default/classes/TriggerHandler.cls | 71 ++- .../triggers/JobApplicationTrigger.trigger | 2 +- 10 files changed, 767 insertions(+), 64 deletions(-) create mode 100644 force-app/main/default/classes/CustomException.cls create mode 100644 force-app/main/default/classes/CustomException.cls-meta.xml create mode 100644 force-app/main/default/classes/JobApplicationHelperTest.cls create mode 100644 force-app/main/default/classes/JobApplicationHelperTest.cls-meta.xml create mode 100644 force-app/main/default/classes/TestDataFactory.cls create mode 100644 force-app/main/default/classes/TestDataFactory.cls-meta.xml diff --git a/force-app/main/default/classes/CustomException.cls b/force-app/main/default/classes/CustomException.cls new file mode 100644 index 0000000..4bbbb7f --- /dev/null +++ b/force-app/main/default/classes/CustomException.cls @@ -0,0 +1 @@ +public class CustomException extends Exception {} diff --git a/force-app/main/default/classes/CustomException.cls-meta.xml b/force-app/main/default/classes/CustomException.cls-meta.xml new file mode 100644 index 0000000..998805a --- /dev/null +++ b/force-app/main/default/classes/CustomException.cls-meta.xml @@ -0,0 +1,5 @@ + + + 62.0 + Active + diff --git a/force-app/main/default/classes/JobApplicationHelper.cls b/force-app/main/default/classes/JobApplicationHelper.cls index 51c9758..cc718be 100644 --- a/force-app/main/default/classes/JobApplicationHelper.cls +++ b/force-app/main/default/classes/JobApplicationHelper.cls @@ -1,58 +1,81 @@ public with sharing class JobApplicationHelper { public static void processJobApplications(List newJobAppList, Map oldJobAppMap) { List tasksToInsert = new List(); + Set processedJobAppIds = new Set(); + + // Fetch existing tasks related to job applications + for (Task existingTask : [SELECT Id, WhatId FROM Task WHERE WhatId IN :newJobAppList]) { + processedJobAppIds.add(existingTask.WhatId); + } + for (Job_Application__c newApplication : newJobAppList) { - Job_Application__c oldApp = oldJobAppMap.get(newApplication.Id); + Job_Application__c oldApp = oldJobAppMap != null ? oldJobAppMap.get(newApplication.Id) : null; + + Boolean isStatusChanged = oldApp == null || newApplication.Job_Application_Status__c != oldApp.Job_Application_Status__c; + + // If the application has been processed before and the status didn't change, skip it + if (processedJobAppIds.contains(newApplication.Id) && !isStatusChanged) { + continue; + } - if (newApplication.Job_Application_Status__c != oldApp.Job_Application_Status__c) { + if (isStatusChanged || !processedJobAppIds.contains(newApplication.Id)) { switch on newApplication.Job_Application_Status__c { when 'Saved' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Check if the job description aligns with your interests and values')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Review the highlighted skills to see if the role is a good fit')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Research the company or role and mark your excitement level')); + if (!processedJobAppIds.contains(newApplication.Id)) { + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Check if the job description aligns with your interests and values')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Normal', 'Review the highlighted skills to see if the role is a good fit')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Research the company or role and mark your excitement level')); + } } when 'Applying' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Find and research someone who works at the company and add them as a contact')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Set up an informational interview to learn more about the role/company')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Identify potential referrals to help get your application on the top of the pile')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Customize your work achievements using the job description keywords')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Submit your application on the company website if possible')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Find and research someone who works at the company and add them as a contact')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Set up an informational interview to learn more about the role/company')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'High', 'Identify potential referrals to help get your application on the top of the pile')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Customize your work achievements using the job description keywords')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Submit your application on the company website if possible')); } when 'Applied' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Reach out to the hiring manager or recruiter')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Follow up on your application via email weekly')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Continue identifying and saving similar job opportunities')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'Normal', 'Set up weekly networking calls to explore similar companies/roles')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'High', 'Reach out to the hiring manager or recruiter')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Application Process', 'Normal', 'Follow up on your application via email weekly')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Research', 'Low', 'Continue identifying and saving similar job opportunities')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Networking', 'Normal', 'Set up weekly networking calls to explore similar companies/roles')); } when 'Interviewing' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Prepare your blurb or “tell me about yourself” response')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Practice answering behavioral interview questions')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Research the company and your interviewers')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Set up your virtual interview space and test your tech')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Send thank you emails within 24 hours')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Prepare your blurb or “tell me about yourself” response')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Practice answering behavioral interview questions')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'Normal', 'Research the company and your interviewers')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Set up your virtual interview space and test your tech')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Interview Preparation', 'High', 'Send thank you emails within 24 hours')); } when 'Negotiating' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Research your market value and know your numbers')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Prepare your negotiation scripts')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'High', 'Evaluate your offer and decline or accept')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Research your market value and know your numbers')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'Normal', 'Prepare your negotiation scripts')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Offer Negotiation', 'High', 'Evaluate your offer and decline or accept')); + } when 'Accepted' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Plan your resignation if applicable')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Take some time to relax and recharge')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Prepare for your first day of onboarding')); + + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Plan your resignation if applicable')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Take some time to relax and recharge')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Normal', 'Prepare for your first day of onboarding')); + } when 'Closed' { - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Email', 'Normal', 'Send a follow-up email thanking the interviewer and asking for feedback')); - tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Review your notes and reflect on areas of improvement')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Email', 'Normal', 'Send a follow-up email thanking the interviewer and asking for feedback')); + tasksToInsert.add(TaskManager.prepareTask(newApplication, 'Onboarding & Reflection', 'Low', 'Review your notes and reflect on areas of improvement')); } when else { System.debug('No tasks created for unrecognized status: ' + newApplication.Job_Application_Status__c); + throw new CustomException('Unrecognized job application status: ' + newApplication.Job_Application_Status__c); } } } } - TaskManager.createTasksForApplication(tasksToInsert); + if (!taskstoInsert.isEmpty()) { + TaskManager.createTasksForApplication(tasksToInsert); + } + } } \ No newline at end of file diff --git a/force-app/main/default/classes/JobApplicationHelperTest.cls b/force-app/main/default/classes/JobApplicationHelperTest.cls new file mode 100644 index 0000000..a9eafe0 --- /dev/null +++ b/force-app/main/default/classes/JobApplicationHelperTest.cls @@ -0,0 +1,589 @@ +@isTest +private class JobApplicationHelperTest { + @TestSetup + static void setup(){ + TestDataFactory.createJobApplications(400, 'Saved'); + } + + @isTest + static void testProcessJobApplications_Saved() { + // Retrieve the updated job applications + List updatedAppList = [SELECT Id, Job_Application_Status__c, OwnerId FROM Job_Application__c]; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(updatedAppList, null); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(3, tasksForApp.size(), 'There should be 3 tasks created for each job application with the "Saved" status'); + + // Check the details of each task + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Research' && task.Priority == 'Normal' && task.Description == 'Check if the job description aligns with your interests and values') { + check1 = true; + } else if (task.Subject == 'Research' && task.Priority == 'Normal' && task.Description == 'Review the highlighted skills to see if the role is a good fit') { + check2 = true; + } else if (task.Subject == 'Research' && task.Priority == 'Low' && task.Description == 'Research the company or role and mark your excitement level') { + check3 = true; + } + } + + // Assert that all three tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Check if the job description aligns with your interests and values) should be created.'); + Assert.isTrue(check2, 'Task 2 (Review the highlighted skills to see if the role is a good fit) should be created.'); + Assert.isTrue(check3, 'Task 3 (Research the company or role and mark your excitement level) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Applying() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Applying' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Applying'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(8, tasksForApp.size(), 'There should be 8 tasks created for each job application after updating to "Applying" status'); + + // Separate tasks into "Saved" and "Applying" groups based on their descriptions + Integer savedTaskCount = 0; + Integer applyingTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Applying" status + applyingTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 5 tasks from 'Applying' status and check their details + Assert.areEqual(5, applyingTaskCount, 'There should be 5 new tasks from the "Applying" status'); + + // Check the details of the "Applying" tasks + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + Boolean check4 = false; + Boolean check5 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Networking' && task.Priority == 'High' && task.Description == 'Find and research someone who works at the company and add them as a contact') { + check1 = true; + } else if (task.Subject == 'Networking' && task.Priority == 'High' && task.Description == 'Set up an informational interview to learn more about the role/company') { + check2 = true; + } else if (task.Subject == 'Networking' && task.Priority == 'High' && task.Description == 'Identify potential referrals to help get your application on the top of the pile') { + check3 = true; + } else if (task.Subject == 'Application Process' && task.Priority == 'Normal' && task.Description == 'Customize your work achievements using the job description keywords') { + check4 = true; + } else if (task.Subject == 'Application Process' && task.Priority == 'High' && task.Description == 'Submit your application on the company website if possible') { + check5 = true; + } + } + + // Assert that all five "Applying" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Find and research someone who works at the company and add them as a contact) should be created.'); + Assert.isTrue(check2, 'Task 2 (Set up an informational interview to learn more about the role/company) should be created.'); + Assert.isTrue(check3, 'Task 3 (Identify potential referrals to help get your application on the top of the pile) should be created.'); + Assert.isTrue(check4, 'Task 4 (Customize your work achievements using the job description keywords) should be created.'); + Assert.isTrue(check5, 'Task 5 (Submit your application on the company website if possible) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Applied() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Applying' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Applied'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(7, tasksForApp.size(), 'There should be 7 tasks created for each job application after updating to "Applied" status'); + + // Separate tasks into "Saved" and "Applying" groups based on their descriptions + Integer savedTaskCount = 0; + Integer appliedTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Applied" Status + appliedTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 4 tasks from 'Applied' status and check their details + Assert.areEqual(4, appliedTaskCount, 'There should be 4 new tasks from the "Applied" status'); + + // Check the details of the "Applying" tasks + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + Boolean check4 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Application Process' && task.Priority == 'High' && task.Description == 'Reach out to the hiring manager or recruiter') { + check1 = true; + } else if (task.Subject == 'Application Process' && task.Priority == 'Normal' && task.Description == 'Follow up on your application via email weekly') { + check2 = true; + } else if (task.Subject == 'Research' && task.Priority == 'Low' && task.Description == 'Continue identifying and saving similar job opportunities') { + check3 = true; + } else if (task.Subject == 'Networking' && task.Priority == 'Normal' && task.Description == 'Set up weekly networking calls to explore similar companies/roles') { + check4 = true; + } + } + + // Assert that all five "Applying" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Reach out to the hiring manager or recruiter) should be created.'); + Assert.isTrue(check2, 'Task 2 (Follow up on your application via email weekly) should be created.'); + Assert.isTrue(check3, 'Task 3 (Continue identifying and saving similar job opportunities) should be created.'); + Assert.isTrue(check4, 'Task 4 (Set up weekly networking calls to explore similar companies/roles) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Interviewing() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Interviewing' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Interviewing'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(8, tasksForApp.size(), 'There should be 8 tasks created for each job application after updating to "Interviewing" status'); + + // Separate tasks into "Saved" and "Interviewing" groups based on their descriptions + Integer savedTaskCount = 0; + Integer interviewingTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Interviewing" Status + interviewingTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 5 tasks from 'Interviewing' status and check their details + Assert.areEqual(5, interviewingTaskCount, 'There should be 5 new tasks from the "Interviewing" status'); + + // Check the details of the "Interviewing" tasks + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + Boolean check4 = false; + Boolean check5 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Interview Preparation' && task.Priority == 'High' && task.Description == 'Prepare your blurb or “tell me about yourself” response') { + check1 = true; + } else if (task.Subject == 'Interview Preparation' && task.Priority == 'Normal' && task.Description == 'Practice answering behavioral interview questions') { + check2 = true; + } else if (task.Subject == 'Interview Preparation' && task.Priority == 'Normal' && task.Description == 'Research the company and your interviewers') { + check3 = true; + } else if (task.Subject == 'Interview Preparation' && task.Priority == 'High' && task.Description == 'Set up your virtual interview space and test your tech') { + check4 = true; + } else if (task.Subject == 'Interview Preparation' && task.Priority == 'High' && task.Description == 'Send thank you emails within 24 hours') { + check4 = true; + } + } + + // Assert that all four "Interviewing" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Prepare your blurb or “tell me about yourself” response) should be created.'); + Assert.isTrue(check2, 'Task 2 (Practice answering behavioral interview questions) should be created.'); + Assert.isTrue(check3, 'Task 3 (Research the company and your interviewers) should be created.'); + Assert.isTrue(check4, 'Task 4 (Send thank you emails within 24 hours) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Negotiating() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Negotiating' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Negotiating'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(6, tasksForApp.size(), 'There should be 6 tasks created for each job application after updating to "Negotiating" status'); + + // Separate tasks into "Saved" and "Negotiating" groups based on their descriptions + Integer savedTaskCount = 0; + Integer negotiatingTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Negotiating" Status + negotiatingTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 3 tasks from 'Negotiating' status and check their details + Assert.areEqual(3, negotiatingTaskCount, 'There should be 3 new tasks from the "Negotiating" status'); + + // Check the details of the "Negotiating" tasks + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Offer Negotiation' && task.Priority == 'Normal' && task.Description == 'Research your market value and know your numbers') { + check1 = true; + } else if (task.Subject == 'Offer Negotiation' && task.Priority == 'Normal' && task.Description == 'Prepare your negotiation scripts') { + check2 = true; + } else if (task.Subject == 'Offer Negotiation' && task.Priority == 'High' && task.Description == 'Evaluate your offer and decline or accept') { + check3 = true; + } + } + + // Assert that all three "Negotiating" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Research your market value and know your numbers) should be created.'); + Assert.isTrue(check2, 'Task 2 (Prepare your negotiation scripts) should be created.'); + Assert.isTrue(check3, 'Task 3 (Evaluate your offer and decline or accept) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Accepted() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Accepted' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Accepted'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(6, tasksForApp.size(), 'There should be 6 tasks created for each job application after updating to "Accepted" status'); + + // Separate tasks into "Saved" and "Accepted" groups based on their descriptions + Integer savedTaskCount = 0; + Integer acceptedTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Accepted" Status + acceptedTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 3 tasks from 'Accepted' status and check their details + Assert.areEqual(3, acceptedTaskCount, 'There should be 3 new tasks from the "Accepted" status'); + + // Check the details of the "Accepted" tasks + Boolean check1 = false; + Boolean check2 = false; + Boolean check3 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Onboarding & Reflection' && task.Priority == 'Normal' && task.Description == 'Plan your resignation if applicable') { + check1 = true; + } else if (task.Subject == 'Onboarding & Reflection' && task.Priority == 'Low' && task.Description == 'Take some time to relax and recharge') { + check2 = true; + } else if (task.Subject == 'Onboarding & Reflection' && task.Priority == 'Normal' && task.Description == 'Prepare for your first day of onboarding') { + check3 = true; + } + } + + // Assert that all three "Accepted" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Plan your resignation if applicable) should be created.'); + Assert.isTrue(check2, 'Task 2 (Take some time to relax and recharge) should be created.'); + Assert.isTrue(check3, 'Task 3 (Prepare for your first day of onboarding) should be created.'); + } + } + + @isTest + static void testProcessJobApplications_Closed() { + // Retrieve Job Applications from TestSetup + List oldAppList = [SELECT Id, Job_Application_Status__c FROM Job_Application__c]; + + //Prepare map of old job applications with original status + Map oldJobAppMap = new Map(oldAppList); + + //Update job applications to 'Closed' status + for (Job_Application__c app : oldAppList) { + app.Job_Application_Status__c = 'Closed'; + } + update oldAppList; + + // Call the method to be tested + Test.startTest(); + JobApplicationHelper.processJobApplications(oldAppList, oldJobAppMap); + Test.stopTest(); + + // Retrieve the created tasks + List createdTasks = [SELECT Id, Subject, ActivityDate, Priority, OwnerId, WhatId, Status, Description FROM Task]; + + // Assertions + // Ensure that each job application has three related tasks + Map> tasksByJobApp = new Map>(); + for (Task task : createdTasks) { + if (!tasksByJobApp.containsKey(task.WhatId)) { + tasksByJobApp.put(task.WhatId, new List()); + } + tasksByJobApp.get(task.WhatId).add(task); + } + + for (Id appId : tasksByJobApp.keySet()) { + List tasksForApp = tasksByJobApp.get(appId); + + // Check that there are exactly 3 tasks for each job application with the "Saved" status + Assert.areEqual(5, tasksForApp.size(), 'There should be 5 tasks created for each job application after updating to "Closed" status'); + + // Separate tasks into "Saved" and "Closed" groups based on their descriptions + Integer savedTaskCount = 0; + Integer closedTaskCount = 0; + + for (Task task : tasksForApp) { + if (task.Description.contains('aligns with your interests') || + task.Description.contains('skills to see if the role is a good fit') || + task.Description.contains('mark your excitement level')) { + // Count tasks from the "Saved" status + savedTaskCount++; + } else { + // Count tasks from the "Closed" Status + closedTaskCount++; + } + } + + // Ensure that there are 3 tasks from 'Saved' status (but don't recheck their details) + Assert.areEqual(3, savedTaskCount, 'There should still be 3 tasks from the "Saved" status'); + + // Ensure that there are 2 tasks from 'Closed' status and check their details + Assert.areEqual(2, closedTaskCount, 'There should be 2 new tasks from the "Closed" status'); + + // Check the details of the "Closed" tasks + Boolean check1 = false; + Boolean check2 = false; + + for (Task task : tasksForApp) { + if (task.Subject == 'Email' && task.Priority == 'Normal' && task.Description == 'Send a follow-up email thanking the interviewer and asking for feedback') { + check1 = true; + } else if (task.Subject == 'Onboarding & Reflection' && task.Priority == 'Low' && task.Description == 'Review your notes and reflect on areas of improvement') { + check2 = true; + } + } + + // Assert that all two "Closed" tasks were created correctly + Assert.isTrue(check1, 'Task 1 (Send a follow-up email thanking the interviewer and asking for feedback) should be created.'); + Assert.isTrue(check2, 'Task 2 (Review your notes and reflect on areas of improvement) should be created.'); + } + } + + + @isTest + static void testWhenElseCondition_ExceptionThrown() { + // Arrange: Create a list of new job applications with an unrecognized status. + List newJobAppList = new List(); + Job_Application__c jobApp = new Job_Application__c(Job_Application_Status__c = 'UnrecognizedStatus'); + newJobAppList.add(jobApp); + + // Empty map for old job applications. + Map oldJobAppMap = new Map(); + + // Act and Assert: Expect the exception to be thrown. + // Act and Assert: Expect the exception to be thrown. + Test.startTest(); + try { + JobApplicationHelper.processJobApplications(newJobAppList, oldJobAppMap); + Assert.fail('Expected a CustomException to be thrown'); // Fail the test if no exception is thrown. + } catch (CustomException e) { + Assert.areEqual('Unrecognized job application status: UnrecognizedStatus', e.getMessage(), 'The exception message should match the expected message.'); + } + Test.stopTest(); + } + +} \ No newline at end of file diff --git a/force-app/main/default/classes/JobApplicationHelperTest.cls-meta.xml b/force-app/main/default/classes/JobApplicationHelperTest.cls-meta.xml new file mode 100644 index 0000000..998805a --- /dev/null +++ b/force-app/main/default/classes/JobApplicationHelperTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 62.0 + Active + diff --git a/force-app/main/default/classes/JobApplicationTriggerHandler.cls b/force-app/main/default/classes/JobApplicationTriggerHandler.cls index d689490..a6ec0d3 100644 --- a/force-app/main/default/classes/JobApplicationTriggerHandler.cls +++ b/force-app/main/default/classes/JobApplicationTriggerHandler.cls @@ -13,5 +13,9 @@ public with sharing class JobApplicationTriggerHandler extends TriggerHandler { public override void afterUpdate() { JobApplicationHelper.processJobApplications(newJobAppList, oldJobAppMap); - } + } + + public override void afterInsert() { + JobApplicationHelper.processJobApplications(newJobAppList, oldJobAppMap); + } } \ No newline at end of file diff --git a/force-app/main/default/classes/TestDataFactory.cls b/force-app/main/default/classes/TestDataFactory.cls new file mode 100644 index 0000000..00d8565 --- /dev/null +++ b/force-app/main/default/classes/TestDataFactory.cls @@ -0,0 +1,68 @@ +@isTest +public class TestDataFactory { + + // Utility method to create multiple Job Applications with associated Accounts and Contacts + public static List createJobApplications(Integer count, String initialStatus) { + List accounts = new List(); + List contacts = new List(); + List jobApplications = new List(); + + // Creating associated Accounts and Contacts + for (Integer i = 0; i < count; i++) { + Account acc = new Account(Name = 'Test Account ' + i); + accounts.add(acc); + } + insert accounts; + + for (Account acc : accounts) { + Contact con = new Contact(FirstName = 'Test', LastName = 'Contact', AccountId = acc.Id); + contacts.add(con); + } + insert contacts; + + // Creating Job Applications with initial status + for (Integer i = 0; i < count; i++) { + Job_Application__c jobApp = new Job_Application__c( + Name = 'Test Job Application ' + i, + Job_Application_Status__c = initialStatus, + OwnerId = UserInfo.getUserId() // Setting the current user as the owner + ); + jobApplications.add(jobApp); + } + + insert jobApplications; + return jobApplications; + } + + // Utility method to update a specific field on Job Applications (e.g., change status) + public static void updateJobApplicationStatus(List jobApplications, String newStatus) { + for (Job_Application__c app : jobApplications) { + app.Job_Application_Status__c = newStatus; + } + update jobApplications; + } + + // Utility method for creating a single Job Application + public static Job_Application__c createSingleJobApplication(String status) { + Account acc = new Account(Name = 'Single Test Account'); + insert acc; + + Contact con = new Contact(FirstName = 'Single', LastName = 'Test Contact', AccountId = acc.Id); + insert con; + + Job_Application__c jobApp = new Job_Application__c( + Name = 'Single Test Job Application', + Job_Application_Status__c = status, + OwnerId = UserInfo.getUserId() + ); + insert jobApp; + + return jobApp; + } + + // Utility method for updating a single Job Application's status + public static void updateSingleJobApplicationStatus(Job_Application__c jobApp, String newStatus) { + jobApp.Job_Application_Status__c = newStatus; + update jobApp; + } +} diff --git a/force-app/main/default/classes/TestDataFactory.cls-meta.xml b/force-app/main/default/classes/TestDataFactory.cls-meta.xml new file mode 100644 index 0000000..998805a --- /dev/null +++ b/force-app/main/default/classes/TestDataFactory.cls-meta.xml @@ -0,0 +1,5 @@ + + + 62.0 + Active + diff --git a/force-app/main/default/classes/TriggerHandler.cls b/force-app/main/default/classes/TriggerHandler.cls index 32e5619..39af998 100644 --- a/force-app/main/default/classes/TriggerHandler.cls +++ b/force-app/main/default/classes/TriggerHandler.cls @@ -71,53 +71,56 @@ public virtual class TriggerHandler { when AFTER_UPDATE { this.afterUpdate(); } - when AFTER_DELETE { - this.afterDelete(); - } - when AFTER_UNDELETE { - this.afterUndelete(); - } + // Uncomment later when in use + // when AFTER_DELETE { + // this.afterDelete(); + // } + // when AFTER_UNDELETE { + // this.afterUndelete(); + // } } } // Set the maximum number of times the handler can run - public void setMaxLoopCount(Integer max) { - String handlerName = getHandlerName(); - if(!TriggerHandler.loopCountMap.containsKey(handlerName)) { - TriggerHandler.loopCountMap.put(handlerName, new LoopCount(max)); - } else { - TriggerHandler.loopCountMap.get(handlerName).setMax(max); - } - } + // Uncomment later when needing to use + // public void setMaxLoopCount(Integer max) { + // String handlerName = getHandlerName(); + // if(!TriggerHandler.loopCountMap.containsKey(handlerName)) { + // TriggerHandler.loopCountMap.put(handlerName, new LoopCount(max)); + // } else { + // TriggerHandler.loopCountMap.get(handlerName).setMax(max); + // } + // } // Clear the maximum loop count for the handler - public void clearMaxLoopCount() { - this.setMaxLoopCount(-1); - } + // Uncomment later when needing to use + // public void clearMaxLoopCount() { + // this.setMaxLoopCount(-1); + // } /*************************************** * public static methods ***************************************/ - - // Bypass a particular handler from execution - public static void bypass(String handlerName) { - TriggerHandler.bypassedHandlers.add(handlerName); - } + // Uncomment later + // // Bypass a particular handler from execution + // public static void bypass(String handlerName) { + // TriggerHandler.bypassedHandlers.add(handlerName); + // } - // Allow a previously bypassed handler to execute - public static void clearBypass(String handlerName) { - TriggerHandler.bypassedHandlers.remove(handlerName); - } + // // Allow a previously bypassed handler to execute + // public static void clearBypass(String handlerName) { + // TriggerHandler.bypassedHandlers.remove(handlerName); + // } - // Check if a handler is bypassed - public static Boolean isBypassed(String handlerName) { - return TriggerHandler.bypassedHandlers.contains(handlerName); - } + // // Check if a handler is bypassed + // public static Boolean isBypassed(String handlerName) { + // return TriggerHandler.bypassedHandlers.contains(handlerName); + // } - // Clear all bypassed handlers - public static void clearAllBypasses() { - TriggerHandler.bypassedHandlers.clear(); - } + // // Clear all bypassed handlers + // public static void clearAllBypasses() { + // TriggerHandler.bypassedHandlers.clear(); + // } /*************************************** * private instancemethods diff --git a/force-app/main/default/triggers/JobApplicationTrigger.trigger b/force-app/main/default/triggers/JobApplicationTrigger.trigger index fae777b..96047fb 100644 --- a/force-app/main/default/triggers/JobApplicationTrigger.trigger +++ b/force-app/main/default/triggers/JobApplicationTrigger.trigger @@ -1,3 +1,3 @@ -trigger JobApplicationTrigger on Job_Application__c (after update) { +trigger JobApplicationTrigger on Job_Application__c (after update, after insert) { new JobApplicationTriggerHandler().run(); } \ No newline at end of file From 44aa4a414826d6e891e3f16d67ceca15ee0fcc95 Mon Sep 17 00:00:00 2001 From: jeremymshull Date: Thu, 17 Oct 2024 20:29:34 -0400 Subject: [PATCH 19/56] Added Task Object updates --- .../default/objects/Task/Task.object-meta.xml | 119 ++++++++++++++++++ .../Task/fields/ActivityDate.field-meta.xml | 5 + .../fields/CallDisposition.field-meta.xml | 5 + .../CallDurationInSeconds.field-meta.xml | 5 + .../Task/fields/CallObject.field-meta.xml | 5 + .../Task/fields/CallType.field-meta.xml | 5 + .../fields/CompletedDateTime.field-meta.xml | 5 + .../Task/fields/Description.field-meta.xml | 5 + .../objects/Task/fields/Email.field-meta.xml | 4 + .../Task/fields/IsRecurrence.field-meta.xml | 5 + .../Task/fields/IsReminderSet.field-meta.xml | 5 + .../Task/fields/OwnerId.field-meta.xml | 6 + .../objects/Task/fields/Phone.field-meta.xml | 4 + .../Task/fields/Priority.field-meta.xml | 6 + .../fields/RecurrenceInterval.field-meta.xml | 5 + .../RecurrenceRegeneratedType.field-meta.xml | 5 + .../objects/Task/fields/Status.field-meta.xml | 6 + .../Task/fields/Subject.field-meta.xml | 6 + .../Task/fields/TaskSubtype.field-meta.xml | 4 + .../objects/Task/fields/Type.field-meta.xml | 6 + .../objects/Task/fields/WhatId.field-meta.xml | 6 + .../objects/Task/fields/WhoId.field-meta.xml | 6 + .../CompletedTasks.listView-meta.xml | 30 +++++ .../DelegatedTasks.listView-meta.xml | 15 +++ .../listViews/OpenTasks.listView-meta.xml | 30 +++++ .../listViews/OverdueTasks.listView-meta.xml | 30 +++++ .../RecurringTasks.listView-meta.xml | 20 +++ .../listViews/TodaysTasks.listView-meta.xml | 30 +++++ .../UnscheduledTasks.listView-meta.xml | 29 +++++ 29 files changed, 412 insertions(+) create mode 100644 force-app/main/default/objects/Task/Task.object-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/ActivityDate.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/CallDisposition.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/CallDurationInSeconds.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/CallObject.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/CallType.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/CompletedDateTime.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Description.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Email.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/IsRecurrence.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/IsReminderSet.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/OwnerId.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Phone.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Priority.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/RecurrenceInterval.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/RecurrenceRegeneratedType.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Status.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Subject.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/TaskSubtype.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/Type.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/WhatId.field-meta.xml create mode 100644 force-app/main/default/objects/Task/fields/WhoId.field-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/CompletedTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/DelegatedTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/OpenTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/OverdueTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/RecurringTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/TodaysTasks.listView-meta.xml create mode 100644 force-app/main/default/objects/Task/listViews/UnscheduledTasks.listView-meta.xml diff --git a/force-app/main/default/objects/Task/Task.object-meta.xml b/force-app/main/default/objects/Task/Task.object-meta.xml new file mode 100644 index 0000000..1233d02 --- /dev/null +++ b/force-app/main/default/objects/Task/Task.object-meta.xml @@ -0,0 +1,119 @@ + + + + CancelEdit + Default + + + CancelEdit + Large + Default + + + CancelEdit + Small + Default + + + Close + Default + + + Close + Large + Default + + + Close + Small + Default + + + Delete + Default + + + Delete + Large + Default + + + Delete + Small + Default + + + DeleteSeries + Default + + + DeleteSeries + Large + Default + + + DeleteSeries + Small + Default + + + Edit + Default + + + Edit + Large + Default + + + Edit + Small + Default + + + NewTask + Default + + + NewTask + Large + Default + + + NewTask + Small + Default + + + SaveEdit + Default + + + SaveEdit + Large + Default + + + SaveEdit + Small + Default + + + View + Default + + + View + Large + Default + + + View + Small + Default + + SYSTEM + false + + Private + diff --git a/force-app/main/default/objects/Task/fields/ActivityDate.field-meta.xml b/force-app/main/default/objects/Task/fields/ActivityDate.field-meta.xml new file mode 100644 index 0000000..1804c8d --- /dev/null +++ b/force-app/main/default/objects/Task/fields/ActivityDate.field-meta.xml @@ -0,0 +1,5 @@ + + + ActivityDate + false + diff --git a/force-app/main/default/objects/Task/fields/CallDisposition.field-meta.xml b/force-app/main/default/objects/Task/fields/CallDisposition.field-meta.xml new file mode 100644 index 0000000..c3dd182 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/CallDisposition.field-meta.xml @@ -0,0 +1,5 @@ + + + CallDisposition + false + diff --git a/force-app/main/default/objects/Task/fields/CallDurationInSeconds.field-meta.xml b/force-app/main/default/objects/Task/fields/CallDurationInSeconds.field-meta.xml new file mode 100644 index 0000000..5821231 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/CallDurationInSeconds.field-meta.xml @@ -0,0 +1,5 @@ + + + CallDurationInSeconds + false + diff --git a/force-app/main/default/objects/Task/fields/CallObject.field-meta.xml b/force-app/main/default/objects/Task/fields/CallObject.field-meta.xml new file mode 100644 index 0000000..98e19e3 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/CallObject.field-meta.xml @@ -0,0 +1,5 @@ + + + CallObject + false + diff --git a/force-app/main/default/objects/Task/fields/CallType.field-meta.xml b/force-app/main/default/objects/Task/fields/CallType.field-meta.xml new file mode 100644 index 0000000..270b77c --- /dev/null +++ b/force-app/main/default/objects/Task/fields/CallType.field-meta.xml @@ -0,0 +1,5 @@ + + + CallType + false + diff --git a/force-app/main/default/objects/Task/fields/CompletedDateTime.field-meta.xml b/force-app/main/default/objects/Task/fields/CompletedDateTime.field-meta.xml new file mode 100644 index 0000000..174ce3d --- /dev/null +++ b/force-app/main/default/objects/Task/fields/CompletedDateTime.field-meta.xml @@ -0,0 +1,5 @@ + + + CompletedDateTime + false + diff --git a/force-app/main/default/objects/Task/fields/Description.field-meta.xml b/force-app/main/default/objects/Task/fields/Description.field-meta.xml new file mode 100644 index 0000000..253d539 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Description.field-meta.xml @@ -0,0 +1,5 @@ + + + Description + false + diff --git a/force-app/main/default/objects/Task/fields/Email.field-meta.xml b/force-app/main/default/objects/Task/fields/Email.field-meta.xml new file mode 100644 index 0000000..92f4b61 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Email.field-meta.xml @@ -0,0 +1,4 @@ + + + Email + diff --git a/force-app/main/default/objects/Task/fields/IsRecurrence.field-meta.xml b/force-app/main/default/objects/Task/fields/IsRecurrence.field-meta.xml new file mode 100644 index 0000000..f5d08e6 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/IsRecurrence.field-meta.xml @@ -0,0 +1,5 @@ + + + IsRecurrence + false + diff --git a/force-app/main/default/objects/Task/fields/IsReminderSet.field-meta.xml b/force-app/main/default/objects/Task/fields/IsReminderSet.field-meta.xml new file mode 100644 index 0000000..d1a624a --- /dev/null +++ b/force-app/main/default/objects/Task/fields/IsReminderSet.field-meta.xml @@ -0,0 +1,5 @@ + + + IsReminderSet + false + diff --git a/force-app/main/default/objects/Task/fields/OwnerId.field-meta.xml b/force-app/main/default/objects/Task/fields/OwnerId.field-meta.xml new file mode 100644 index 0000000..711ada1 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/OwnerId.field-meta.xml @@ -0,0 +1,6 @@ + + + OwnerId + false + Lookup + diff --git a/force-app/main/default/objects/Task/fields/Phone.field-meta.xml b/force-app/main/default/objects/Task/fields/Phone.field-meta.xml new file mode 100644 index 0000000..2d3dc65 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Phone.field-meta.xml @@ -0,0 +1,4 @@ + + + Phone + diff --git a/force-app/main/default/objects/Task/fields/Priority.field-meta.xml b/force-app/main/default/objects/Task/fields/Priority.field-meta.xml new file mode 100644 index 0000000..0a58df1 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Priority.field-meta.xml @@ -0,0 +1,6 @@ + + + Priority + false + Picklist + diff --git a/force-app/main/default/objects/Task/fields/RecurrenceInterval.field-meta.xml b/force-app/main/default/objects/Task/fields/RecurrenceInterval.field-meta.xml new file mode 100644 index 0000000..9c3bf6f --- /dev/null +++ b/force-app/main/default/objects/Task/fields/RecurrenceInterval.field-meta.xml @@ -0,0 +1,5 @@ + + + RecurrenceInterval + false + diff --git a/force-app/main/default/objects/Task/fields/RecurrenceRegeneratedType.field-meta.xml b/force-app/main/default/objects/Task/fields/RecurrenceRegeneratedType.field-meta.xml new file mode 100644 index 0000000..e1d6ec7 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/RecurrenceRegeneratedType.field-meta.xml @@ -0,0 +1,5 @@ + + + RecurrenceRegeneratedType + false + diff --git a/force-app/main/default/objects/Task/fields/Status.field-meta.xml b/force-app/main/default/objects/Task/fields/Status.field-meta.xml new file mode 100644 index 0000000..3c95c97 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Status.field-meta.xml @@ -0,0 +1,6 @@ + + + Status + false + Picklist + diff --git a/force-app/main/default/objects/Task/fields/Subject.field-meta.xml b/force-app/main/default/objects/Task/fields/Subject.field-meta.xml new file mode 100644 index 0000000..7fc2128 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Subject.field-meta.xml @@ -0,0 +1,6 @@ + + + Subject + false + Picklist + diff --git a/force-app/main/default/objects/Task/fields/TaskSubtype.field-meta.xml b/force-app/main/default/objects/Task/fields/TaskSubtype.field-meta.xml new file mode 100644 index 0000000..3f28795 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/TaskSubtype.field-meta.xml @@ -0,0 +1,4 @@ + + + TaskSubtype + diff --git a/force-app/main/default/objects/Task/fields/Type.field-meta.xml b/force-app/main/default/objects/Task/fields/Type.field-meta.xml new file mode 100644 index 0000000..260a878 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/Type.field-meta.xml @@ -0,0 +1,6 @@ + + + Type + false + Picklist + diff --git a/force-app/main/default/objects/Task/fields/WhatId.field-meta.xml b/force-app/main/default/objects/Task/fields/WhatId.field-meta.xml new file mode 100644 index 0000000..c5237c5 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/WhatId.field-meta.xml @@ -0,0 +1,6 @@ + + + WhatId + false + Lookup + diff --git a/force-app/main/default/objects/Task/fields/WhoId.field-meta.xml b/force-app/main/default/objects/Task/fields/WhoId.field-meta.xml new file mode 100644 index 0000000..6d445f5 --- /dev/null +++ b/force-app/main/default/objects/Task/fields/WhoId.field-meta.xml @@ -0,0 +1,6 @@ + + + WhoId + false + Lookup + diff --git a/force-app/main/default/objects/Task/listViews/CompletedTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/CompletedTasks.listView-meta.xml new file mode 100644 index 0000000..0273413 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/CompletedTasks.listView-meta.xml @@ -0,0 +1,30 @@ + + + CompletedTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_CLOSED + equals + 1 + + + IS_RECURRENCE + equals + 0 + + + LAST_UPDATE + equals + TODAY,LAST_N_DAYS:30 + + + diff --git a/force-app/main/default/objects/Task/listViews/DelegatedTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/DelegatedTasks.listView-meta.xml new file mode 100644 index 0000000..8572a44 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/DelegatedTasks.listView-meta.xml @@ -0,0 +1,15 @@ + + + DelegatedTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Delegated + + diff --git a/force-app/main/default/objects/Task/listViews/OpenTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/OpenTasks.listView-meta.xml new file mode 100644 index 0000000..d2d6198 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/OpenTasks.listView-meta.xml @@ -0,0 +1,30 @@ + + + OpenTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_CLOSED + equals + 0 + + + IS_RECURRENCE + equals + 0 + + + DUE_DATE + greaterOrEqual + LAST_N_DAYS:30 + + + diff --git a/force-app/main/default/objects/Task/listViews/OverdueTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/OverdueTasks.listView-meta.xml new file mode 100644 index 0000000..1346f78 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/OverdueTasks.listView-meta.xml @@ -0,0 +1,30 @@ + + + OverdueTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_CLOSED + equals + 0 + + + IS_RECURRENCE + equals + 0 + + + DUE_DATE + lessThan + TODAY + + + diff --git a/force-app/main/default/objects/Task/listViews/RecurringTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/RecurringTasks.listView-meta.xml new file mode 100644 index 0000000..0be8738 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/RecurringTasks.listView-meta.xml @@ -0,0 +1,20 @@ + + + RecurringTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_RECURRENCE + equals + 1 + + + diff --git a/force-app/main/default/objects/Task/listViews/TodaysTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/TodaysTasks.listView-meta.xml new file mode 100644 index 0000000..9186c69 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/TodaysTasks.listView-meta.xml @@ -0,0 +1,30 @@ + + + TodaysTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_CLOSED + equals + 0 + + + IS_RECURRENCE + equals + 0 + + + DUE_DATE + equals + TODAY,LAST_N_DAYS:30 + + + diff --git a/force-app/main/default/objects/Task/listViews/UnscheduledTasks.listView-meta.xml b/force-app/main/default/objects/Task/listViews/UnscheduledTasks.listView-meta.xml new file mode 100644 index 0000000..6f47977 --- /dev/null +++ b/force-app/main/default/objects/Task/listViews/UnscheduledTasks.listView-meta.xml @@ -0,0 +1,29 @@ + + + UnscheduledTasks + SUBJECT + WHO_NAME + WHAT_NAME + DUE_DATE + STATUS + PRIORITY + CORE.USERS.ALIAS + LAST_UPDATE + UPDATEDBY_USER.ALIAS + Mine + + IS_CLOSED + equals + 0 + + + IS_RECURRENCE + equals + 0 + + + DUE_DATE + equals + + + From 225bbf840a7900abc48329111261b900c87d49be Mon Sep 17 00:00:00 2001 From: Benjamin Pierre Date: Thu, 17 Oct 2024 22:20:50 -0400 Subject: [PATCH 20/56] more lwc prep for integration --- .../main/default/lwc/jobList/jobList.html | 48 ++++++--- force-app/main/default/lwc/jobList/jobList.js | 37 ++----- .../lwc/jobTable/__tests__/jobTable.test.js | 25 +++++ .../main/default/lwc/jobTable/jobTable.html | 18 ++++ .../main/default/lwc/jobTable/jobTable.js | 97 +++++++++++++++++++ .../default/lwc/jobTable/jobTable.js-meta.xml | 5 + 6 files changed, 184 insertions(+), 46 deletions(-) create mode 100644 force-app/main/default/lwc/jobTable/__tests__/jobTable.test.js create mode 100644 force-app/main/default/lwc/jobTable/jobTable.html create mode 100644 force-app/main/default/lwc/jobTable/jobTable.js create mode 100644 force-app/main/default/lwc/jobTable/jobTable.js-meta.xml diff --git a/force-app/main/default/lwc/jobList/jobList.html b/force-app/main/default/lwc/jobList/jobList.html index f883a94..4341a90 100644 --- a/force-app/main/default/lwc/jobList/jobList.html +++ b/force-app/main/default/lwc/jobList/jobList.html @@ -1,32 +1,47 @@