/** * ═══════════════════════════════════════════════════════════════════════════════ * BULK INSERT 500+ RECORDS * For testing batch Apex and queueable job bulkification * ═══════════════════════════════════════════════════════════════════════════════ * * PURPOSE: * Test that batch Apex classes and queueable jobs handle larger datasets. * Default batch size is 200, so 500+ tests multiple batch iterations. * * WHY 500 RECORDS: * • Tests 2-3 batch iterations (200 records per batch) * • Validates stateful processing across batches * • Ensures aggregate operations work correctly * * BATCH APEX CONTEXT: * • Default scope is 200 records per execute() * • Maximum scope is 2000 records per execute() * • 50 million records can be processed total * * ═══════════════════════════════════════════════════════════════════════════════ */ // ═══════════════════════════════════════════════════════════════════════════════ // CONFIGURATION // ═══════════════════════════════════════════════════════════════════════════════ Integer accountCount = 100; // 100 accounts Integer contactsPerAccount = 3; // 300 contacts total Integer oppsPerAccount = 2; // 200 opportunities total // Total: ~600 records String namePrefix = 'BatchTest'; DateTime testStartTime = DateTime.now(); // ═══════════════════════════════════════════════════════════════════════════════ // TRACKING COLLECTIONS // ═══════════════════════════════════════════════════════════════════════════════ Map> createdRecords = new Map>{ 'Account' => new Set(), 'Contact' => new Set(), 'Opportunity' => new Set() }; // ═══════════════════════════════════════════════════════════════════════════════ // LIMIT TRACKING // ═══════════════════════════════════════════════════════════════════════════════ Integer startQueries = Limits.getQueries(); Integer startDml = Limits.getDmlStatements(); Integer startDmlRows = Limits.getDmlRows(); Integer startCpu = Limits.getCpuTime(); System.debug('═══════════════════════════════════════════════════════════════'); System.debug('Starting Batch-Size Test: ' + accountCount + ' accounts'); System.debug('Expected total records: ~' + (accountCount + accountCount * contactsPerAccount + accountCount * oppsPerAccount)); System.debug('═══════════════════════════════════════════════════════════════'); // ═══════════════════════════════════════════════════════════════════════════════ // STEP 1: CREATE ACCOUNTS IN CHUNKS // ═══════════════════════════════════════════════════════════════════════════════ List accounts = new List(); List industries = new List{ 'Technology', 'Healthcare', 'Finance', 'Manufacturing', 'Retail', 'Education', 'Energy', 'Media', 'Government', 'Nonprofit' }; List types = new List{'Prospect', 'Customer', 'Partner'}; for (Integer i = 0; i < accountCount; i++) { accounts.add(new Account( Name = namePrefix + '_Account_' + String.valueOf(i).leftPad(5, '0'), Industry = industries[Math.mod(i, industries.size())], Type = types[Math.mod(i, types.size())], AnnualRevenue = 100000 + (i * 25000), NumberOfEmployees = 25 + (i * 10), BillingCity = 'San Francisco', BillingState = 'CA', BillingCountry = 'USA', Description = 'Batch test account created at ' + testStartTime )); } insert accounts; for (Account acc : accounts) { createdRecords.get('Account').add(acc.Id); } System.debug('✓ Created ' + accounts.size() + ' Accounts'); // ═══════════════════════════════════════════════════════════════════════════════ // STEP 2: CREATE CONTACTS IN CHUNKS (to stay under DML row limit) // ═══════════════════════════════════════════════════════════════════════════════ List allContacts = new List(); Integer contactIndex = 0; List titles = new List{ 'CEO', 'CFO', 'CTO', 'VP Sales', 'VP Marketing', 'Director', 'Manager', 'Analyst', 'Developer', 'Consultant' }; for (Account acc : accounts) { for (Integer i = 0; i < contactsPerAccount; i++) { String idx = String.valueOf(contactIndex++).leftPad(5, '0'); allContacts.add(new Contact( FirstName = namePrefix, LastName = 'Contact_' + idx, AccountId = acc.Id, Email = namePrefix.toLowerCase() + '.contact' + idx + '@batchtest.example.com', Phone = '(555) 200-' + String.valueOf(1000 + Math.mod(contactIndex, 9000)), Title = titles[Math.mod(contactIndex, titles.size())], Department = 'Department ' + Math.mod(contactIndex, 5), MailingCity = 'San Francisco', MailingState = 'CA' )); } } // Insert contacts insert allContacts; for (Contact con : allContacts) { createdRecords.get('Contact').add(con.Id); } System.debug('✓ Created ' + allContacts.size() + ' Contacts'); // ═══════════════════════════════════════════════════════════════════════════════ // STEP 3: CREATE OPPORTUNITIES // ═══════════════════════════════════════════════════════════════════════════════ List allOpportunities = new List(); Integer oppIndex = 0; List stages = new List{ 'Prospecting', 'Qualification', 'Needs Analysis', 'Value Proposition', 'Proposal/Price Quote', 'Negotiation/Review' }; List leadSources = new List{ 'Web', 'Phone Inquiry', 'Partner Referral', 'Trade Show', 'Other' }; for (Account acc : accounts) { for (Integer i = 0; i < oppsPerAccount; i++) { String idx = String.valueOf(oppIndex++).leftPad(5, '0'); allOpportunities.add(new Opportunity( Name = namePrefix + '_Opportunity_' + idx, AccountId = acc.Id, StageName = stages[Math.mod(oppIndex, stages.size())], CloseDate = Date.today().addDays(15 + Math.mod(oppIndex, 90)), Amount = 5000 + (oppIndex * 500), Probability = 10 + Math.mod(oppIndex, 80), Type = 'New Customer', LeadSource = leadSources[Math.mod(oppIndex, leadSources.size())] )); } } insert allOpportunities; for (Opportunity opp : allOpportunities) { createdRecords.get('Opportunity').add(opp.Id); } System.debug('✓ Created ' + allOpportunities.size() + ' Opportunities'); // ═══════════════════════════════════════════════════════════════════════════════ // REPORT RESULTS // ═══════════════════════════════════════════════════════════════════════════════ Integer endQueries = Limits.getQueries(); Integer endDml = Limits.getDmlStatements(); Integer endDmlRows = Limits.getDmlRows(); Integer endCpu = Limits.getCpuTime(); Integer totalRecords = createdRecords.get('Account').size() + createdRecords.get('Contact').size() + createdRecords.get('Opportunity').size(); System.debug(''); System.debug('═══════════════════════════════════════════════════════════════'); System.debug('BATCH-SIZE TEST COMPLETE'); System.debug('═══════════════════════════════════════════════════════════════'); System.debug(''); System.debug('📊 RECORDS CREATED:'); System.debug(' Accounts: ' + createdRecords.get('Account').size()); System.debug(' Contacts: ' + createdRecords.get('Contact').size()); System.debug(' Opportunities: ' + createdRecords.get('Opportunity').size()); System.debug(' ────────────────────────────────'); System.debug(' TOTAL: ' + totalRecords); System.debug(''); System.debug('📈 GOVERNOR LIMITS USED:'); System.debug(' SOQL Queries: ' + (endQueries - startQueries) + ' / 100 (' + ((endQueries - startQueries) * 100 / 100) + '%)'); System.debug(' DML Statements: ' + (endDml - startDml) + ' / 150 (' + ((endDml - startDml) * 100 / 150) + '%)'); System.debug(' DML Rows: ' + endDmlRows + ' / 10000 (' + (endDmlRows * 100 / 10000) + '%)'); System.debug(' CPU Time (ms): ' + (endCpu - startCpu) + ' / 10000 (' + ((endCpu - startCpu) * 100 / 10000) + '%)'); System.debug(''); System.debug('🔄 BATCH RECOMMENDATIONS:'); System.debug(' Records can be processed in batches of 200 (default)'); System.debug(' This dataset would require ' + Math.ceil((Decimal)totalRecords / 200) + ' batch iterations'); System.debug(''); System.debug('═══════════════════════════════════════════════════════════════'); // ═══════════════════════════════════════════════════════════════════════════════ // CLEANUP SCRIPT // ═══════════════════════════════════════════════════════════════════════════════ /* CLEANUP - Run this after testing: DELETE [SELECT Id FROM Opportunity WHERE Name LIKE 'BatchTest%']; DELETE [SELECT Id FROM Contact WHERE LastName LIKE 'Contact_%' AND Email LIKE '%batchtest.example.com']; DELETE [SELECT Id FROM Account WHERE Name LIKE 'BatchTest%']; System.debug('Cleanup complete'); */ // ═══════════════════════════════════════════════════════════════════════════════ // OUTPUT FOR CLEANUP VIA SF CLI // ═══════════════════════════════════════════════════════════════════════════════ System.debug(''); System.debug('CLI Cleanup Commands:'); System.debug('sf data query --query "SELECT Id FROM Account WHERE Name LIKE \'BatchTest%\'" --target-org [alias] --result-format csv > cleanup-accounts.csv'); System.debug('sf data delete bulk --file cleanup-accounts.csv --sobject Account --target-org [alias] --wait 10');