diff --git a/java/google/registry/flows/ResourceFlowUtils.java b/java/google/registry/flows/ResourceFlowUtils.java
index 6450779d5..946c18a28 100644
--- a/java/google/registry/flows/ResourceFlowUtils.java
+++ b/java/google/registry/flows/ResourceFlowUtils.java
@@ -217,6 +217,60 @@ public class ResourceFlowUtils {
}
}
+ /**
+ * Turn a resource into a builder with its pending transfer resolved.
+ *
+ *
This removes the {@link StatusValue#PENDING_TRANSFER} status, sets the
+ * {@link TransferStatus}, clears all the server-approve fields on the {@link TransferData}
+ * including the extended registration years field, and sets the expiration time of the last
+ * pending transfer to now.
+ */
+ @SuppressWarnings("unchecked")
+ private static EppResource.Builder resolvePendingTransfer(
+ R resource, TransferStatus transferStatus, DateTime now) {
+ return (EppResource.Builder) resource.asBuilder()
+ .removeStatusValue(StatusValue.PENDING_TRANSFER)
+ .setTransferData(resource.getTransferData().asBuilder()
+ .setExtendedRegistrationYears(null)
+ .setServerApproveEntities(null)
+ .setServerApproveBillingEvent(null)
+ .setServerApproveAutorenewEvent(null)
+ .setServerApproveAutorenewPollMessage(null)
+ .setTransferStatus(transferStatus)
+ .setPendingTransferExpirationTime(now)
+ .build());
+ }
+
+ /**
+ * Resolve a pending transfer by awarding it to the gaining client.
+ *
+ *
This removes the {@link StatusValue#PENDING_TRANSFER} status, sets the
+ * {@link TransferStatus}, clears all the server-approve fields on the {@link TransferData}
+ * including the extended registration years field, and sets the expiration time of the last
+ * pending transfer to now.
+ */
+ public static R approvePendingTransfer(
+ R resource, TransferStatus transferStatus, DateTime now) {
+ Builder builder = resolvePendingTransfer(resource, transferStatus, now);
+ builder
+ .setLastTransferTime(now)
+ .setCurrentSponsorClientId(resource.getTransferData().getGainingClientId());
+ return builder.build();
+ }
+
+ /**
+ * Resolve a pending transfer by denying it.
+ *
+ *
This removes the {@link StatusValue#PENDING_TRANSFER} status, sets the
+ * {@link TransferStatus}, clears all the server-approve fields on the {@link TransferData}
+ * including the extended registration years field, sets the new client id, and sets the last
+ * transfer time and the expiration time of the last pending transfer to now.
+ */
+ public static R denyPendingTransfer(
+ R resource, TransferStatus transferStatus, DateTime now) {
+ return resolvePendingTransfer(resource, transferStatus, now).build();
+ }
+
/** The specified resource belongs to another client. */
public static class ResourceNotOwnedException extends AuthorizationErrorException {
public ResourceNotOwnedException() {
diff --git a/java/google/registry/flows/contact/ContactTransferApproveFlow.java b/java/google/registry/flows/contact/ContactTransferApproveFlow.java
index 406cce245..66aa588d5 100644
--- a/java/google/registry/flows/contact/ContactTransferApproveFlow.java
+++ b/java/google/registry/flows/contact/ContactTransferApproveFlow.java
@@ -14,6 +14,7 @@
package google.registry.flows.contact;
+import static google.registry.flows.ResourceFlowUtils.approvePendingTransfer;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
@@ -38,6 +39,7 @@ import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry;
+import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferStatus;
import javax.inject.Inject;
@@ -70,15 +72,13 @@ public class ContactTransferApproveFlow extends LoggedInFlow implements Transact
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
- if (existingResource.getTransferData().getTransferStatus() != TransferStatus.PENDING) {
+ TransferData transferData = existingResource.getTransferData();
+ if (transferData.getTransferStatus() != TransferStatus.PENDING) {
throw new NotPendingTransferException(targetId);
}
verifyResourceOwnership(clientId, existingResource);
- ContactResource newResource = existingResource.asBuilder()
- .clearPendingTransfer(TransferStatus.CLIENT_APPROVED, now)
- .setLastTransferTime(now)
- .setCurrentSponsorClientId(existingResource.getTransferData().getGainingClientId())
- .build();
+ ContactResource newResource =
+ approvePendingTransfer(existingResource, TransferStatus.CLIENT_APPROVED, now);
HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.CONTACT_TRANSFER_APPROVE)
.setModificationTime(now)
@@ -90,7 +90,7 @@ public class ContactTransferApproveFlow extends LoggedInFlow implements Transact
ofy().save().