mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 04:09:46 +02:00
Generate sql schema for BillingEvent (#565)
* Generate sql schema for BillingEvent * Change to use sequence * Address comments * Resolve warnings and remove duplicate cost related fields * Increase the flayway file version to V25 * Remove extra space * Split to 3 tables, merge VKey * Rename talbes * Rename repoId to domainRepoId * Exclude VKey in schema.txt * Rename target_id to domain_name * Fix javadoc * Resolve comments
This commit is contained in:
parent
02e43ab134
commit
cf092c7e50
22 changed files with 941 additions and 179 deletions
|
@ -155,89 +155,100 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||||
}
|
}
|
||||||
int numBillingEventsSaved = 0;
|
int numBillingEventsSaved = 0;
|
||||||
try {
|
try {
|
||||||
numBillingEventsSaved = tm().transactNew(() -> {
|
numBillingEventsSaved =
|
||||||
ImmutableSet.Builder<OneTime> syntheticOneTimesBuilder =
|
tm().transactNew(
|
||||||
new ImmutableSet.Builder<>();
|
() -> {
|
||||||
final Registry tld = Registry.get(getTldFromDomainName(recurring.getTargetId()));
|
ImmutableSet.Builder<OneTime> syntheticOneTimesBuilder =
|
||||||
|
new ImmutableSet.Builder<>();
|
||||||
|
final Registry tld =
|
||||||
|
Registry.get(getTldFromDomainName(recurring.getTargetId()));
|
||||||
|
|
||||||
// Determine the complete set of times at which this recurring event should occur
|
// Determine the complete set of times at which this recurring event should
|
||||||
// (up to and including the runtime of the mapreduce).
|
// occur (up to and including the runtime of the mapreduce).
|
||||||
Iterable<DateTime> eventTimes =
|
Iterable<DateTime> eventTimes =
|
||||||
recurring.getRecurrenceTimeOfYear().getInstancesInRange(Range.closed(
|
recurring
|
||||||
recurring.getEventTime(),
|
.getRecurrenceTimeOfYear()
|
||||||
earliestOf(recurring.getRecurrenceEndTime(), executeTime)));
|
.getInstancesInRange(
|
||||||
|
Range.closed(
|
||||||
|
recurring.getEventTime(),
|
||||||
|
earliestOf(recurring.getRecurrenceEndTime(), executeTime)));
|
||||||
|
|
||||||
// Convert these event times to billing times
|
// Convert these event times to billing times
|
||||||
final ImmutableSet<DateTime> billingTimes =
|
final ImmutableSet<DateTime> billingTimes =
|
||||||
getBillingTimesInScope(eventTimes, cursorTime, executeTime, tld);
|
getBillingTimesInScope(eventTimes, cursorTime, executeTime, tld);
|
||||||
|
|
||||||
Key<? extends EppResource> domainKey = recurring.getParentKey().getParent();
|
Key<? extends EppResource> domainKey = recurring.getParentKey().getParent();
|
||||||
Iterable<OneTime> oneTimesForDomain =
|
Iterable<OneTime> oneTimesForDomain =
|
||||||
ofy().load().type(OneTime.class).ancestor(domainKey);
|
ofy().load().type(OneTime.class).ancestor(domainKey);
|
||||||
|
|
||||||
// Determine the billing times that already have OneTime events persisted.
|
// Determine the billing times that already have OneTime events persisted.
|
||||||
ImmutableSet<DateTime> existingBillingTimes =
|
ImmutableSet<DateTime> existingBillingTimes =
|
||||||
getExistingBillingTimes(oneTimesForDomain, recurring);
|
getExistingBillingTimes(oneTimesForDomain, recurring);
|
||||||
|
|
||||||
ImmutableSet.Builder<HistoryEntry> historyEntriesBuilder =
|
ImmutableSet.Builder<HistoryEntry> historyEntriesBuilder =
|
||||||
new ImmutableSet.Builder<>();
|
new ImmutableSet.Builder<>();
|
||||||
// Create synthetic OneTime events for all billing times that do not yet have an event
|
// Create synthetic OneTime events for all billing times that do not yet have
|
||||||
// persisted.
|
// an event persisted.
|
||||||
for (DateTime billingTime : difference(billingTimes, existingBillingTimes)) {
|
for (DateTime billingTime : difference(billingTimes, existingBillingTimes)) {
|
||||||
// Construct a new HistoryEntry that parents over the OneTime
|
// Construct a new HistoryEntry that parents over the OneTime
|
||||||
HistoryEntry historyEntry = new HistoryEntry.Builder()
|
HistoryEntry historyEntry =
|
||||||
.setBySuperuser(false)
|
new HistoryEntry.Builder()
|
||||||
.setClientId(recurring.getClientId())
|
.setBySuperuser(false)
|
||||||
.setModificationTime(tm().getTransactionTime())
|
.setClientId(recurring.getClientId())
|
||||||
.setParent(domainKey)
|
.setModificationTime(tm().getTransactionTime())
|
||||||
.setPeriod(Period.create(1, YEARS))
|
.setParent(domainKey)
|
||||||
.setReason("Domain autorenewal by ExpandRecurringBillingEventsAction")
|
.setPeriod(Period.create(1, YEARS))
|
||||||
.setRequestedByRegistrar(false)
|
.setReason(
|
||||||
.setType(DOMAIN_AUTORENEW)
|
"Domain autorenewal by ExpandRecurringBillingEventsAction")
|
||||||
// Don't write a domain transaction record if the recurrence was ended prior to the
|
.setRequestedByRegistrar(false)
|
||||||
// billing time (i.e. a domain was deleted during the autorenew grace period).
|
.setType(DOMAIN_AUTORENEW)
|
||||||
.setDomainTransactionRecords(
|
// Don't write a domain transaction record if the recurrence was
|
||||||
recurring.getRecurrenceEndTime().isBefore(billingTime)
|
// ended prior to the billing time (i.e. a domain was deleted
|
||||||
? ImmutableSet.of()
|
// during the autorenew grace period).
|
||||||
: ImmutableSet.of(
|
.setDomainTransactionRecords(
|
||||||
DomainTransactionRecord.create(
|
recurring.getRecurrenceEndTime().isBefore(billingTime)
|
||||||
tld.getTldStr(),
|
? ImmutableSet.of()
|
||||||
// We report this when the autorenew grace period ends
|
: ImmutableSet.of(
|
||||||
billingTime,
|
DomainTransactionRecord.create(
|
||||||
TransactionReportField.netRenewsFieldFromYears(1),
|
tld.getTldStr(),
|
||||||
1)))
|
// We report this when the autorenew grace period
|
||||||
.build();
|
// ends
|
||||||
historyEntriesBuilder.add(historyEntry);
|
billingTime,
|
||||||
|
TransactionReportField.netRenewsFieldFromYears(1),
|
||||||
|
1)))
|
||||||
|
.build();
|
||||||
|
historyEntriesBuilder.add(historyEntry);
|
||||||
|
|
||||||
DateTime eventTime = billingTime.minus(tld.getAutoRenewGracePeriodLength());
|
DateTime eventTime = billingTime.minus(tld.getAutoRenewGracePeriodLength());
|
||||||
// Determine the cost for a one-year renewal.
|
// Determine the cost for a one-year renewal.
|
||||||
Money renewCost = getDomainRenewCost(recurring.getTargetId(), eventTime, 1);
|
Money renewCost = getDomainRenewCost(recurring.getTargetId(), eventTime, 1);
|
||||||
syntheticOneTimesBuilder.add(new OneTime.Builder()
|
syntheticOneTimesBuilder.add(
|
||||||
.setBillingTime(billingTime)
|
new OneTime.Builder()
|
||||||
.setClientId(recurring.getClientId())
|
.setBillingTime(billingTime)
|
||||||
.setCost(renewCost)
|
.setClientId(recurring.getClientId())
|
||||||
.setEventTime(eventTime)
|
.setCost(renewCost)
|
||||||
.setFlags(union(recurring.getFlags(), Flag.SYNTHETIC))
|
.setEventTime(eventTime)
|
||||||
.setParent(historyEntry)
|
.setFlags(union(recurring.getFlags(), Flag.SYNTHETIC))
|
||||||
.setPeriodYears(1)
|
.setParent(historyEntry)
|
||||||
.setReason(recurring.getReason())
|
.setPeriodYears(1)
|
||||||
.setSyntheticCreationTime(executeTime)
|
.setReason(recurring.getReason())
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setSyntheticCreationTime(executeTime)
|
||||||
.setTargetId(recurring.getTargetId())
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
.build());
|
.setTargetId(recurring.getTargetId())
|
||||||
}
|
.build());
|
||||||
Set<HistoryEntry> historyEntries = historyEntriesBuilder.build();
|
}
|
||||||
Set<OneTime> syntheticOneTimes = syntheticOneTimesBuilder.build();
|
Set<HistoryEntry> historyEntries = historyEntriesBuilder.build();
|
||||||
if (!isDryRun) {
|
Set<OneTime> syntheticOneTimes = syntheticOneTimesBuilder.build();
|
||||||
ImmutableSet<ImmutableObject> entitiesToSave =
|
if (!isDryRun) {
|
||||||
new ImmutableSet.Builder<ImmutableObject>()
|
ImmutableSet<ImmutableObject> entitiesToSave =
|
||||||
.addAll(historyEntries)
|
new ImmutableSet.Builder<ImmutableObject>()
|
||||||
.addAll(syntheticOneTimes)
|
.addAll(historyEntries)
|
||||||
.build();
|
.addAll(syntheticOneTimes)
|
||||||
ofy().save().entities(entitiesToSave).now();
|
.build();
|
||||||
}
|
ofy().save().entities(entitiesToSave).now();
|
||||||
return syntheticOneTimes.size();
|
}
|
||||||
});
|
return syntheticOneTimes.size();
|
||||||
|
});
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
getContext().incrementCounter("error: " + t.getClass().getSimpleName());
|
getContext().incrementCounter("error: " + t.getClass().getSimpleName());
|
||||||
getContext().incrementCounter(ERROR_COUNTER);
|
getContext().incrementCounter(ERROR_COUNTER);
|
||||||
|
@ -279,7 +290,8 @@ public class ExpandRecurringBillingEventsAction implements Runnable {
|
||||||
return Streams.stream(oneTimesForDomain)
|
return Streams.stream(oneTimesForDomain)
|
||||||
.filter(
|
.filter(
|
||||||
billingEvent ->
|
billingEvent ->
|
||||||
Key.create(recurringEvent)
|
recurringEvent
|
||||||
|
.createVKey()
|
||||||
.equals(billingEvent.getCancellationMatchingBillingEvent()))
|
.equals(billingEvent.getCancellationMatchingBillingEvent()))
|
||||||
.map(OneTime::getBillingTime)
|
.map(OneTime::getBillingTime)
|
||||||
.collect(toImmutableSet());
|
.collect(toImmutableSet());
|
||||||
|
|
|
@ -534,7 +534,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
.setPeriodYears(years)
|
.setPeriodYears(years)
|
||||||
.setCost(feesAndCredits.getCreateCost())
|
.setCost(feesAndCredits.getCreateCost())
|
||||||
.setEventTime(now)
|
.setEventTime(now)
|
||||||
.setAllocationToken(allocationToken.map(Key::create).orElse(null))
|
.setAllocationToken(allocationToken.map(AllocationToken::createVKey).orElse(null))
|
||||||
.setBillingTime(
|
.setBillingTime(
|
||||||
now.plus(
|
now.plus(
|
||||||
isAnchorTenant
|
isAnchorTenant
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.annotation.Id;
|
import com.googlecode.objectify.annotation.Id;
|
||||||
import com.googlecode.objectify.annotation.Ignore;
|
import com.googlecode.objectify.annotation.Ignore;
|
||||||
import com.googlecode.objectify.annotation.Parent;
|
import com.googlecode.objectify.annotation.Parent;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
@ -139,10 +140,13 @@ public class ModelUtils {
|
||||||
|
|
||||||
// If the field's type is the same as the field's class object, then it's a non-parameterized
|
// If the field's type is the same as the field's class object, then it's a non-parameterized
|
||||||
// type, and thus we just add it directly. We also don't bother looking at the parameterized
|
// type, and thus we just add it directly. We also don't bother looking at the parameterized
|
||||||
// types of Key objects, since they are just references to other objects and don't actually
|
// types of Key and VKey objects, since they are just references to other objects and don't
|
||||||
// embed themselves in the persisted object anyway.
|
// actually embed themselves in the persisted object anyway.
|
||||||
Class<?> fieldClazz = field.getType();
|
Class<?> fieldClazz = field.getType();
|
||||||
Type fieldType = field.getGenericType();
|
Type fieldType = field.getGenericType();
|
||||||
|
if (VKey.class.equals(fieldClazz)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
builder.add(fieldClazz);
|
builder.add(fieldClazz);
|
||||||
if (fieldType.equals(fieldClazz) || Key.class.equals(clazz)) {
|
if (fieldType.equals(fieldClazz) || Key.class.equals(clazz)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.google.common.collect.Sets;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.annotation.Entity;
|
import com.googlecode.objectify.annotation.Entity;
|
||||||
import com.googlecode.objectify.annotation.Id;
|
import com.googlecode.objectify.annotation.Id;
|
||||||
|
import com.googlecode.objectify.annotation.Ignore;
|
||||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||||
import com.googlecode.objectify.annotation.Index;
|
import com.googlecode.objectify.annotation.Index;
|
||||||
import com.googlecode.objectify.annotation.Parent;
|
import com.googlecode.objectify.annotation.Parent;
|
||||||
|
@ -43,14 +44,28 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import google.registry.persistence.WithLongVKey;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.AttributeOverride;
|
||||||
|
import javax.persistence.AttributeOverrides;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.persistence.Transient;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/** A billable event in a domain's lifecycle. */
|
/** A billable event in a domain's lifecycle. */
|
||||||
|
@MappedSuperclass
|
||||||
|
@WithLongVKey
|
||||||
public abstract class BillingEvent extends ImmutableObject
|
public abstract class BillingEvent extends ImmutableObject
|
||||||
implements Buildable, TransferServerApproveEntity {
|
implements Buildable, TransferServerApproveEntity {
|
||||||
|
|
||||||
|
@ -93,24 +108,41 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
|
|
||||||
/** Entity id. */
|
/** Entity id. */
|
||||||
@Id
|
@Id
|
||||||
long id;
|
@javax.persistence.Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
Long id;
|
||||||
|
|
||||||
@Parent
|
@Parent @DoNotHydrate @Transient Key<HistoryEntry> parent;
|
||||||
@DoNotHydrate
|
|
||||||
Key<HistoryEntry> parent;
|
|
||||||
|
|
||||||
/** The registrar to bill. */
|
/** The registrar to bill. */
|
||||||
@Index
|
@Index
|
||||||
|
@Column(nullable = false)
|
||||||
String clientId;
|
String clientId;
|
||||||
|
|
||||||
|
/** Revision id of the entry in DomainHistory table that ths bill belongs to. */
|
||||||
|
// TODO(shicong): Add foreign key constraint when DomainHistory table is generated
|
||||||
|
@Ignore
|
||||||
|
@Column(nullable = false)
|
||||||
|
Long domainHistoryRevisionId;
|
||||||
|
|
||||||
|
/** ID of the EPP resource that the bill is for. */
|
||||||
|
// TODO(shicong): Add foreign key constraint when we expand DatastoreHelp for Postgresql
|
||||||
|
@Ignore
|
||||||
|
@Column(nullable = false)
|
||||||
|
String domainRepoId;
|
||||||
|
|
||||||
/** When this event was created. For recurring events, this is also the recurrence start time. */
|
/** When this event was created. For recurring events, this is also the recurrence start time. */
|
||||||
@Index
|
@Index
|
||||||
|
@Column(nullable = false)
|
||||||
DateTime eventTime;
|
DateTime eventTime;
|
||||||
|
|
||||||
/** The reason for the bill. */
|
/** The reason for the bill. */
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(nullable = false)
|
||||||
Reason reason;
|
Reason reason;
|
||||||
|
|
||||||
/** The fully qualified domain name of the domain that the bill is for. */
|
/** The fully qualified domain name of the domain that the bill is for. */
|
||||||
|
@Column(name = "domain_name", nullable = false)
|
||||||
String targetId;
|
String targetId;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -120,6 +152,14 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return clientId;
|
return clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getDomainHistoryRevisionId() {
|
||||||
|
return domainHistoryRevisionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDomainRepoId() {
|
||||||
|
return domainRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
public DateTime getEventTime() {
|
public DateTime getEventTime() {
|
||||||
return eventTime;
|
return eventTime;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +203,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public B setId(Long id) {
|
public B setId(long id) {
|
||||||
getInstance().id = id;
|
getInstance().id = id;
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
@ -173,6 +213,16 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public B setDomainHistoryRevisionId(long domainHistoryRevisionId) {
|
||||||
|
getInstance().domainHistoryRevisionId = domainHistoryRevisionId;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setDomainRepoId(String domainRepoId) {
|
||||||
|
getInstance().domainRepoId = domainRepoId;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
public B setEventTime(DateTime eventTime) {
|
public B setEventTime(DateTime eventTime) {
|
||||||
getInstance().eventTime = eventTime;
|
getInstance().eventTime = eventTime;
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
|
@ -194,6 +244,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
}
|
}
|
||||||
|
|
||||||
public B setParent(Key<HistoryEntry> parentKey) {
|
public B setParent(Key<HistoryEntry> parentKey) {
|
||||||
|
// TODO(shicong): Figure out how to set domainHistoryRevisionId and domainRepoId
|
||||||
getInstance().parent = parentKey;
|
getInstance().parent = parentKey;
|
||||||
return thisCastToDerived();
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
@ -213,9 +264,23 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
/** A one-time billable event. */
|
/** A one-time billable event. */
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
|
@javax.persistence.Entity(name = "BillingEvent")
|
||||||
|
@javax.persistence.Table(
|
||||||
|
indexes = {
|
||||||
|
@javax.persistence.Index(columnList = "clientId"),
|
||||||
|
@javax.persistence.Index(columnList = "eventTime"),
|
||||||
|
@javax.persistence.Index(columnList = "billingTime"),
|
||||||
|
@javax.persistence.Index(columnList = "syntheticCreationTime"),
|
||||||
|
@javax.persistence.Index(columnList = "allocation_token_id")
|
||||||
|
})
|
||||||
|
@AttributeOverride(name = "id", column = @Column(name = "billing_event_id"))
|
||||||
public static class OneTime extends BillingEvent {
|
public static class OneTime extends BillingEvent {
|
||||||
|
|
||||||
/** The billable value. */
|
/** The billable value. */
|
||||||
|
@AttributeOverrides({
|
||||||
|
@AttributeOverride(name = "money.amount", column = @Column(name = "cost_amount")),
|
||||||
|
@AttributeOverride(name = "money.currency", column = @Column(name = "cost_currency"))
|
||||||
|
})
|
||||||
Money cost;
|
Money cost;
|
||||||
|
|
||||||
/** When the cost should be billed. */
|
/** When the cost should be billed. */
|
||||||
|
@ -223,8 +288,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
DateTime billingTime;
|
DateTime billingTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The period in years of the action being billed for, if applicable, otherwise null.
|
* The period in years of the action being billed for, if applicable, otherwise null. Used for
|
||||||
* Used for financial reporting.
|
* financial reporting.
|
||||||
*/
|
*/
|
||||||
@IgnoreSave(IfNull.class)
|
@IgnoreSave(IfNull.class)
|
||||||
Integer periodYears = null;
|
Integer periodYears = null;
|
||||||
|
@ -240,15 +305,21 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For {@link Flag#SYNTHETIC} events, a {@link Key} to the {@link BillingEvent} from which this
|
* For {@link Flag#SYNTHETIC} events, a {@link Key} to the {@link BillingEvent} from which this
|
||||||
* OneTime was created. This is needed in order to properly match billing events against
|
* OneTime was created. This is needed in order to properly match billing events against {@link
|
||||||
* {@link Cancellation}s.
|
* Cancellation}s.
|
||||||
*/
|
*/
|
||||||
Key<? extends BillingEvent> cancellationMatchingBillingEvent;
|
@Column(name = "cancellation_matching_billing_recurrence_id")
|
||||||
|
VKey<? extends BillingEvent> cancellationMatchingBillingEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link AllocationToken} used in the creation of this event, or null if one was not used.
|
* The {@link AllocationToken} used in the creation of this event, or null if one was not used.
|
||||||
|
*
|
||||||
|
* <p>TODO(shicong): Add foreign key constraint when AllocationToken schema is generated
|
||||||
*/
|
*/
|
||||||
@Index @Nullable Key<AllocationToken> allocationToken;
|
@Column(name = "allocation_token_id")
|
||||||
|
@Index
|
||||||
|
@Nullable
|
||||||
|
VKey<AllocationToken> allocationToken;
|
||||||
|
|
||||||
public Money getCost() {
|
public Money getCost() {
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -266,14 +337,18 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return syntheticCreationTime;
|
return syntheticCreationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key<? extends BillingEvent> getCancellationMatchingBillingEvent() {
|
public VKey<? extends BillingEvent> getCancellationMatchingBillingEvent() {
|
||||||
return cancellationMatchingBillingEvent;
|
return cancellationMatchingBillingEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Key<AllocationToken>> getAllocationToken() {
|
public Optional<VKey<AllocationToken>> getAllocationToken() {
|
||||||
return Optional.ofNullable(allocationToken);
|
return Optional.ofNullable(allocationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VKey<OneTime> createVKey() {
|
||||||
|
return VKey.createOfy(getClass(), Key.create(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
|
@ -311,12 +386,12 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setCancellationMatchingBillingEvent(
|
public Builder setCancellationMatchingBillingEvent(
|
||||||
Key<? extends BillingEvent> cancellationMatchingBillingEvent) {
|
VKey<? extends BillingEvent> cancellationMatchingBillingEvent) {
|
||||||
getInstance().cancellationMatchingBillingEvent = cancellationMatchingBillingEvent;
|
getInstance().cancellationMatchingBillingEvent = cancellationMatchingBillingEvent;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setAllocationToken(@Nullable Key<AllocationToken> allocationToken) {
|
public Builder setAllocationToken(@Nullable VKey<AllocationToken> allocationToken) {
|
||||||
getInstance().allocationToken = allocationToken;
|
getInstance().allocationToken = allocationToken;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -361,6 +436,15 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
*/
|
*/
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
|
@javax.persistence.Entity(name = "BillingRecurrence")
|
||||||
|
@javax.persistence.Table(
|
||||||
|
indexes = {
|
||||||
|
@javax.persistence.Index(columnList = "clientId"),
|
||||||
|
@javax.persistence.Index(columnList = "eventTime"),
|
||||||
|
@javax.persistence.Index(columnList = "recurrenceEndTime"),
|
||||||
|
@javax.persistence.Index(columnList = "recurrence_time_of_year")
|
||||||
|
})
|
||||||
|
@AttributeOverride(name = "id", column = @Column(name = "billing_recurrence_id"))
|
||||||
public static class Recurring extends BillingEvent {
|
public static class Recurring extends BillingEvent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -384,6 +468,10 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
* model, whereas the billing time is a fixed {@link org.joda.time.Duration} later.
|
* model, whereas the billing time is a fixed {@link org.joda.time.Duration} later.
|
||||||
*/
|
*/
|
||||||
@Index
|
@Index
|
||||||
|
@Embedded
|
||||||
|
@AttributeOverrides({
|
||||||
|
@AttributeOverride(name = "timeString", column = @Column(name = "recurrence_time_of_year"))
|
||||||
|
})
|
||||||
TimeOfYear recurrenceTimeOfYear;
|
TimeOfYear recurrenceTimeOfYear;
|
||||||
|
|
||||||
public DateTime getRecurrenceEndTime() {
|
public DateTime getRecurrenceEndTime() {
|
||||||
|
@ -394,6 +482,10 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return recurrenceTimeOfYear;
|
return recurrenceTimeOfYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VKey<Recurring> createVKey() {
|
||||||
|
return VKey.createOfy(getClass(), Key.create(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
|
@ -434,6 +526,14 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
*/
|
*/
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
|
@javax.persistence.Entity(name = "BillingCancellation")
|
||||||
|
@javax.persistence.Table(
|
||||||
|
indexes = {
|
||||||
|
@javax.persistence.Index(columnList = "clientId"),
|
||||||
|
@javax.persistence.Index(columnList = "eventTime"),
|
||||||
|
@javax.persistence.Index(columnList = "billingTime")
|
||||||
|
})
|
||||||
|
@AttributeOverride(name = "id", column = @Column(name = "billing_cancellation_id"))
|
||||||
public static class Cancellation extends BillingEvent {
|
public static class Cancellation extends BillingEvent {
|
||||||
|
|
||||||
/** The billing time of the charge that is being cancelled. */
|
/** The billing time of the charge that is being cancelled. */
|
||||||
|
@ -446,7 +546,8 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
* <p>Although the type is {@link Key} the name "ref" is preserved for historical reasons.
|
* <p>Although the type is {@link Key} the name "ref" is preserved for historical reasons.
|
||||||
*/
|
*/
|
||||||
@IgnoreSave(IfNull.class)
|
@IgnoreSave(IfNull.class)
|
||||||
Key<BillingEvent.OneTime> refOneTime = null;
|
@Column(name = "billing_event_id")
|
||||||
|
VKey<BillingEvent.OneTime> refOneTime = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recurring billing event to cancel, or null for non-autorenew cancellations.
|
* The recurring billing event to cancel, or null for non-autorenew cancellations.
|
||||||
|
@ -454,13 +555,14 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
* <p>Although the type is {@link Key} the name "ref" is preserved for historical reasons.
|
* <p>Although the type is {@link Key} the name "ref" is preserved for historical reasons.
|
||||||
*/
|
*/
|
||||||
@IgnoreSave(IfNull.class)
|
@IgnoreSave(IfNull.class)
|
||||||
Key<BillingEvent.Recurring> refRecurring = null;
|
@Column(name = "billing_recurrence_id")
|
||||||
|
VKey<BillingEvent.Recurring> refRecurring = null;
|
||||||
|
|
||||||
public DateTime getBillingTime() {
|
public DateTime getBillingTime() {
|
||||||
return billingTime;
|
return billingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key<? extends BillingEvent> getEventKey() {
|
public VKey<? extends BillingEvent> getEventKey() {
|
||||||
return firstNonNull(refOneTime, refRecurring);
|
return firstNonNull(refOneTime, refRecurring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,13 +594,19 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
.setParent(historyEntry);
|
.setParent(historyEntry);
|
||||||
// Set the grace period's billing event using the appropriate Cancellation builder method.
|
// Set the grace period's billing event using the appropriate Cancellation builder method.
|
||||||
if (gracePeriod.getOneTimeBillingEvent() != null) {
|
if (gracePeriod.getOneTimeBillingEvent() != null) {
|
||||||
builder.setOneTimeEventKey(gracePeriod.getOneTimeBillingEvent());
|
builder.setOneTimeEventKey(
|
||||||
|
VKey.createOfy(BillingEvent.OneTime.class, gracePeriod.getOneTimeBillingEvent()));
|
||||||
} else if (gracePeriod.getRecurringBillingEvent() != null) {
|
} else if (gracePeriod.getRecurringBillingEvent() != null) {
|
||||||
builder.setRecurringEventKey(gracePeriod.getRecurringBillingEvent());
|
builder.setRecurringEventKey(
|
||||||
|
VKey.createOfy(BillingEvent.Recurring.class, gracePeriod.getRecurringBillingEvent()));
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VKey<Cancellation> createVKey() {
|
||||||
|
return VKey.createOfy(getClass(), Key.create(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
|
@ -518,12 +626,12 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setOneTimeEventKey(Key<BillingEvent.OneTime> eventKey) {
|
public Builder setOneTimeEventKey(VKey<BillingEvent.OneTime> eventKey) {
|
||||||
getInstance().refOneTime = eventKey;
|
getInstance().refOneTime = eventKey;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setRecurringEventKey(Key<BillingEvent.Recurring> eventKey) {
|
public Builder setRecurringEventKey(VKey<BillingEvent.Recurring> eventKey) {
|
||||||
getInstance().refRecurring = eventKey;
|
getInstance().refRecurring = eventKey;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -540,9 +648,7 @@ public abstract class BillingEvent extends ImmutableObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** An event representing a modification of an existing one-time billing event. */
|
||||||
* An event representing a modification of an existing one-time billing event.
|
|
||||||
*/
|
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
public static class Modification extends BillingEvent {
|
public static class Modification extends BillingEvent {
|
||||||
|
|
|
@ -29,20 +29,22 @@ import com.googlecode.objectify.annotation.Embed;
|
||||||
import com.googlecode.objectify.annotation.Index;
|
import com.googlecode.objectify.annotation.Index;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A time of year (month, day, millis of day) that can be stored in a sort-friendly format.
|
* A time of year (month, day, millis of day) that can be stored in a sort-friendly format.
|
||||||
*
|
*
|
||||||
* <p>This is conceptually similar to {@code MonthDay} in Joda or more generally to Joda's
|
* <p>This is conceptually similar to {@code MonthDay} in Joda or more generally to Joda's {@code
|
||||||
* {@code Partial}, but the parts we need are too simple to justify a full implementation of
|
* Partial}, but the parts we need are too simple to justify a full implementation of {@code
|
||||||
* {@code Partial}.
|
* Partial}.
|
||||||
*
|
*
|
||||||
* <p>For simplicity, the native representation of this class's data is its stored format. This
|
* <p>For simplicity, the native representation of this class's data is its stored format. This
|
||||||
* allows it to be embeddable with no translation needed and also delays parsing of the string on
|
* allows it to be embeddable with no translation needed and also delays parsing of the string on
|
||||||
* load until it's actually needed.
|
* load until it's actually needed.
|
||||||
*/
|
*/
|
||||||
@Embed
|
@Embed
|
||||||
|
@Embeddable
|
||||||
public class TimeOfYear extends ImmutableObject {
|
public class TimeOfYear extends ImmutableObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,8 @@ import google.registry.model.common.TimedTransitionProperty;
|
||||||
import google.registry.model.common.TimedTransitionProperty.TimeMapper;
|
import google.registry.model.common.TimedTransitionProperty.TimeMapper;
|
||||||
import google.registry.model.common.TimedTransitionProperty.TimedTransition;
|
import google.registry.model.common.TimedTransitionProperty.TimedTransition;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import google.registry.persistence.WithStringVKey;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -53,6 +55,7 @@ import org.joda.time.DateTime;
|
||||||
/** An entity representing an allocation token. */
|
/** An entity representing an allocation token. */
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
|
@WithStringVKey
|
||||||
public class AllocationToken extends BackupGroupRoot implements Buildable {
|
public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||||
|
|
||||||
// Promotions should only move forward, and ENDED / CANCELLED are terminal states.
|
// Promotions should only move forward, and ENDED / CANCELLED are terminal states.
|
||||||
|
@ -179,6 +182,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||||
return tokenStatusTransitions;
|
return tokenStatusTransitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VKey<AllocationToken> createVKey() {
|
||||||
|
return VKey.createOfy(getClass(), Key.create(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.googlecode.objectify.annotation.EntitySubclass;
|
||||||
import com.googlecode.objectify.impl.translate.TranslatorFactory;
|
import com.googlecode.objectify.impl.translate.TranslatorFactory;
|
||||||
import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory;
|
import com.googlecode.objectify.impl.translate.opt.joda.MoneyStringTranslatorFactory;
|
||||||
import google.registry.config.RegistryEnvironment;
|
import google.registry.config.RegistryEnvironment;
|
||||||
|
import google.registry.model.Buildable;
|
||||||
import google.registry.model.EntityClasses;
|
import google.registry.model.EntityClasses;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
|
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
|
||||||
|
@ -167,10 +168,16 @@ public class ObjectifyService {
|
||||||
}
|
}
|
||||||
com.googlecode.objectify.ObjectifyService.register(clazz);
|
com.googlecode.objectify.ObjectifyService.register(clazz);
|
||||||
// Autogenerated ids make the commit log code very difficult since we won't always be able
|
// Autogenerated ids make the commit log code very difficult since we won't always be able
|
||||||
// to create a key for an entity immediately when requesting a save. Disallow that here.
|
// to create a key for an entity immediately when requesting a save. So, we require such
|
||||||
checkState(
|
// entities to implement google.registry.model.Buildable as its build() function allocates the
|
||||||
!factory().getMetadata(clazz).getKeyMetadata().isIdGeneratable(),
|
// id to the entity.
|
||||||
"Can't register %s: Autogenerated ids (@Id on a Long) are not supported.", kind);
|
if (factory().getMetadata(clazz).getKeyMetadata().isIdGeneratable()) {
|
||||||
|
checkState(
|
||||||
|
Buildable.class.isAssignableFrom(clazz),
|
||||||
|
"Can't register %s: Entity with autogenerated ids (@Id on a Long) must implement"
|
||||||
|
+ " google.registry.model.Buildable.",
|
||||||
|
kind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.persistence.converter;
|
||||||
|
|
||||||
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.AttributeConverter;
|
||||||
|
import javax.persistence.Converter;
|
||||||
|
|
||||||
|
/** JPA {@link AttributeConverter} for storing/retrieving {@link Set}. */
|
||||||
|
@Converter(autoApply = true)
|
||||||
|
public class BillingEventFlagSetConverter extends StringSetConverterBase<Flag> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString(Flag element) {
|
||||||
|
return element.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Flag fromString(String value) {
|
||||||
|
return Flag.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,9 @@
|
||||||
* Move tests to another (sub)project. This is not a big problem, but feels unnatural.
|
* Move tests to another (sub)project. This is not a big problem, but feels unnatural.
|
||||||
* Use Hibernate's ServiceRegistry for bootstrapping (not JPA-compliant)
|
* Use Hibernate's ServiceRegistry for bootstrapping (not JPA-compliant)
|
||||||
-->
|
-->
|
||||||
|
<class>google.registry.model.billing.BillingEvent$Cancellation</class>
|
||||||
|
<class>google.registry.model.billing.BillingEvent$OneTime</class>
|
||||||
|
<class>google.registry.model.billing.BillingEvent$Recurring</class>
|
||||||
<class>google.registry.model.contact.ContactResource</class>
|
<class>google.registry.model.contact.ContactResource</class>
|
||||||
<class>google.registry.model.domain.DomainBase</class>
|
<class>google.registry.model.domain.DomainBase</class>
|
||||||
<class>google.registry.model.host.HostResource</class>
|
<class>google.registry.model.host.HostResource</class>
|
||||||
|
@ -36,6 +39,7 @@
|
||||||
|
|
||||||
<!-- Customized type converters -->
|
<!-- Customized type converters -->
|
||||||
<class>google.registry.persistence.converter.BillingCostTransitionConverter</class>
|
<class>google.registry.persistence.converter.BillingCostTransitionConverter</class>
|
||||||
|
<class>google.registry.persistence.converter.BillingEventFlagSetConverter</class>
|
||||||
<class>google.registry.persistence.converter.BloomFilterConverter</class>
|
<class>google.registry.persistence.converter.BloomFilterConverter</class>
|
||||||
<class>google.registry.persistence.converter.CidrAddressBlockListConverter</class>
|
<class>google.registry.persistence.converter.CidrAddressBlockListConverter</class>
|
||||||
<class>google.registry.persistence.converter.CreateAutoTimestampConverter</class>
|
<class>google.registry.persistence.converter.CreateAutoTimestampConverter</class>
|
||||||
|
@ -53,6 +57,8 @@
|
||||||
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
|
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
|
||||||
|
|
||||||
<!-- Generated converters for VKey -->
|
<!-- Generated converters for VKey -->
|
||||||
|
<class>google.registry.model.billing.VKeyConverter_BillingEvent</class>
|
||||||
|
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
|
||||||
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
||||||
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class ExpandRecurringBillingEventsActionTest
|
||||||
.setPeriodYears(1)
|
.setPeriodYears(1)
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.setSyntheticCreationTime(beginningOfTest)
|
.setSyntheticCreationTime(beginningOfTest)
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
.setTargetId(domain.getFullyQualifiedDomainName());
|
.setTargetId(domain.getFullyQualifiedDomainName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,10 +274,12 @@ public class ExpandRecurringBillingEventsActionTest
|
||||||
.setParent(persistedEntries.get(0))
|
.setParent(persistedEntries.get(0))
|
||||||
.build();
|
.build();
|
||||||
// Persist an otherwise identical billing event that differs only in recurring event key.
|
// Persist an otherwise identical billing event that differs only in recurring event key.
|
||||||
BillingEvent.OneTime persisted = expected.asBuilder()
|
BillingEvent.OneTime persisted =
|
||||||
.setParent(persistedEntries.get(1))
|
expected
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring2))
|
.asBuilder()
|
||||||
.build();
|
.setParent(persistedEntries.get(1))
|
||||||
|
.setCancellationMatchingBillingEvent(recurring2.createVKey())
|
||||||
|
.build();
|
||||||
assertCursorAt(beginningOfTest);
|
assertCursorAt(beginningOfTest);
|
||||||
assertBillingEventsForResource(domain, persisted, expected, recurring, recurring2);
|
assertBillingEventsForResource(domain, persisted, expected, recurring, recurring2);
|
||||||
}
|
}
|
||||||
|
@ -604,19 +606,21 @@ public class ExpandRecurringBillingEventsActionTest
|
||||||
assertHistoryEntryMatches(
|
assertHistoryEntryMatches(
|
||||||
domain, persistedEntries.get(0), "TheRegistrar", DateTime.parse("2000-02-19T00:00:00Z"),
|
domain, persistedEntries.get(0), "TheRegistrar", DateTime.parse("2000-02-19T00:00:00Z"),
|
||||||
true);
|
true);
|
||||||
BillingEvent.OneTime expected = defaultOneTimeBuilder()
|
BillingEvent.OneTime expected =
|
||||||
.setParent(persistedEntries.get(0))
|
defaultOneTimeBuilder()
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setParent(persistedEntries.get(0))
|
||||||
.build();
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
|
.build();
|
||||||
assertHistoryEntryMatches(
|
assertHistoryEntryMatches(
|
||||||
domain, persistedEntries.get(1), "TheRegistrar", DateTime.parse("2000-05-20T00:00:00Z"),
|
domain, persistedEntries.get(1), "TheRegistrar", DateTime.parse("2000-05-20T00:00:00Z"),
|
||||||
true);
|
true);
|
||||||
BillingEvent.OneTime expected2 = defaultOneTimeBuilder()
|
BillingEvent.OneTime expected2 =
|
||||||
.setBillingTime(DateTime.parse("2000-05-20T00:00:00Z"))
|
defaultOneTimeBuilder()
|
||||||
.setEventTime(DateTime.parse("2000-04-05T00:00:00Z"))
|
.setBillingTime(DateTime.parse("2000-05-20T00:00:00Z"))
|
||||||
.setParent(persistedEntries.get(1))
|
.setEventTime(DateTime.parse("2000-04-05T00:00:00Z"))
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring2))
|
.setParent(persistedEntries.get(1))
|
||||||
.build();
|
.setCancellationMatchingBillingEvent(recurring2.createVKey())
|
||||||
|
.build();
|
||||||
assertBillingEventsForResource(domain, expected, expected2, recurring, recurring2);
|
assertBillingEventsForResource(domain, expected, expected2, recurring, recurring2);
|
||||||
assertCursorAt(beginningOfTest);
|
assertCursorAt(beginningOfTest);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.HistoryEntry.Type;
|
import google.registry.model.reporting.HistoryEntry.Type;
|
||||||
import google.registry.monitoring.whitebox.EppMetric;
|
import google.registry.monitoring.whitebox.EppMetric;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeHttpSession;
|
import google.registry.testing.FakeHttpSession;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
|
@ -339,7 +340,8 @@ public class EppTestCase extends ShardableTestCase {
|
||||||
.setTargetId(domain.getFullyQualifiedDomainName())
|
.setTargetId(domain.getFullyQualifiedDomainName())
|
||||||
.setClientId(domain.getCurrentSponsorClientId())
|
.setClientId(domain.getCurrentSponsorClientId())
|
||||||
.setEventTime(deleteTime)
|
.setEventTime(deleteTime)
|
||||||
.setOneTimeEventKey(findKeyToActualOneTimeBillingEvent(billingEventToCancel))
|
.setOneTimeEventKey(
|
||||||
|
VKey.createOfy(OneTime.class, findKeyToActualOneTimeBillingEvent(billingEventToCancel)))
|
||||||
.setBillingTime(createTime.plus(Registry.get(domain.getTld()).getAddGracePeriodLength()))
|
.setBillingTime(createTime.plus(Registry.get(domain.getTld()).getAddGracePeriodLength()))
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
.setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE))
|
.setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE))
|
||||||
|
@ -353,7 +355,8 @@ public class EppTestCase extends ShardableTestCase {
|
||||||
.setTargetId(domain.getFullyQualifiedDomainName())
|
.setTargetId(domain.getFullyQualifiedDomainName())
|
||||||
.setClientId(domain.getCurrentSponsorClientId())
|
.setClientId(domain.getCurrentSponsorClientId())
|
||||||
.setEventTime(deleteTime)
|
.setEventTime(deleteTime)
|
||||||
.setOneTimeEventKey(findKeyToActualOneTimeBillingEvent(billingEventToCancel))
|
.setOneTimeEventKey(
|
||||||
|
VKey.createOfy(OneTime.class, findKeyToActualOneTimeBillingEvent(billingEventToCancel)))
|
||||||
.setBillingTime(renewTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength()))
|
.setBillingTime(renewTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength()))
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE))
|
.setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE))
|
||||||
|
|
|
@ -276,7 +276,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
.setBillingTime(billingTime)
|
.setBillingTime(billingTime)
|
||||||
.setFlags(expectedBillingFlags)
|
.setFlags(expectedBillingFlags)
|
||||||
.setParent(historyEntry)
|
.setParent(historyEntry)
|
||||||
.setAllocationToken(allocationToken == null ? null : Key.create(allocationToken))
|
.setAllocationToken(allocationToken == null ? null : allocationToken.createVKey())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
BillingEvent.Recurring renewBillingEvent =
|
BillingEvent.Recurring renewBillingEvent =
|
||||||
|
|
|
@ -214,7 +214,7 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
|
||||||
.setClientId("TheRegistrar")
|
.setClientId("TheRegistrar")
|
||||||
.setEventTime(eventTime)
|
.setEventTime(eventTime)
|
||||||
.setBillingTime(TIME_BEFORE_FLOW.plusDays(1))
|
.setBillingTime(TIME_BEFORE_FLOW.plusDays(1))
|
||||||
.setOneTimeEventKey(Key.create(graceBillingEvent))
|
.setOneTimeEventKey(graceBillingEvent.createVKey())
|
||||||
.setParent(historyEntryDomainDelete)
|
.setParent(historyEntryDomainDelete)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
|
@ -402,7 +403,8 @@ public class DomainTransferApproveFlowTest
|
||||||
.setEventTime(clock.nowUtc()) // The cancellation happens at the moment of transfer.
|
.setEventTime(clock.nowUtc()) // The cancellation happens at the moment of transfer.
|
||||||
.setBillingTime(
|
.setBillingTime(
|
||||||
oldExpirationTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
oldExpirationTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
||||||
.setRecurringEventKey(domain.getAutorenewBillingEvent()));
|
.setRecurringEventKey(
|
||||||
|
VKey.createOfy(BillingEvent.Recurring.class, domain.getAutorenewBillingEvent())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -100,6 +100,7 @@ import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
import google.registry.model.transfer.TransferResponse;
|
import google.registry.model.transfer.TransferResponse;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -1136,7 +1137,8 @@ public class DomainTransferRequestFlowTest
|
||||||
.setEventTime(clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()))
|
.setEventTime(clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()))
|
||||||
.setBillingTime(autorenewTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
.setBillingTime(autorenewTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
||||||
// The cancellation should refer to the old autorenew billing event.
|
// The cancellation should refer to the old autorenew billing event.
|
||||||
.setRecurringEventKey(existingAutorenewEvent));
|
.setRecurringEventKey(
|
||||||
|
VKey.createOfy(BillingEvent.Recurring.class, existingAutorenewEvent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1164,7 +1166,8 @@ public class DomainTransferRequestFlowTest
|
||||||
.setBillingTime(
|
.setBillingTime(
|
||||||
expirationTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
expirationTime.plus(Registry.get("tld").getAutoRenewGracePeriodLength()))
|
||||||
// The cancellation should refer to the old autorenew billing event.
|
// The cancellation should refer to the old autorenew billing event.
|
||||||
.setRecurringEventKey(existingAutorenewEvent));
|
.setRecurringEventKey(
|
||||||
|
VKey.createOfy(BillingEvent.Recurring.class, existingAutorenewEvent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -17,9 +17,11 @@ package google.registry.model.billing;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
||||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
|
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
import static org.joda.money.CurrencyUnit.USD;
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
import static org.joda.time.DateTimeZone.UTC;
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
|
@ -37,19 +39,25 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.util.DateTimeUtils;
|
import google.registry.util.DateTimeUtils;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Before;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/** Unit tests for {@link BillingEvent}. */
|
/** Unit tests for {@link BillingEvent}. */
|
||||||
public class BillingEventTest extends EntityTestCase {
|
public class BillingEventTest extends EntityTestCase {
|
||||||
private final DateTime now = DateTime.now(UTC);
|
private final DateTime now = DateTime.now(UTC);
|
||||||
|
|
||||||
|
public BillingEventTest() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
HistoryEntry historyEntry;
|
HistoryEntry historyEntry;
|
||||||
HistoryEntry historyEntry2;
|
HistoryEntry historyEntry2;
|
||||||
DomainBase domain;
|
DomainBase domain;
|
||||||
|
BillingEvent.OneTime sqlOneTime;
|
||||||
BillingEvent.OneTime oneTime;
|
BillingEvent.OneTime oneTime;
|
||||||
BillingEvent.OneTime oneTimeSynthetic;
|
BillingEvent.OneTime oneTimeSynthetic;
|
||||||
BillingEvent.Recurring recurring;
|
BillingEvent.Recurring recurring;
|
||||||
|
@ -57,7 +65,7 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
BillingEvent.Cancellation cancellationRecurring;
|
BillingEvent.Cancellation cancellationRecurring;
|
||||||
BillingEvent.Modification modification;
|
BillingEvent.Modification modification;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
createTld("tld");
|
createTld("tld");
|
||||||
domain = persistActiveDomain("foo.tld");
|
domain = persistActiveDomain("foo.tld");
|
||||||
|
@ -97,7 +105,18 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
.setCost(Money.of(USD, 1))
|
.setCost(Money.of(USD, 1))
|
||||||
.setEventTime(now)
|
.setEventTime(now)
|
||||||
.setBillingTime(now.plusDays(5))
|
.setBillingTime(now.plusDays(5))
|
||||||
.setAllocationToken(Key.create(allocationToken))));
|
.setAllocationToken(allocationToken.createVKey())));
|
||||||
|
|
||||||
|
sqlOneTime =
|
||||||
|
oneTime
|
||||||
|
.asBuilder()
|
||||||
|
.setDomainRepoId(domain.getRepoId())
|
||||||
|
.setDomainHistoryRevisionId(1L)
|
||||||
|
.setAllocationToken(
|
||||||
|
VKey.create(
|
||||||
|
AllocationToken.class, allocationToken.getToken(), Key.create(allocationToken)))
|
||||||
|
.build();
|
||||||
|
|
||||||
recurring =
|
recurring =
|
||||||
persistResource(
|
persistResource(
|
||||||
commonInit(
|
commonInit(
|
||||||
|
@ -107,31 +126,41 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.setEventTime(now.plusYears(1))
|
.setEventTime(now.plusYears(1))
|
||||||
.setRecurrenceEndTime(END_OF_TIME)));
|
.setRecurrenceEndTime(END_OF_TIME)));
|
||||||
oneTimeSynthetic = persistResource(commonInit(
|
oneTimeSynthetic =
|
||||||
new BillingEvent.OneTime.Builder()
|
persistResource(
|
||||||
.setParent(historyEntry)
|
commonInit(
|
||||||
.setReason(Reason.CREATE)
|
new BillingEvent.OneTime.Builder()
|
||||||
.setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT, BillingEvent.Flag.SYNTHETIC))
|
.setParent(historyEntry)
|
||||||
.setSyntheticCreationTime(now.plusDays(10))
|
.setReason(Reason.CREATE)
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setFlags(
|
||||||
.setPeriodYears(2)
|
ImmutableSet.of(
|
||||||
.setCost(Money.of(USD, 1))
|
BillingEvent.Flag.ANCHOR_TENANT, BillingEvent.Flag.SYNTHETIC))
|
||||||
.setEventTime(now)
|
.setSyntheticCreationTime(now.plusDays(10))
|
||||||
.setBillingTime(now.plusDays(5))));
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
cancellationOneTime = persistResource(commonInit(
|
.setPeriodYears(2)
|
||||||
new BillingEvent.Cancellation.Builder()
|
.setCost(Money.of(USD, 1))
|
||||||
.setParent(historyEntry2)
|
.setEventTime(now)
|
||||||
.setReason(Reason.CREATE)
|
.setBillingTime(now.plusDays(5))));
|
||||||
.setEventTime(now.plusDays(1))
|
|
||||||
.setBillingTime(now.plusDays(5))
|
cancellationOneTime =
|
||||||
.setOneTimeEventKey(Key.create(oneTime))));
|
persistResource(
|
||||||
cancellationRecurring = persistResource(commonInit(
|
commonInit(
|
||||||
new BillingEvent.Cancellation.Builder()
|
new BillingEvent.Cancellation.Builder()
|
||||||
.setParent(historyEntry2)
|
.setParent(historyEntry2)
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.CREATE)
|
||||||
.setEventTime(now.plusDays(1))
|
.setEventTime(now.plusDays(1))
|
||||||
.setBillingTime(now.plusYears(1).plusDays(45))
|
.setBillingTime(now.plusDays(5))
|
||||||
.setRecurringEventKey(Key.create(recurring))));
|
.setOneTimeEventKey(oneTime.createVKey())));
|
||||||
|
|
||||||
|
cancellationRecurring =
|
||||||
|
persistResource(
|
||||||
|
commonInit(
|
||||||
|
new BillingEvent.Cancellation.Builder()
|
||||||
|
.setParent(historyEntry2)
|
||||||
|
.setReason(Reason.RENEW)
|
||||||
|
.setEventTime(now.plusDays(1))
|
||||||
|
.setBillingTime(now.plusYears(1).plusDays(45))
|
||||||
|
.setRecurringEventKey(recurring.createVKey())));
|
||||||
modification = persistResource(commonInit(
|
modification = persistResource(commonInit(
|
||||||
new BillingEvent.Modification.Builder()
|
new BillingEvent.Modification.Builder()
|
||||||
.setParent(historyEntry2)
|
.setParent(historyEntry2)
|
||||||
|
@ -149,6 +178,83 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveNewBillingEvent(BillingEvent billingEvent) {
|
||||||
|
billingEvent.id = null;
|
||||||
|
jpaTm().transact(() -> jpaTm().saveNew(billingEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCloudSqlPersistence_OneTime() {
|
||||||
|
saveRegistrar("a registrar");
|
||||||
|
saveNewBillingEvent(sqlOneTime);
|
||||||
|
|
||||||
|
BillingEvent.OneTime persisted =
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> jpaTm().load(VKey.createSql(BillingEvent.OneTime.class, sqlOneTime.id)));
|
||||||
|
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||||
|
BillingEvent.OneTime fixed =
|
||||||
|
persisted
|
||||||
|
.asBuilder()
|
||||||
|
.setParent(sqlOneTime.getParentKey())
|
||||||
|
.setAllocationToken(sqlOneTime.getAllocationToken().get())
|
||||||
|
.build();
|
||||||
|
assertThat(fixed).isEqualTo(sqlOneTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCloudSqlPersistence_Cancellation() {
|
||||||
|
saveRegistrar("a registrar");
|
||||||
|
saveNewBillingEvent(sqlOneTime);
|
||||||
|
VKey<BillingEvent.OneTime> sqlVKey = VKey.createSql(BillingEvent.OneTime.class, sqlOneTime.id);
|
||||||
|
BillingEvent sqlCancellationOneTime =
|
||||||
|
cancellationOneTime
|
||||||
|
.asBuilder()
|
||||||
|
.setOneTimeEventKey(sqlVKey)
|
||||||
|
.setDomainRepoId(domain.getRepoId())
|
||||||
|
.setDomainHistoryRevisionId(1L)
|
||||||
|
.build();
|
||||||
|
saveNewBillingEvent(sqlCancellationOneTime);
|
||||||
|
|
||||||
|
BillingEvent.Cancellation persisted =
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() ->
|
||||||
|
jpaTm()
|
||||||
|
.load(
|
||||||
|
VKey.createSql(
|
||||||
|
BillingEvent.Cancellation.class, sqlCancellationOneTime.id)));
|
||||||
|
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||||
|
BillingEvent.Cancellation fixed =
|
||||||
|
persisted
|
||||||
|
.asBuilder()
|
||||||
|
.setParent(sqlCancellationOneTime.getParentKey())
|
||||||
|
.setOneTimeEventKey(sqlVKey)
|
||||||
|
.build();
|
||||||
|
assertThat(fixed).isEqualTo(sqlCancellationOneTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCloudSqlPersistence_Recurring() {
|
||||||
|
saveRegistrar("a registrar");
|
||||||
|
BillingEvent.Recurring sqlRecurring =
|
||||||
|
recurring
|
||||||
|
.asBuilder()
|
||||||
|
.setDomainRepoId(domain.getRepoId())
|
||||||
|
.setDomainHistoryRevisionId(1L)
|
||||||
|
.build();
|
||||||
|
saveNewBillingEvent(sqlRecurring);
|
||||||
|
|
||||||
|
BillingEvent.Recurring persisted =
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> jpaTm().load(VKey.createSql(BillingEvent.Recurring.class, sqlRecurring.id)));
|
||||||
|
// TODO(shicong): Remove these fixes after the entities are fully compatible
|
||||||
|
BillingEvent.Recurring fixed =
|
||||||
|
persisted.asBuilder().setParent(sqlRecurring.getParentKey()).build();
|
||||||
|
assertThat(fixed).isEqualTo(sqlRecurring);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPersistence() {
|
public void testPersistence() {
|
||||||
assertThat(ofy().load().entity(oneTime).now()).isEqualTo(oneTime);
|
assertThat(ofy().load().entity(oneTime).now()).isEqualTo(oneTime);
|
||||||
|
@ -183,8 +289,13 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCancellationMatching() {
|
public void testCancellationMatching() {
|
||||||
Key<?> recurringKey = ofy().load().entity(oneTimeSynthetic).now()
|
Key<?> recurringKey =
|
||||||
.getCancellationMatchingBillingEvent();
|
ofy()
|
||||||
|
.load()
|
||||||
|
.entity(oneTimeSynthetic)
|
||||||
|
.now()
|
||||||
|
.getCancellationMatchingBillingEvent()
|
||||||
|
.getOfyKey();
|
||||||
assertThat(ofy().load().key(recurringKey).now()).isEqualTo(recurring);
|
assertThat(ofy().load().key(recurringKey).now()).isEqualTo(recurring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +330,7 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
oneTime
|
oneTime
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setFlags(ImmutableSet.of(BillingEvent.Flag.SYNTHETIC))
|
.setFlags(ImmutableSet.of(BillingEvent.Flag.SYNTHETIC))
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
.build());
|
.build());
|
||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
|
@ -263,7 +374,7 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
() ->
|
() ->
|
||||||
oneTime
|
oneTime
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setCancellationMatchingBillingEvent(Key.create(recurring))
|
.setCancellationMatchingBillingEvent(recurring.createVKey())
|
||||||
.build());
|
.build());
|
||||||
assertThat(thrown)
|
assertThat(thrown)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
|
@ -334,8 +445,8 @@ public class BillingEventTest extends EntityTestCase {
|
||||||
() ->
|
() ->
|
||||||
cancellationOneTime
|
cancellationOneTime
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setOneTimeEventKey(Key.create(oneTime))
|
.setOneTimeEventKey(oneTime.createVKey())
|
||||||
.setRecurringEventKey(Key.create(recurring))
|
.setRecurringEventKey(recurring.createVKey())
|
||||||
.build());
|
.build());
|
||||||
assertThat(thrown).hasMessageThat().contains("exactly one billing event");
|
assertThat(thrown).hasMessageThat().contains("exactly one billing event");
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class JpaEntityCoverage extends ExternalResource {
|
||||||
private static final ImmutableSet<Class> ALL_JPA_ENTITIES =
|
private static final ImmutableSet<Class> ALL_JPA_ENTITIES =
|
||||||
PersistenceXmlUtility.getManagedClasses().stream()
|
PersistenceXmlUtility.getManagedClasses().stream()
|
||||||
.filter(e -> !IGNORE_ENTITIES.contains(e.getSimpleName()))
|
.filter(e -> !IGNORE_ENTITIES.contains(e.getSimpleName()))
|
||||||
.filter(e -> e.getAnnotation(Entity.class) != null)
|
.filter(e -> e.isAnnotationPresent(Entity.class))
|
||||||
.collect(ImmutableSet.toImmutableSet());
|
.collect(ImmutableSet.toImmutableSet());
|
||||||
private static final Set<Class> allCoveredJpaEntities = Sets.newHashSet();
|
private static final Set<Class> allCoveredJpaEntities = Sets.newHashSet();
|
||||||
// Map of test class name to boolean flag indicating if it tests any JPA entities.
|
// Map of test class name to boolean flag indicating if it tests any JPA entities.
|
||||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.schema.integration;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assert_;
|
import static com.google.common.truth.Truth.assert_;
|
||||||
|
|
||||||
|
import google.registry.model.billing.BillingEventTest;
|
||||||
import google.registry.model.contact.ContactResourceTest;
|
import google.registry.model.contact.ContactResourceTest;
|
||||||
import google.registry.model.domain.DomainBaseSqlTest;
|
import google.registry.model.domain.DomainBaseSqlTest;
|
||||||
import google.registry.model.registry.RegistryLockDaoTest;
|
import google.registry.model.registry.RegistryLockDaoTest;
|
||||||
|
@ -68,6 +69,7 @@ import org.junit.runner.RunWith;
|
||||||
@SelectClasses({
|
@SelectClasses({
|
||||||
// BeforeSuiteTest must be the first entry. See class javadoc for details.
|
// BeforeSuiteTest must be the first entry. See class javadoc for details.
|
||||||
BeforeSuiteTest.class,
|
BeforeSuiteTest.class,
|
||||||
|
BillingEventTest.class,
|
||||||
ClaimsListDaoTest.class,
|
ClaimsListDaoTest.class,
|
||||||
ContactResourceTest.class,
|
ContactResourceTest.class,
|
||||||
CursorDaoTest.class,
|
CursorDaoTest.class,
|
||||||
|
|
|
@ -5,11 +5,11 @@ class google.registry.model.UpdateAutoTimestamp {
|
||||||
org.joda.time.DateTime timestamp;
|
org.joda.time.DateTime timestamp;
|
||||||
}
|
}
|
||||||
class google.registry.model.billing.BillingEvent$Cancellation {
|
class google.registry.model.billing.BillingEvent$Cancellation {
|
||||||
@Id long id;
|
@Id java.lang.Long id;
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
||||||
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> refOneTime;
|
|
||||||
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$Recurring> refRecurring;
|
|
||||||
google.registry.model.billing.BillingEvent$Reason reason;
|
google.registry.model.billing.BillingEvent$Reason reason;
|
||||||
|
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$OneTime> refOneTime;
|
||||||
|
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> refRecurring;
|
||||||
java.lang.String clientId;
|
java.lang.String clientId;
|
||||||
java.lang.String targetId;
|
java.lang.String targetId;
|
||||||
java.util.Set<google.registry.model.billing.BillingEvent$Flag> flags;
|
java.util.Set<google.registry.model.billing.BillingEvent$Flag> flags;
|
||||||
|
@ -26,7 +26,7 @@ enum google.registry.model.billing.BillingEvent$Flag {
|
||||||
SYNTHETIC;
|
SYNTHETIC;
|
||||||
}
|
}
|
||||||
class google.registry.model.billing.BillingEvent$Modification {
|
class google.registry.model.billing.BillingEvent$Modification {
|
||||||
@Id long id;
|
@Id java.lang.Long id;
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
||||||
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> eventRef;
|
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> eventRef;
|
||||||
google.registry.model.billing.BillingEvent$Reason reason;
|
google.registry.model.billing.BillingEvent$Reason reason;
|
||||||
|
@ -38,11 +38,11 @@ class google.registry.model.billing.BillingEvent$Modification {
|
||||||
org.joda.time.DateTime eventTime;
|
org.joda.time.DateTime eventTime;
|
||||||
}
|
}
|
||||||
class google.registry.model.billing.BillingEvent$OneTime {
|
class google.registry.model.billing.BillingEvent$OneTime {
|
||||||
@Id long id;
|
@Id java.lang.Long id;
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
||||||
com.googlecode.objectify.Key<? extends google.registry.model.billing.BillingEvent> cancellationMatchingBillingEvent;
|
|
||||||
com.googlecode.objectify.Key<google.registry.model.domain.token.AllocationToken> allocationToken;
|
|
||||||
google.registry.model.billing.BillingEvent$Reason reason;
|
google.registry.model.billing.BillingEvent$Reason reason;
|
||||||
|
google.registry.persistence.VKey<? extends google.registry.model.billing.BillingEvent> cancellationMatchingBillingEvent;
|
||||||
|
google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> allocationToken;
|
||||||
java.lang.Integer periodYears;
|
java.lang.Integer periodYears;
|
||||||
java.lang.String clientId;
|
java.lang.String clientId;
|
||||||
java.lang.String targetId;
|
java.lang.String targetId;
|
||||||
|
@ -62,7 +62,7 @@ enum google.registry.model.billing.BillingEvent$Reason {
|
||||||
TRANSFER;
|
TRANSFER;
|
||||||
}
|
}
|
||||||
class google.registry.model.billing.BillingEvent$Recurring {
|
class google.registry.model.billing.BillingEvent$Recurring {
|
||||||
@Id long id;
|
@Id java.lang.Long id;
|
||||||
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent;
|
||||||
google.registry.model.billing.BillingEvent$Reason reason;
|
google.registry.model.billing.BillingEvent$Reason reason;
|
||||||
google.registry.model.common.TimeOfYear recurrenceTimeOfYear;
|
google.registry.model.common.TimeOfYear recurrenceTimeOfYear;
|
||||||
|
|
104
db/src/main/resources/sql/flyway/V26__create_billing_event.sql
Normal file
104
db/src/main/resources/sql/flyway/V26__create_billing_event.sql
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
-- Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
--
|
||||||
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
-- you may not use this file except in compliance with the License.
|
||||||
|
-- You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing, software
|
||||||
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
-- See the License for the specific language governing permissions and
|
||||||
|
-- limitations under the License.
|
||||||
|
|
||||||
|
create table "BillingCancellation" (
|
||||||
|
billing_cancellation_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
billing_time timestamptz,
|
||||||
|
billing_event_id int8,
|
||||||
|
billing_recurrence_id int8,
|
||||||
|
primary key (billing_cancellation_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table "BillingEvent" (
|
||||||
|
billing_event_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
allocation_token_id text,
|
||||||
|
billing_time timestamptz,
|
||||||
|
cancellation_matching_billing_recurrence_id int8,
|
||||||
|
cost_amount numeric(19, 2),
|
||||||
|
cost_currency text,
|
||||||
|
period_years int4,
|
||||||
|
synthetic_creation_time timestamptz,
|
||||||
|
primary key (billing_event_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table "BillingRecurrence" (
|
||||||
|
billing_recurrence_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
recurrence_end_time timestamptz,
|
||||||
|
recurrence_time_of_year text,
|
||||||
|
primary key (billing_recurrence_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index IDXeokttmxtpq2hohcioe5t2242b on "BillingCancellation" (client_id);
|
||||||
|
create index IDX2exdfbx6oiiwnhr8j6gjpqt2j on "BillingCancellation" (event_time);
|
||||||
|
create index IDXqa3g92jc17e8dtiaviy4fet4x on "BillingCancellation" (billing_time);
|
||||||
|
create index IDX73l103vc5900ig3p4odf0cngt on "BillingEvent" (client_id);
|
||||||
|
create index IDX5yfbr88439pxw0v3j86c74fp8 on "BillingEvent" (event_time);
|
||||||
|
create index IDX6py6ocrab0ivr76srcd2okpnq on "BillingEvent" (billing_time);
|
||||||
|
create index IDXplxf9v56p0wg8ws6qsvd082hk on "BillingEvent" (synthetic_creation_time);
|
||||||
|
create index IDXhmv411mdqo5ibn4vy7ykxpmlv on "BillingEvent" (allocation_token_id);
|
||||||
|
create index IDXn898pb9mwcg359cdwvolb11ck on "BillingRecurrence" (client_id);
|
||||||
|
create index IDX6syykou4nkc7hqa5p8r92cpch on "BillingRecurrence" (event_time);
|
||||||
|
create index IDXp3usbtvk0v1m14i5tdp4xnxgc on "BillingRecurrence" (recurrence_end_time);
|
||||||
|
create index IDXjny8wuot75b5e6p38r47wdawu on "BillingRecurrence" (recurrence_time_of_year);
|
||||||
|
|
||||||
|
alter table if exists "BillingEvent"
|
||||||
|
add constraint fk_billing_event_client_id
|
||||||
|
foreign key (client_id)
|
||||||
|
references "Registrar";
|
||||||
|
|
||||||
|
alter table if exists "BillingEvent"
|
||||||
|
add constraint fk_billing_event_cancellation_matching_billing_recurrence_id
|
||||||
|
foreign key (cancellation_matching_billing_recurrence_id)
|
||||||
|
references "BillingRecurrence";
|
||||||
|
|
||||||
|
alter table if exists "BillingCancellation"
|
||||||
|
add constraint fk_billing_cancellation_client_id
|
||||||
|
foreign key (client_id)
|
||||||
|
references "Registrar";
|
||||||
|
|
||||||
|
alter table if exists "BillingCancellation"
|
||||||
|
add constraint fk_billing_cancellation_billing_event_id
|
||||||
|
foreign key (billing_event_id)
|
||||||
|
references "BillingEvent";
|
||||||
|
|
||||||
|
alter table if exists "BillingCancellation"
|
||||||
|
add constraint fk_billing_cancellation_billing_recurrence_id
|
||||||
|
foreign key (billing_recurrence_id)
|
||||||
|
references "BillingRecurrence";
|
||||||
|
|
||||||
|
alter table if exists "BillingRecurrence"
|
||||||
|
add constraint fk_billing_recurrence_client_id
|
||||||
|
foreign key (client_id)
|
||||||
|
references "Registrar";
|
|
@ -12,6 +12,54 @@
|
||||||
-- See the License for the specific language governing permissions and
|
-- See the License for the specific language governing permissions and
|
||||||
-- limitations under the License.
|
-- limitations under the License.
|
||||||
|
|
||||||
|
create table "BillingCancellation" (
|
||||||
|
billing_cancellation_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
billing_time timestamptz,
|
||||||
|
billing_event_id int8,
|
||||||
|
billing_recurrence_id int8,
|
||||||
|
primary key (billing_cancellation_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table "BillingEvent" (
|
||||||
|
billing_event_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
allocation_token_id text,
|
||||||
|
billing_time timestamptz,
|
||||||
|
cancellation_matching_billing_recurrence_id int8,
|
||||||
|
cost_amount numeric(19, 2),
|
||||||
|
cost_currency text,
|
||||||
|
period_years int4,
|
||||||
|
synthetic_creation_time timestamptz,
|
||||||
|
primary key (billing_event_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table "BillingRecurrence" (
|
||||||
|
billing_recurrence_id bigserial not null,
|
||||||
|
client_id text not null,
|
||||||
|
domain_history_revision_id int8 not null,
|
||||||
|
domain_repo_id text not null,
|
||||||
|
event_time timestamptz not null,
|
||||||
|
flags text[],
|
||||||
|
reason text not null,
|
||||||
|
domain_name text not null,
|
||||||
|
recurrence_end_time timestamptz,
|
||||||
|
recurrence_time_of_year text,
|
||||||
|
primary key (billing_recurrence_id)
|
||||||
|
);
|
||||||
|
|
||||||
create table "ClaimsEntry" (
|
create table "ClaimsEntry" (
|
||||||
revision_id int8 not null,
|
revision_id int8 not null,
|
||||||
claim_key text not null,
|
claim_key text not null,
|
||||||
|
@ -280,6 +328,18 @@
|
||||||
should_publish boolean not null,
|
should_publish boolean not null,
|
||||||
primary key (revision_id)
|
primary key (revision_id)
|
||||||
);
|
);
|
||||||
|
create index IDXeokttmxtpq2hohcioe5t2242b on "BillingCancellation" (client_id);
|
||||||
|
create index IDX2exdfbx6oiiwnhr8j6gjpqt2j on "BillingCancellation" (event_time);
|
||||||
|
create index IDXqa3g92jc17e8dtiaviy4fet4x on "BillingCancellation" (billing_time);
|
||||||
|
create index IDX73l103vc5900ig3p4odf0cngt on "BillingEvent" (client_id);
|
||||||
|
create index IDX5yfbr88439pxw0v3j86c74fp8 on "BillingEvent" (event_time);
|
||||||
|
create index IDX6py6ocrab0ivr76srcd2okpnq on "BillingEvent" (billing_time);
|
||||||
|
create index IDXplxf9v56p0wg8ws6qsvd082hk on "BillingEvent" (synthetic_creation_time);
|
||||||
|
create index IDXhmv411mdqo5ibn4vy7ykxpmlv on "BillingEvent" (allocation_token_id);
|
||||||
|
create index IDXn898pb9mwcg359cdwvolb11ck on "BillingRecurrence" (client_id);
|
||||||
|
create index IDX6syykou4nkc7hqa5p8r92cpch on "BillingRecurrence" (event_time);
|
||||||
|
create index IDXp3usbtvk0v1m14i5tdp4xnxgc on "BillingRecurrence" (recurrence_end_time);
|
||||||
|
create index IDXjny8wuot75b5e6p38r47wdawu on "BillingRecurrence" (recurrence_time_of_year);
|
||||||
create index IDX3y752kr9uh4kh6uig54vemx0l on "Contact" (creation_time);
|
create index IDX3y752kr9uh4kh6uig54vemx0l on "Contact" (creation_time);
|
||||||
create index IDXbn8t4wp85fgxjl8q4ctlscx55 on "Contact" (current_sponsor_client_id);
|
create index IDXbn8t4wp85fgxjl8q4ctlscx55 on "Contact" (current_sponsor_client_id);
|
||||||
create index IDXn1f711wicdnooa2mqb7g1m55o on "Contact" (deletion_time);
|
create index IDXn1f711wicdnooa2mqb7g1m55o on "Contact" (deletion_time);
|
||||||
|
|
|
@ -34,6 +34,123 @@ SET default_tablespace = '';
|
||||||
|
|
||||||
SET default_with_oids = false;
|
SET default_with_oids = false;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."BillingCancellation" (
|
||||||
|
billing_cancellation_id bigint NOT NULL,
|
||||||
|
client_id text NOT NULL,
|
||||||
|
domain_history_revision_id bigint NOT NULL,
|
||||||
|
domain_repo_id text NOT NULL,
|
||||||
|
event_time timestamp with time zone NOT NULL,
|
||||||
|
flags text[],
|
||||||
|
reason text NOT NULL,
|
||||||
|
domain_name text NOT NULL,
|
||||||
|
billing_time timestamp with time zone,
|
||||||
|
billing_event_id bigint,
|
||||||
|
billing_recurrence_id bigint
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation_billing_cancellation_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public."BillingCancellation_billing_cancellation_id_seq"
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation_billing_cancellation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public."BillingCancellation_billing_cancellation_id_seq" OWNED BY public."BillingCancellation".billing_cancellation_id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."BillingEvent" (
|
||||||
|
billing_event_id bigint NOT NULL,
|
||||||
|
client_id text NOT NULL,
|
||||||
|
domain_history_revision_id bigint NOT NULL,
|
||||||
|
domain_repo_id text NOT NULL,
|
||||||
|
event_time timestamp with time zone NOT NULL,
|
||||||
|
flags text[],
|
||||||
|
reason text NOT NULL,
|
||||||
|
domain_name text NOT NULL,
|
||||||
|
allocation_token_id text,
|
||||||
|
billing_time timestamp with time zone,
|
||||||
|
cancellation_matching_billing_recurrence_id bigint,
|
||||||
|
cost_amount numeric(19,2),
|
||||||
|
cost_currency text,
|
||||||
|
period_years integer,
|
||||||
|
synthetic_creation_time timestamp with time zone
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent_billing_event_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public."BillingEvent_billing_event_id_seq"
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent_billing_event_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public."BillingEvent_billing_event_id_seq" OWNED BY public."BillingEvent".billing_event_id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."BillingRecurrence" (
|
||||||
|
billing_recurrence_id bigint NOT NULL,
|
||||||
|
client_id text NOT NULL,
|
||||||
|
domain_history_revision_id bigint NOT NULL,
|
||||||
|
domain_repo_id text NOT NULL,
|
||||||
|
event_time timestamp with time zone NOT NULL,
|
||||||
|
flags text[],
|
||||||
|
reason text NOT NULL,
|
||||||
|
domain_name text NOT NULL,
|
||||||
|
recurrence_end_time timestamp with time zone,
|
||||||
|
recurrence_time_of_year text
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence_billing_recurrence_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public."BillingRecurrence_billing_recurrence_id_seq"
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence_billing_recurrence_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public."BillingRecurrence_billing_recurrence_id_seq" OWNED BY public."BillingRecurrence".billing_recurrence_id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ClaimsEntry; Type: TABLE; Schema: public; Owner: -
|
-- Name: ClaimsEntry; Type: TABLE; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -427,6 +544,27 @@ CREATE SEQUENCE public."ReservedList_revision_id_seq"
|
||||||
ALTER SEQUENCE public."ReservedList_revision_id_seq" OWNED BY public."ReservedList".revision_id;
|
ALTER SEQUENCE public."ReservedList_revision_id_seq" OWNED BY public."ReservedList".revision_id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation billing_cancellation_id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingCancellation" ALTER COLUMN billing_cancellation_id SET DEFAULT nextval('public."BillingCancellation_billing_cancellation_id_seq"'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent billing_event_id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingEvent" ALTER COLUMN billing_event_id SET DEFAULT nextval('public."BillingEvent_billing_event_id_seq"'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence billing_recurrence_id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingRecurrence" ALTER COLUMN billing_recurrence_id SET DEFAULT nextval('public."BillingRecurrence_billing_recurrence_id_seq"'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ClaimsList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: ClaimsList revision_id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -455,6 +593,30 @@ ALTER TABLE ONLY public."RegistryLock" ALTER COLUMN revision_id SET DEFAULT next
|
||||||
ALTER TABLE ONLY public."ReservedList" ALTER COLUMN revision_id SET DEFAULT nextval('public."ReservedList_revision_id_seq"'::regclass);
|
ALTER TABLE ONLY public."ReservedList" ALTER COLUMN revision_id SET DEFAULT nextval('public."ReservedList_revision_id_seq"'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation BillingCancellation_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingCancellation"
|
||||||
|
ADD CONSTRAINT "BillingCancellation_pkey" PRIMARY KEY (billing_cancellation_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent BillingEvent_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingEvent"
|
||||||
|
ADD CONSTRAINT "BillingEvent_pkey" PRIMARY KEY (billing_event_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence BillingRecurrence_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingRecurrence"
|
||||||
|
ADD CONSTRAINT "BillingRecurrence_pkey" PRIMARY KEY (billing_recurrence_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ClaimsEntry ClaimsEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: ClaimsEntry ClaimsEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -597,6 +759,13 @@ CREATE INDEX idx1p3esngcwwu6hstyua6itn6ff ON public."Contact" USING btree (searc
|
||||||
CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (fully_qualified_domain_name);
|
CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (fully_qualified_domain_name);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx2exdfbx6oiiwnhr8j6gjpqt2j; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx2exdfbx6oiiwnhr8j6gjpqt2j ON public."BillingCancellation" USING btree (event_time);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idx3y752kr9uh4kh6uig54vemx0l; Type: INDEX; Schema: public; Owner: -
|
-- Name: idx3y752kr9uh4kh6uig54vemx0l; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -611,6 +780,34 @@ CREATE INDEX idx3y752kr9uh4kh6uig54vemx0l ON public."Contact" USING btree (creat
|
||||||
CREATE INDEX idx5mnf0wn20tno4b9do88j61klr ON public."Domain" USING btree (deletion_time);
|
CREATE INDEX idx5mnf0wn20tno4b9do88j61klr ON public."Domain" USING btree (deletion_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx5yfbr88439pxw0v3j86c74fp8; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx5yfbr88439pxw0v3j86c74fp8 ON public."BillingEvent" USING btree (event_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx6py6ocrab0ivr76srcd2okpnq; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx6py6ocrab0ivr76srcd2okpnq ON public."BillingEvent" USING btree (billing_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx6syykou4nkc7hqa5p8r92cpch; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx6syykou4nkc7hqa5p8r92cpch ON public."BillingRecurrence" USING btree (event_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx73l103vc5900ig3p4odf0cngt; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx73l103vc5900ig3p4odf0cngt ON public."BillingEvent" USING btree (client_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idx8nr0ke9mrrx4ewj6pd2ag4rmr; Type: INDEX; Schema: public; Owner: -
|
-- Name: idx8nr0ke9mrrx4ewj6pd2ag4rmr; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -639,6 +836,27 @@ CREATE INDEX idx_registry_lock_verification_code ON public."RegistryLock" USING
|
||||||
CREATE INDEX idxbn8t4wp85fgxjl8q4ctlscx55 ON public."Contact" USING btree (current_sponsor_client_id);
|
CREATE INDEX idxbn8t4wp85fgxjl8q4ctlscx55 ON public."Contact" USING btree (current_sponsor_client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxeokttmxtpq2hohcioe5t2242b; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING btree (client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxhmv411mdqo5ibn4vy7ykxpmlv; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxhmv411mdqo5ibn4vy7ykxpmlv ON public."BillingEvent" USING btree (allocation_token_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxjny8wuot75b5e6p38r47wdawu; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxjny8wuot75b5e6p38r47wdawu ON public."BillingRecurrence" USING btree (recurrence_time_of_year);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxkjt9yaq92876dstimd93hwckh; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxkjt9yaq92876dstimd93hwckh; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -653,6 +871,34 @@ CREATE INDEX idxkjt9yaq92876dstimd93hwckh ON public."Domain" USING btree (curren
|
||||||
CREATE INDEX idxn1f711wicdnooa2mqb7g1m55o ON public."Contact" USING btree (deletion_time);
|
CREATE INDEX idxn1f711wicdnooa2mqb7g1m55o ON public."Contact" USING btree (deletion_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxn898pb9mwcg359cdwvolb11ck; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxn898pb9mwcg359cdwvolb11ck ON public."BillingRecurrence" USING btree (client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxp3usbtvk0v1m14i5tdp4xnxgc; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxp3usbtvk0v1m14i5tdp4xnxgc ON public."BillingRecurrence" USING btree (recurrence_end_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxplxf9v56p0wg8ws6qsvd082hk; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxplxf9v56p0wg8ws6qsvd082hk ON public."BillingEvent" USING btree (synthetic_creation_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxqa3g92jc17e8dtiaviy4fet4x; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxqa3g92jc17e8dtiaviy4fet4x ON public."BillingCancellation" USING btree (billing_time);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxrwl38wwkli1j7gkvtywi9jokq; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxrwl38wwkli1j7gkvtywi9jokq; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -751,6 +997,54 @@ ALTER TABLE ONLY public."Contact"
|
||||||
ADD CONSTRAINT fk93c185fx7chn68uv7nl6uv2s0 FOREIGN KEY (current_sponsor_client_id) REFERENCES public."Registrar"(client_id);
|
ADD CONSTRAINT fk93c185fx7chn68uv7nl6uv2s0 FOREIGN KEY (current_sponsor_client_id) REFERENCES public."Registrar"(client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation fk_billing_cancellation_billing_event_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingCancellation"
|
||||||
|
ADD CONSTRAINT fk_billing_cancellation_billing_event_id FOREIGN KEY (billing_event_id) REFERENCES public."BillingEvent"(billing_event_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation fk_billing_cancellation_billing_recurrence_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingCancellation"
|
||||||
|
ADD CONSTRAINT fk_billing_cancellation_billing_recurrence_id FOREIGN KEY (billing_recurrence_id) REFERENCES public."BillingRecurrence"(billing_recurrence_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingCancellation fk_billing_cancellation_client_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingCancellation"
|
||||||
|
ADD CONSTRAINT fk_billing_cancellation_client_id FOREIGN KEY (client_id) REFERENCES public."Registrar"(client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent fk_billing_event_cancellation_matching_billing_recurrence_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingEvent"
|
||||||
|
ADD CONSTRAINT fk_billing_event_cancellation_matching_billing_recurrence_id FOREIGN KEY (cancellation_matching_billing_recurrence_id) REFERENCES public."BillingRecurrence"(billing_recurrence_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingEvent fk_billing_event_client_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingEvent"
|
||||||
|
ADD CONSTRAINT fk_billing_event_client_id FOREIGN KEY (client_id) REFERENCES public."Registrar"(client_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: BillingRecurrence fk_billing_recurrence_client_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."BillingRecurrence"
|
||||||
|
ADD CONSTRAINT fk_billing_recurrence_client_id FOREIGN KEY (client_id) REFERENCES public."Registrar"(client_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: Domain fk_domain_admin_contact; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: Domain fk_domain_admin_contact; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue