# Precommit Plugin



The Precommit Plugin allows you to modify an entity before committing it and saving it in the system. Validation requests trigger the Precommit Plugin, followed by the [Validation Plugin](/configuration/plugins/validation). Once the entity is successfully validated, all changes will be committed and saved.

The following entity types can be modified by the Precommit Plugin:

| Entity              | Plugin Definition Level |
| ------------------- | ----------------------- |
| Accounts            | Tenant or product       |
| Quotes              | Tenant or product       |
| Policy Transactions | Tenant or product       |
| Payments            | Tenant                  |
| Disbursements       | Tenant                  |
| Delinquencies       | Tenant                  |

Implementation [#implementation]

The Precommit Plugin can be implemented by overriding the method corresponding to the entity type you wish to modify.

The method input object contains two fields:

* The entity
* A `trigger`, which specifies the request type that triggered the method

<Callout>
  The `trigger` value will always be `validate` or `manual` since we currently only support automatic executions triggered by a validation request and manual executions.
</Callout>

The method returns the modified entity.

Automatic Execution [#automatic-execution]

The Precommit Plugin will be executed automatically before entity validation requests if an implementation exists for the target entity type.

Manual Execution [#manual-execution]

The Precommit Plugin can be executed manually for quotes in the `draft` state by calling the <ApiLink name="precommitQuote">Invoke the precommit plugin for a draft quote</ApiLink> API endpoint, and for transactions in the `draft` or `initialized` state by calling the <ApiLink name="precommitTransaction">Invoke the precommit plugin for a draft or initialized transaction</ApiLink> API endpoint.

Examples [#examples]

Account [#account]

```java
// Modify the company name

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public CommercialAccount preCommit(CommercialAccountRequest commercialAccountRequest) {
        log.info("Account locator: {}", commercialAccountRequest.account().locator());
        log.info("Trigger: {}", commercialAccountRequest.trigger());

        CommercialAccount account = commercialAccountRequest.account();

        if (account.data().companyName() == null || account.data().companyName().isBlank()) {
            return account.toBuilder()
                    .data(account.data().toBuilder().companyName("Example Company Name").build())
                    .build();
        } else {
            return account;
        }
    }
}
```

Quote [#quote]

```java
// Modify driver numbers

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public CommercialAutoQuote preCommit(CommercialAutoQuoteRequest commercialAutoQuoteRequest) {
        log.info("Quote locator: {}", commercialAutoQuoteRequest.quote().locator());
        log.info("Trigger: {}", commercialAutoQuoteRequest.trigger());

        CommercialAutoQuote quote = commercialAutoQuoteRequest.quote();
        CommercialAutoQuote.CommercialAutoQuoteBuilder builder = quote.toBuilder();

        if (quote.driverSchedule() != null) {

            int driver_assignment_number = 1;
            Collection<DriverQuote> modified_driver_schedule_numbers = new ArrayList<>();

            for (DriverQuote driver : quote.driverSchedule().drivers()) {

                driver = driver.toBuilder()
                        .data(driver.data().toBuilder()
                                .driverNumber(Integer.toString(driver_assignment_number)).build())
                        .build();

                modified_driver_schedule_numbers.add(driver);
                driver_assignment_number++;
            }

            DriverScheduleQuote.DriverScheduleQuoteBuilder driverScheduleBuilder = quote.driverSchedule().toBuilder();
            driverScheduleBuilder.drivers(modified_driver_schedule_numbers);
            builder.driverSchedule(driverScheduleBuilder.build());

            return builder.build();

        } else {
            return quote;
        }
    }
}
```

Policy Transaction [#policy-transaction]

```java
// Modify change instructions for a transaction

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public PreCommitTransactionResponse preCommit(CommercialAutoTransactionRequest commercialAutoTransactionRequest) {
        log.info("Transaction locator: {}", commercialAutoTransactionRequest.transaction().locator());
        log.info("Trigger: {}", commercialAutoTransactionRequest.trigger());

        PreCommitTransactionResponse.PreCommitTransactionResponseBuilder builder = PreCommitTransactionResponse.builder();

        if (commercialAutoTransactionRequest.changeInstructions() != null) {
            builder.addChangeInstructions(commercialAutoTransactionRequest.changeInstructions());
        } else {
            ParamsChangeInstruction newParamsChangeInstruction = ParamsChangeInstruction.builder().effectiveTime(Instant.now()).build();
            ChangeInstructionHolder newChangeInstructionHolder = ChangeInstructionHolder.builder().paramsInstruction(newParamsChangeInstruction).build();

            builder.addChangeInstruction(newChangeInstructionHolder);
        }

        return builder.build();
    }
}
```

Payment [#payment]

```java
// Modify a payment note

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public StandardPayment preCommit(StandardPaymentRequest standardPaymentRequest) {
        log.info("Payment locator: {}", standardPaymentRequest.payment().locator());
        log.info("Trigger: {}", standardPaymentRequest.trigger());

        if (standardPaymentRequest.payment().data().note().equals("Change this payment note")) {

            StandardPayment payment = standardPaymentRequest.payment();

            return payment.toBuilder()
                    .data(payment.data().toBuilder().note("New payment note").build())
                    .build();
        } else {
            return standardPaymentRequest.payment();
        }
    }
}
```

Disbursement [#disbursement]

```java
// Modify a disbursement note

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public StandardDisbursement preCommit(StandardDisbursementRequest standardDisbursementRequest) {
        log.info("Disbursement locator: {}", standardDisbursementRequest.disbursement().locator());
        log.info("Trigger: {}", standardDisbursementRequest.trigger());

        if (standardDisbursementRequest.disbursement().data().note().equals("Change this disbursement note")) {

            StandardDisbursement disbursement = standardDisbursementRequest.disbursement();

            return disbursement.toBuilder()
                    .data(disbursement.data().toBuilder().note("New disbursement note").build())
                    .build();
        } else {
            return standardDisbursementRequest.disbursement();
        }
    }
}
```

Delinquency [#delinquency]

<Callout>
  Delinquency requests don't contain a `trigger` field, since the delinquency method is executed when a delinquency moves to the `inGrace` state.
</Callout>

```java
// Modify the grace period end date of a delinquency

public class Precommit implements PreCommitPlugin {
    private static final Logger log = LoggerFactory.getLogger(Precommit.class);

    @Override
    public PreCommitDelinquencyResponse preCommit(DelinquencyRequest delinquencyRequest) {
        log.info("Delinquency locator: {}", delinquencyRequest.delinquency().locator());

        return PreCommitDelinquencyResponse.builder()
                .graceEndAt(Instant.now().plus(30, ChronoUnit.DAYS))
                .settings(delinquencyRequest.delinquency().settings())
                .build();
    }
}
```

Next Steps [#next-steps]

* [Validation Plugin](/configuration/plugins/validation)

See Also [#see-also]

* [Plugins Overview](/configuration/plugins/overview)
* [Quotes API](/api/quotes/quotes)
* [Policy Transactions API](/api/policy-management/policy-transactions)
