mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Add syntheticCreationTime to BillingEvent.OneTime
In order to clean up potentially bad BillingEvent.Recurring expansions, we'll need to be able to trace synthetic billing events back to particular runs of the []. This field will be set to the cursor time at the start of the MR (all expansions in one MR job will have the same timestamp). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=121999938
This commit is contained in:
parent
d62da7bb19
commit
51362722cd
4 changed files with 76 additions and 18 deletions
|
@ -216,6 +216,15 @@ public abstract class BillingEvent extends ImmutableObject
|
|||
@IgnoreSave(IfNull.class)
|
||||
Integer periodYears = null;
|
||||
|
||||
/**
|
||||
* For {@link Flag#SYNTHETIC} events, when this event was persisted to datastore (i.e. the
|
||||
* cursor position at the time the recurrence expansion job was last run). In the event a job
|
||||
* needs to be undone, a query on this field will return the complete set of potentially bad
|
||||
* events.
|
||||
*/
|
||||
@Index
|
||||
DateTime syntheticCreationTime;
|
||||
|
||||
public Money getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
@ -228,6 +237,10 @@ public abstract class BillingEvent extends ImmutableObject
|
|||
return periodYears;
|
||||
}
|
||||
|
||||
public DateTime getSyntheticCreationTime() {
|
||||
return syntheticCreationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
|
@ -259,6 +272,11 @@ public abstract class BillingEvent extends ImmutableObject
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setSyntheticCreationTime(DateTime syntheticCreationTime) {
|
||||
getInstance().syntheticCreationTime = syntheticCreationTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OneTime build() {
|
||||
OneTime instance = getInstance();
|
||||
|
@ -270,6 +288,10 @@ public abstract class BillingEvent extends ImmutableObject
|
|||
checkState(
|
||||
reasonsWithPeriods.contains(instance.reason) == (instance.periodYears != null),
|
||||
"Period years must be set if and only if reason is CREATE, RENEW, or TRANSFER.");
|
||||
checkState(
|
||||
instance.getFlags().contains(Flag.SYNTHETIC)
|
||||
== (instance.syntheticCreationTime != null),
|
||||
"Billing events with SYNTHETIC flag set must have a synthetic creation time.");
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public class BillingEventTest extends EntityTestCase {
|
|||
HistoryEntry historyEntry2;
|
||||
DomainResource domain;
|
||||
BillingEvent.OneTime oneTime;
|
||||
BillingEvent.OneTime oneTimeSynthetic;
|
||||
BillingEvent.Recurring recurring;
|
||||
BillingEvent.Cancellation cancellationOneTime;
|
||||
BillingEvent.Cancellation cancellationRecurring;
|
||||
|
@ -84,6 +85,16 @@ public class BillingEventTest extends EntityTestCase {
|
|||
.setCost(Money.of(USD, 1))
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now.plusDays(5))));
|
||||
oneTimeSynthetic = persistResource(commonInit(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setParent(historyEntry)
|
||||
.setReason(Reason.CREATE)
|
||||
.setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT, BillingEvent.Flag.SYNTHETIC))
|
||||
.setSyntheticCreationTime(now.plusDays(10))
|
||||
.setPeriodYears(2)
|
||||
.setCost(Money.of(USD, 1))
|
||||
.setEventTime(now)
|
||||
.setBillingTime(now.plusDays(5))));
|
||||
recurring = persistResource(commonInit(
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setParent(historyEntry)
|
||||
|
@ -136,7 +147,7 @@ public class BillingEventTest extends EntityTestCase {
|
|||
// Note that these are all tested separately because BillingEvent is an abstract base class that
|
||||
// lacks the @Entity annotation, and thus we cannot call .type(BillingEvent.class)
|
||||
assertThat(ofy().load().type(BillingEvent.OneTime.class).ancestor(domain).list())
|
||||
.containsExactly(oneTime);
|
||||
.containsExactly(oneTime, oneTimeSynthetic);
|
||||
assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(domain).list())
|
||||
.containsExactly(recurring);
|
||||
assertThat(ofy().load().type(BillingEvent.Cancellation.class).ancestor(domain).list())
|
||||
|
@ -144,7 +155,7 @@ public class BillingEventTest extends EntityTestCase {
|
|||
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domain).list())
|
||||
.containsExactly(modification);
|
||||
assertThat(ofy().load().type(BillingEvent.OneTime.class).ancestor(historyEntry).list())
|
||||
.containsExactly(oneTime);
|
||||
.containsExactly(oneTime, oneTimeSynthetic);
|
||||
assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(historyEntry).list())
|
||||
.containsExactly(recurring);
|
||||
assertThat(ofy().load().type(BillingEvent.Cancellation.class).ancestor(historyEntry2).list())
|
||||
|
@ -155,13 +166,35 @@ public class BillingEventTest extends EntityTestCase {
|
|||
|
||||
@Test
|
||||
public void testIndexing() throws Exception {
|
||||
verifyIndexing(oneTime, "clientId", "eventTime", "billingTime");
|
||||
verifyIndexing(oneTime, "clientId", "eventTime", "billingTime", "syntheticCreationTime");
|
||||
verifyIndexing(
|
||||
oneTimeSynthetic, "clientId", "eventTime", "billingTime", "syntheticCreationTime");
|
||||
verifyIndexing(
|
||||
recurring, "clientId", "eventTime", "recurrenceEndTime", "recurrenceTimeOfYear.timeString");
|
||||
verifyIndexing(cancellationOneTime, "clientId", "eventTime", "billingTime");
|
||||
verifyIndexing(modification, "clientId", "eventTime");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_syntheticFlagWithoutCreationTime() {
|
||||
thrown.expect(
|
||||
IllegalStateException.class,
|
||||
"Billing events with SYNTHETIC flag set must have a synthetic creation time");
|
||||
oneTime.asBuilder()
|
||||
.setFlags(ImmutableSet.of(BillingEvent.Flag.SYNTHETIC))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_syntheticCreationTimeWithoutFlag() {
|
||||
thrown.expect(
|
||||
IllegalStateException.class,
|
||||
"Billing events with SYNTHETIC flag set must have a synthetic creation time");
|
||||
oneTime.asBuilder()
|
||||
.setSyntheticCreationTime(now.plusDays(10))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_cancellation_forGracePeriod_withOneTime() {
|
||||
BillingEvent.Cancellation newCancellation = BillingEvent.Cancellation.forGracePeriod(
|
||||
|
|
|
@ -25,28 +25,28 @@ public class DeleteDomainCommandTest extends EppToolCommandTestCase<DeleteDomain
|
|||
public void testSuccess() throws Exception {
|
||||
runCommand("--client=NewRegistrar", "--domain_name=example.tld", "--force",
|
||||
"--reason=Test");
|
||||
new EppVerifier().verifySent("testdata/domain_delete.xml");
|
||||
eppVerifier().verifySent("testdata/domain_delete.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_multipleWordReason() throws Exception {
|
||||
runCommand("--client=NewRegistrar", "--domain_name=example.tld", "--force",
|
||||
"--reason=\"Test test\"");
|
||||
new EppVerifier().verifySent("testdata/domain_delete_multiple_word_reason.xml");
|
||||
eppVerifier().verifySent("testdata/domain_delete_multiple_word_reason.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_requestedByRegistrarFalse() throws Exception {
|
||||
runCommand("--client=NewRegistrar", "--domain_name=example.tld", "--force",
|
||||
"--reason=Test", "--registrar_request=false");
|
||||
new EppVerifier().verifySent("testdata/domain_delete.xml");
|
||||
eppVerifier().verifySent("testdata/domain_delete.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_requestedByRegistrarTrue() throws Exception {
|
||||
runCommand("--client=NewRegistrar", "--domain_name=example.tld", "--force",
|
||||
"--reason=Test", "--registrar_request=true");
|
||||
new EppVerifier().verifySent("testdata/domain_delete_by_registrar.xml");
|
||||
eppVerifier().verifySent("testdata/domain_delete_by_registrar.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -67,29 +67,32 @@ public abstract class EppToolCommandTestCase<C extends EppToolCommand> extends C
|
|||
|
||||
/** Helper to get a new {@link EppVerifier} instance. */
|
||||
EppVerifier eppVerifier() {
|
||||
return new EppVerifier();
|
||||
return new EppVerifier("NewRegistrar", false, false);
|
||||
}
|
||||
|
||||
/** Builder pattern class for verifying EPP commands sent to the server. */
|
||||
/** Class for verifying EPP commands sent to the server. */
|
||||
class EppVerifier {
|
||||
|
||||
String clientIdentifier = "NewRegistrar";
|
||||
boolean superuser = false;
|
||||
boolean dryRun = false;
|
||||
private final String clientIdentifier;
|
||||
private final boolean superuser;
|
||||
private final boolean dryRun;
|
||||
|
||||
private EppVerifier(String clientIdentifier, boolean superuser, boolean dryRun) {
|
||||
this.clientIdentifier = clientIdentifier;
|
||||
this.superuser = superuser;
|
||||
this.dryRun = dryRun;
|
||||
}
|
||||
|
||||
EppVerifier setClientIdentifier(String clientIdentifier) {
|
||||
this.clientIdentifier = clientIdentifier;
|
||||
return this;
|
||||
return new EppVerifier(clientIdentifier, superuser, dryRun);
|
||||
}
|
||||
|
||||
EppVerifier asSuperuser() {
|
||||
this.superuser = true;
|
||||
return this;
|
||||
return new EppVerifier(clientIdentifier, true, dryRun);
|
||||
}
|
||||
|
||||
EppVerifier asDryRun() {
|
||||
this.dryRun = true;
|
||||
return this;
|
||||
return new EppVerifier(clientIdentifier, superuser, true);
|
||||
}
|
||||
|
||||
void verifySent(String... filesToMatch) throws Exception {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue