Introduction
I'm a Salesforce Admin Teamlead and currently working for Enpal B.V. a leading solar energy company based in Berlin, Germany. Enpal has experienced remarkable growth in recent years, expanding its presence across Europe and revolutionizing the solar energy market with innovative solutions. As part of the Enpal team, I contribute to driving efficiency and scalability in our Salesforce operations to support the company's rapid expansion.
Before joining Enpal, I was in Turkey working as Salesforce Developer for Trendyol, the largest e-commerce platform in Turkey. During my tenure at Trendyol, I played a pivotal role in the company's growth journey, particularly in optimizing seller acquisition and incentive management processes. Trendyol has emerged as a key player in the e-commerce sector, experiencing exponential growth and diversification of its product offerings.
I'm an All-in-One Salesforce professional, proficient in various aspects of Salesforce architecture, development, and administration. I serve as a valuable asset to organizations like Enpal and Trendyol by providing comprehensive expertise tailored to their specific needs. As a result, I've earned a reputation as a trusted consultant and problem-solver, delivering scalable and maintainable solutions that drive long-term success.
I'm a golden contractor for clients where:
Aside from my professional endeavors, I'm passionate about innovation and continuous learning. I'm currently working on packaging a solution that I developed, with the goal of listing it on the Salesforce AppExchange in the coming months. To learn more about my projects and contributions, feel free to explore my profile here.
Work Experience
Enpal B.V.
Salesforce Admin Teamlead (Berlin, Germany, July 2023 - Current)
- Engage in ongoing participation in technical implementations by actively contributing to the development and refinement of user stories
- Conducted monthly administrative sessions with peers to disseminate best practices, fostering an environment of continuous improvement and enhancing the overall quality of work
- Conduct monthly one-on-one meetings with administrators to discuss and assess their performance, address concerns, understand their professional aspirations, and align their goals with organizational objectives
- Collaborate in team lead meetings alongside other team leads to provide comprehensive updates on ongoing initiatives and discuss future strategic plans.
- Be a required reviewer of deployments of other admins/developers from dev to int sandboxes to ensure quality
Senior Salesforce Administrator (Berlin, Germany, August 2022 - July 2023)
- Oversee Flow Infrastructure by refactoring complex flows and create flow guidelines for other developers to follow
- Create a custom round robin application with Schedule, Batch APEX, and Lightning Web Components
- Implement GDPR compliance project with Schedule and Batch APEX and anonymize 380K leads
- In the process of designing the before conversion part of internalization project to create a new org
- Integrate marketing and customer portal systems with salesforce with REST API and Platform Events
- Hold technical and cultural interviews for salesforce admins and developers
- Create invocable methods to overcome limitations of flows
- Debug and troubleshoot any issue regarding trigger, flow, Bulk API, REST API, APEX
- Train and share knowledge to junior members to develop them professionally
Trendyol
Salesforce Developer (Istanbul, Turkey, June 2021 - August 2022)
- Analyze data issues and contact product owners of other integrated systems to resolve them
- Configure flows and apex triggers to automate business processes
- Hold workshop meetings to gather requirements
- Responsible for four Sales and Service cloud projects on international projects
Project Highlights
Custom Solution to Distribute Records Instead of Omni-Channel (Soon to be on AppExchange)
Context:
The omni-channel approach was falling short when it came to distributing records with the right criteria to specific users. Some criteria were quite complex, involving various objects such as events and opportunities.
Requirements:
Departments need to prioritize certain case records based on defined criteria. Users should have access to a Lightning Web Component (LWC) that displays assigned records along with their fields and values. Users should also be able to view a record directly from the component. The component should paginate assigned records in groups of 5. Managers should be able to modify the criteria and their priority, as well as halt record assignments. Standard Queues and Public Groups should determine to whom records will be distributed.
Solution:
- Create two custom objects: X (Parent object) and Y (Child object).
- Include a checkbox for managers to prevent users from owning a record on the parent object.
- Add a text field for managers to specify the queue developer name, determining which users can own records on the parent object.
- Provide a text field to input a query returning a certain number of records with specified criteria on the child object.
- Include a number field for managers to prioritize records on the child object.
- Develop an LWC component and place it in the app's utility bar.
- Place a "Own a Record" button on LWC. When a user clicks the button, query all child records in an ascending order based on priority and query records.
- Add an "Own a Record" button on the LWC. When clicked, query all child records in ascending order based on priority and assign the first record to the user.
Challenges:
- Queues contain more than 90 users, increasing the likelihood of simultaneous assignment to multiple users. Record locking is necessary to prevent this.
- Since the first record is locked for the entire transaction, users might encounter "UNABLE_TO_LOCK_ROW" error. To address this, randomization was introduced; if the rule returns 20 records in total based on priority, one of the first 5 records is randomly selected.
- Execute Anonymous REST API is utilized to execute APEX code for complex logic in criteria. A custom error is thrown from anonymous block to indicate unsuccessful assignment and prompt further action.
Role Permission Set Group Automation for Sales Department
Context:
Managing hundreds of Sales Agents with varying permission sets poses challenges in determining the necessary permissions for the Sales Agent persona. Onboarding processes are hindered as essential permission sets often cannot be promptly assigned, resulting in operational costs.
Requirements:
- Communicate with the business to discern required permissions for each role/persona and organize them into permission set groups.
- Maintain mappings of permission set groups for each sales role: Sales TL, Sales, VP Sales, Sales Director, and others.
- Upon creation of a user with a sales role, assign corresponding permission set groups.
- When a sales user's role is changed, ensure to remove the old role's permission set assignments and assign new ones.
- If a sales user's role is changed to a non-sales role, delete all associated permission set assignments.
- When a user outside of the sales department is assigned to a sales role, ensure they do not already have corresponding permission set assignments and create any missing ones.
Solution:
- Implement a trigger on the user object triggered upon creation and update to handle actions through a controller class.
- Store permission set groups and role mappings in custom metadata.
Challenges:
- Design each trigger in a bulkified manner to adhere to best practices. Due to the time required for record insertion and querying in Salesforce transactions, permission set assignments cannot be completed during a transaction. Assignments are managed in a static map, with permission set assignments/unassignments handled first, followed by deletion and insertion at the end of the transaction.
Close Case API and Refactoring
Context:
Users close different types of cases either successfully or unsuccessfully using a screen flow. They need to select one mandatory and two optional unsuccessful reasons, along with a comment. The screen flow closes the case and, based on the type, updates different records.
Requirements:
An external system needs to be able to close a certain type of case unsuccessfully, which is a process that already exists and is triggered via a screen flow. The endpoint and screen flow should follow the same logic. When a case is closed through the endpoint, the owner should be changed to the user in Salesforce with the same Azure ID provided in the request.
Solution:
- Create a class using the factory pattern so that if the same or other external systems require closing cases successfully or unsuccessfully, we don't need to create a new class each time.
- Implement an invocable method and replace the logic in the screen flow with it so that the record can be locked to prevent overwriting.
Challenges:
- The owner of the case should only be changed when it's closed through the endpoint, not the invocable method. To address this, a wrapper is created to specify whether an owner change is needed or not, along with other values.
- The external system might send between 1 and 3 rejection reasons. Dynamic Apex is used, where respected values are assigned to fields values instead of using repetitive if and else blocks.
- Updates to other related records could result in various issues. Custom exception classes are created to throw exceptions between classes to alert other systems and users who are using the screen flow.
Reassignment of Sales Calls via Rest API
Context:
Users have two types of sales calls recorded in the event object: reserved and available slots. Booking agents in Salesforce and an external system are responsible for booking available slots and turning them into reserved ones. The external system provides the event ID that needs to be reassigned and the Azure ID of the targeted assignee. Reserved events follow the following naming convention for the subject: customer name - user name.
Requirements:
- The targeted user should have an available slot at the same start date/time.
- The event ID that is sent and the available slot of the targeted assignee should be locked so that other systems or users shouldn't overwrite the current transaction.
- Records related to which polymorphic relationship should be updated, such as which IDs (case) parent case, opportunity, and other child cases.
- The naming convention of the reassigned event's subject needs to be modified; the targeted assignee's name should be replaced with the previous owner, and "(Reassigned)" needs to be added at the end of it.
- If all criteria are met, meaning reassignment is successful, the available slot of the target assignee should be deleted.
Solution:
- An endpoint for the external system has been created to make a call out with two parameters: event ID and Azure ID of the targeted user.
Challenges:
- TYPEOF is used to query cases in which the ID is polymorphic lookup along with its parent case and opportunity to save two SOQL statements. All records to be updated are collected into an SObject list to make transaction control easy when an exception is caught.
Global Sales
Context:
- There are several sales channels where leads are received. They all follow the same customer journey with small changes: owners are not the same for leads, parent cases, opportunities, accounts, and child cases.
- Some child cases need to be auto-closed (inserted as Closed - Successful).
- Leads need to be auto-converted based on different criteria for each sales channel.
- Converted opportunities' price book and other values differ from sales channel to sales channel.
- Previously, these logics were implemented in different flows. Whenever a new sales channel was introduced, all flows needed modification, resulting in 5-7 user stories.
Requirements:
- Map all sales channels as keys to their corresponding leads, accounts, opportunities, parent case owners, and auto-conversion criteria exclusion options in custom metadata.
- Apply this logic to the existing customer journey logic managed in case triggers, which are responsible for creating new cases.
Solution:
- All the logic has been moved from flows to triggers.
- Custom metadata is referenced in triggers. Therefore, when a new sales channel is introduced, all that's needed is to add new entries to the custom metadata.
Challenges:
- An existing trigger responsible for creating cases for further customer journeys was already in place.
- Instead of extending the logic and complicating it, global sales needed to be applied to it.
Auto-convert Leads
Context:
Marketing external system inserts leads and users update qualifies leads based on the customer-entered data through sliders on different web pages. Users were manually checking certain fields and related records on leads and converting them if they deemed them qualified.
Requirements:
Implement a solution to check if a lead is qualified for conversion upon insertion or update. If a lead meets all the criteria, it should be converted.
Solution:
- Create lead trigger and handler classes to verify if inserted and updated leads meet the qualification criteria for conversion.
- If a lead qualifies, convert it using an invocable method via Apex.
Challenges:
- Before converting a qualified lead, a duplicate check needs to be performed in a bulkified manner.
- If a lead exists with the same external ID as an account, then it shouldn't be converted and should be marked as a duplicate.
Anonymize Leads
Context:
Companies in Europe need to comply with GDPR, so a lead anonymization project was initiated. We might have multiple leads for the same customer, or a customer might already have an account. External IDs are used to identify customers.
Requirements:
Personal identification fields (such as First Name, Last Name, Email, etc.) of Lead records that are lost or not updated for a certain amount of time need to be anonymized, and a default value needs to be placed. Default values for each personal identification field need to be mapped in custom metadata.
Solution:
- Create a batch and schedule Apex to query leads and anonymize them.
Challenges:
- Other systems subscribe to changes in personal identification fields, so we need to be certain whether a customer should be anonymized or not.
- If there are any newer leads for a customer or if a customer already has an account, the customer shouldn't be anonymized.
- If there are no newer leads and no accounts for the customer, all leads that have the same external ID belonging to the customer should be anonymized.
Education
Georgia State University, Atlanta GA
Bachelor of Business Administration - Computer Information Systems (Fall 2017 - Summer 2021)
Honors, GPA 3.31, Dean's List 5 Semesters, President's List 1 Semester
Technical Skills
- APEX
- LWC
- SOQL
- JavaScript
- HTML
- Apex Triggers
- REST API
- Platform Events/Change Data Capture
- Flows
Certifications
- Salesforce Platform Developer II
- Salesforce Application Architect
- Salesforce Data Architect
- Salesforce Sharing and Visibility Architect
- Salesforce Process Automation Accredited Professional
- Salesforce Platform Developer I
- Salesforce Certified Service Consultant
- Salesforce Certified Sales Consultant
- Salesforce Certified Advanced Administrator
- Salesforce Platform App Builder
- Tableau Desktop Specialist
- AWS Certified Cloud Practitioner
- Salesforce Certified Administrator
Volunteer Activities
Trailblazer Mentorship Program (Salesforce, March 2022 - Current, Remote)
- This program is owned by Salesforce where a different mentee is assigned to a mentor each month to guide mentee's Salesforce journey
Trailblazer Answers Leader (Salesforce, Remote)
- An answers leader is someone who answer questions on trailblazer community to help other trailblazers
Tools
- Visual Studio Code
- Salesforce Inspector
- Salesforce Data Loader
- Salesforce Workbench
- Jira
- Confluence
- Copado
- Simple Survey
- Azure AD