Skip to main content

QPlanWriter Class

Zuora

QPlanWriter Class

This article describes the global methods in the QPlanWriter class. The QPlanWriter class is used to commit QPlan records to the Salesforce database. The QPlanWriter contains methods to create, update, or delete QuoteAmendment, QuoteRatePlan, QuoteRatePlanCharge, and QuoteChargeTier records based on the states of QPlans.

QPlanWriter Global Methods

The QPlanWriter class includes the following global methods.

Method Type Description
save(QPlan plan) void

Given a single QPlan instance, this method creates, deletes, or updates the SObject records for QuoteAmendment, QuoteRatePlan, QuoteRatePlanCharge or QuoteChargeTier when applicable.

Throws exceptions on invalid input.

save(List<QPlan> plans) void

Given a List of QPlan instances, this method creates, deletes, or updates the SObject records for QuoteAmendment, QuoteRatePlan, QuoteRatePlanCharge or QuoteChargeTier when applicable.

Throws exceptions on invalid input.

State Matrix

The state of a QPlan can be tracked by a combination of the values of isChanged(), isSaved(), isVoidAction(), and Amendment Type. According to the state represented by these four values, the QPlanWriter performs different actions when saving the QPlan.

  • isChanged: indicates whether or not any action has been taken on this QPlan since last retrieval.
  • AmendmentType: indicates the product action represented by this QPlan. It can be OriginalProduct, AddProduct, RemoveProduct, and UpdateProduct.
  • isSaved: indicates whether the QPlan currently exists in the database. A QPlan is saved if it has a Salesforce Id representing an action.
  • isVoidAction: indicates whether the action has been reverted. A VoidAction should be represented in the database the same way as it was initially loaded on the quote.
isChanged AmendmentType isSaved isVoidAction On Save Use Case
false * * *

No change.

No change made since last retrieval.

Products with isChanged as false are always ignored.

true AddProduct true true

Delete AddProduct Amendment.

Added product was removed.

false

Update AddProduct Amendment.

Added product was updated.

false true

No change.

New product was added, and then removed before saved.

false

Create AddProduct Amendment.

New product was added.

OriginalProduct false *

Invalid Data Exception.

Original Products should always keep the IsChanged false if they are not saved.

true false

Invalid Data Exception.

Original Products should always keep the isVoidAction true if they are saved and changed.

true

Delete Amendment.

Either an UpdateProduct Amendment or a RemoveProduct Amendment has been reverted.

UpdateProduct true true

Delete Amendment.

A reverted UpdateProduct is immediately converted to an OriginalProduct.

false

Update UpdateProduct Amendment.

Updated product was changed again.

false true

No change.

Original Product was updated, then reverted before being saved.

In this case, we assume isVoidAction indicates that the product is in its original state.

The isVoidAction flag should be reset in the model after the save action completes successfully.

false

Create UpdateProduct Amendment.

Original Product was updated.

RemoveProduct true true

Invalid Data Exception.

A reverted RemoveProduct is immediately converted to an OriginalProduct.

false

Delete UpdateProduct Amendment.

Create RemoveProduct Amendment.

Updated product was removed.

A Removed Product is not editable. The only actions that can be taken on it are reverting it, or editing a previously updated product.

false true

No change.

Original Product was removed, and then the removal was reverted before saved.

false

Create RemoveProduct amendment.

Original Product was removed.

 

After a successful Save action, the following adjustments are made against the QPlan model.

  • If isVoidAction is true,
    • isSaved becomes false when the record of the action has been deleted from the database.
    • isVoidAction becomes false when the database rollback is completed, and the state of the QPlan already represents the previous state.
    • isChanged becomes false when the QPlan model is in synchronization with the database.
  • If isVoidAction is false, 
    • isSaved becomes true when the record of the action has been saved.
    • isChanged becomes false when the QPlan model is in synchronization with the database.

Security Considerations

  • DML Operations run by QPlanWriter for the following objects will be executed in System mode. Implementation should ensure that only permissible fields can be overridden on QPlan and QCharge data as part of any implementation that invokes the save operation, prior to initiating a QPlanWriter.save() operation.
    • QuoteAmendment
    • QuoteRatePlan
    • QuoteRatePlanCharge
    • QuoteChargeTier
    • QuoteChargeSummary
  • Users must have Read and Create access to the following objects when triggering an action to Add, Update and Remove actions against Products on a Quote using QPlanReader and QPlanWriter.
    • QuoteAmendment
    • QuoteRatePlan
    • QuoteRatePlanCharge
    • QuoteChargeTier
    • QuoteChargeSummary

Sample Code

Add Products to a New Quote

public void test(Id quoteId, List<Id> productRatePlanId) {
    // Construct a plan from Catalog.
    List<zqu.QPlan> newPlan = zqu.QPlanBuilder.makeFromCatalog(quoteId, productRatePlanId);

    // Add and save.
    System.assertEquals('NewProduct', newPlan[0].getAmendment().get('zqu__Type__c'));
    System.assertEquals(true, newPlan[0].isChanged());
    System.assertEquals(false, newPlan[0].isSaved());
 
    zqu.QPlanWriter.save(newPlan);
    System.assertEquals(false, newPlan[0].isChanged());
    System.assertEquals(true, newPlan[0].isSaved());
 
    // Remove and save.
    newPlan[0].remove();
    System.assertEquals(true, newPlan[0].isChanged());
    System.assertEquals(true, newPlan[0].isSaved());
 
    zqu.QPlanWriter.save(newPlan);
    System.assertEquals(false, newPlan[0].isChanged());
    System.assertEquals(false, newPlan[0].isSaved());
}

Update Products on an Amendment Quote

public void test(Id quoteId, Decimal newPrice) {
    // Get Existing Subscription Products
    List<zqu.QPlan> plans = zqu.QPlanReader.load(quoteId);
    zqu.QPlan existingPlan = plans[0];
 
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
 
    // Update and save.
     List<zqu.QCharge> charges = existingPlan.getCharges();
    charges[0].put('zqu__EffectivePrice__c', newPrice);
    System.assertEquals('UpdateProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(true, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
 
    zqu.QPlanWriter.save(existingPlan);
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(true, existingPlan.isSaved());
 
 
    // Revert and save.
    existingPlan.revert();
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(true, existingPlan.isChanged());
    System.assertEquals(true, existingPlan.isSaved());
 
    zqu.QPlanWriter.save(existingPlan);
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
}

Remove Products on an Amendment Quote

public void test(Id quoteId) {
    // Get Existing Subscription Products
    List<zqu.QPlan> plans = zqu.QPlanReader.load(quoteId);
    zqu.QPlan existingPlan = plans[0];
 
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
 
    // Remove and save.
    existingPlan.remove();
    System.assertEquals('RemoveProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(true, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
 
    zqu.QPlanWriter.save(existingPlan);
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(true, existingPlan.isSaved());
 
 
    // Revert and save.
    existingPlan.revert();
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(true, existingPlan.isChanged());
    System.assertEquals(true, existingPlan.isSaved());
 
    zqu.QPlanWriter.save(existingPlan);
    System.assertEquals('OriginalProduct', existingPlan.getAmendment().get('zqu__Type__c'));
    System.assertEquals(false, existingPlan.isChanged());
    System.assertEquals(false, existingPlan.isSaved());
}