4

I'm in the process of bringing the all API versions up to the current release in an old project and have run into a breaking change with how OpportunityLineItemSchedule records are created.

In v37.0 and earlier if an OpportunityLineItem record is inserted in an Apex test case where the related Product2 record has CanUseRevenueSchedule set to true and the Default Revenue schedule fields are set the OpportunityLineItemSchedule records get created automatically inserted by my OpportunityLineItem trigger that detects HasRevenueSchedule is false but the Product2 has schedules enabled.

However, when I push the test classes API version to or past v38.0 this behavior changes. The OpportunityLineItemSchedule records are no longer created as HasRevenueSchedule field is true in the trigger. All sorts of assertions start failing unless I pull the API version back.

I see the following in the documentation for OpportunityLineItemSchedule:

In API version 38.0 and later, when an OpportunityLineItem record is created for a product with a previously established schedule, an OpportunityLineItemSchedule record is also created.

This seems to be the opposite of my findings, unless I'm reading the docs incorrectly.

The Winter `17 release notes also have Add Products with Schedules in Lightning Experience:

Add products with revenue or quantity schedules to opportunities anywhere, any time. When your reps add a product with an established revenue or quantity schedule, the established schedule is added to the opportunity line item. This feature is available in Lightning Experience and all versions of the Salesforce1 mobile app.

I'm not touching the UI in this case. It's pure Apex code and tests.

What is confusing is that this works fine in anonymous Apex, but fails in a test context.

Why aren't the OpportunityLineItemSchedule records being created in a test context with v38.0 and later even though HasRevenueSchedule is true?

Note that I had a trigger on OpportunityLineItem in the original org that was showing OpportunityLineItem.HasRevenueSchedule as true during insertion. Yet the schedules were nowhere to be found.

Repo:

Scratch org created using settings:

"productSettings" : {
    "enableRevenueSchedule": true
}

Anonymous Apex that runs fine (including failing on the intentional rollback assertion):

Product2 testProduct = new Product2();
testProduct.Name = 'Test';
testProduct.CanUseRevenueSchedule = true;
testProduct.RevenueScheduleType = 'Divide';
testProduct.RevenueInstallmentPeriod = 'Daily';
testProduct.NumberOfRevenueInstallments = 1;
insert testProduct;

Id standardPricebookId = [Select Id from Pricebook2 where IsStandard = true].Id;

Opportunity opp = new Opportunity();
opp.Name = 'Test';
opp.StageName = 'Closed/Won';
opp.CloseDate = DateTime.now().date();
opp.Pricebook2Id = standardPricebookId;
insert opp;

PricebookEntry pbe = new PricebookEntry();
pbe.Product2Id = testProduct.Id;
pbe.Pricebook2Id = standardPricebookId;
pbe.UnitPrice = 1.0;
pbe.IsActive = true;
insert pbe;

OpportunityLineItem oli = new OpportunityLineItem();
oli.OpportunityId = opp.Id;
oli.Quantity = 100;
oli.TotalPrice = 700;
oli.PricebookEntryId = pbe.Id;
insert oli;

OpportunityLineItem oliAfter = [Select Id, HasRevenueSchedule from 
OpportunityLineItem where Id = :oli.Id];
System.assert(oliAfter.HasRevenueSchedule, 'Expected to have Revenue Schedule');

List<OpportunityLineItemSchedule> schedules = [select Id, Type, Revenue, ScheduleDate from OpportunityLineItemSchedule where OpportunityLineItemId = :oli.Id];
System.debug(schedules);

System.assertNotEquals(0, schedules.size());

System.assert(false, 'Rollback');

Almost identical Apex in a test class that fails (needed to switch out the standard pricebook2Id):

@IsTest
public class TestClass {
    @IsTest
    static void createSchedules() {
        Product2 testProduct = new Product2();
        testProduct.Name = 'Test';
        testProduct.CanUseRevenueSchedule = true;
        testProduct.RevenueScheduleType = 'Divide';
        testProduct.RevenueInstallmentPeriod = 'Daily';
        testProduct.NumberOfRevenueInstallments = 1;
        insert testProduct;

        Id standardPricebookId = Test.getStandardPricebookId();

        Opportunity opp = new Opportunity();
        opp.Name = 'Test';
        opp.StageName = 'Closed/Won';
        opp.CloseDate = DateTime.now().date();
        opp.Pricebook2Id = standardPricebookId;
        insert opp;

        PricebookEntry pbe = new PricebookEntry();
        pbe.Product2Id = testProduct.Id;
        pbe.Pricebook2Id = standardPricebookId;
        pbe.UnitPrice = 1.0;
        pbe.IsActive = true;
        insert pbe;

        OpportunityLineItem oli = new OpportunityLineItem();
        oli.OpportunityId = opp.Id;
        oli.Quantity = 100;
        oli.TotalPrice = 700;
        oli.PricebookEntryId = pbe.Id;
        insert oli;

        OpportunityLineItem oliAfter = [Select Id, HasRevenueSchedule from 
        OpportunityLineItem where Id = :oli.Id];
        System.assert(oliAfter.HasRevenueSchedule, 'Expected to have Revenue Schedule');

        List<OpportunityLineItemSchedule> schedules = [select Id, Type, Revenue, ScheduleDate from OpportunityLineItemSchedule where OpportunityLineItemId = :oli.Id];
        System.debug(schedules);

        System.assertNotEquals(0, schedules.size());
    }
}

Raised as support case #40555632 as this seems broken.

1

The outcome of the support case #40555632 is that this is a bug. It has been logged as W-9044084. There isn't currently an ETA or a corresponding known issue to track it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.