diff --git a/core/src/main/java/google/registry/beam/invoicing/sql/billing_events.sql b/core/src/main/java/google/registry/beam/invoicing/sql/billing_events.sql
index 2fabfde82..c5bdb635d 100644
--- a/core/src/main/java/google/registry/beam/invoicing/sql/billing_events.sql
+++ b/core/src/main/java/google/registry/beam/invoicing/sql/billing_events.sql
@@ -56,7 +56,8 @@ FROM (
`%PROJECT_ID%.%DATASTORE_EXPORT_DATA_SET%.%REGISTRY_TABLE%`
WHERE
-- TODO(b/18092292): Add a filter for tldState (not PDT/PREDELEGATION)
- tldType = 'REAL') ) AS BillingEvent
+ tldType = 'REAL'
+ AND disableInvoicing is not TRUE) ) AS BillingEvent
-- Gather billing ID from registrar table
-- This is a 'JOIN' as opposed to 'LEFT JOIN' to filter out
-- non-billable registrars
diff --git a/core/src/main/java/google/registry/model/registry/Registry.java b/core/src/main/java/google/registry/model/registry/Registry.java
index 85f341ce5..859da9e65 100644
--- a/core/src/main/java/google/registry/model/registry/Registry.java
+++ b/core/src/main/java/google/registry/model/registry/Registry.java
@@ -339,6 +339,14 @@ public class Registry extends ImmutableObject implements Buildable {
/** The type of the TLD, whether it's real or for testing. */
TldType tldType = TldType.REAL;
+ /**
+ * Whether to disable invoicing for a {@link TldType#REAL} TLD.
+ *
+ *
Note that invoicing is always disabled for {@link TldType#TEST} TLDs. Setting this field has
+ * no effect for {@link TldType#TEST} TLDs.
+ */
+ boolean disableInvoicing = false;
+
/**
* A property that transitions to different TldStates at different times. Stored as a list of
* TldStateTransition embedded objects using the @Mapify annotation.
@@ -637,6 +645,11 @@ public class Registry extends ImmutableObject implements Buildable {
return this;
}
+ public Builder setDisableInvoicing(boolean disableInvoicing) {
+ getInstance().disableInvoicing = disableInvoicing;
+ return this;
+ }
+
/** Sets the TLD state to transition to the specified states at the specified times. */
public Builder setTldStateTransitions(ImmutableSortedMap tldStatesMap) {
checkNotNull(tldStatesMap, "TLD states map cannot be null");
diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java
index e31c2cc92..ae408ce90 100644
--- a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java
+++ b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java
@@ -116,6 +116,13 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
description = "Tld type (REAL or TEST)")
private TldType tldType;
+ @Nullable
+ @Parameter(
+ names = "--disable_invoicing",
+ description = "Whether invoicing is disabled for a REAL tld.",
+ arity = 1)
+ private Boolean disableInvoicing;
+
@Nullable
@Parameter(
names = "--create_billing_cost",
@@ -320,6 +327,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
Optional.ofNullable(serverStatusChangeCost)
.ifPresent(builder::setServerStatusChangeBillingCost);
Optional.ofNullable(tldType).ifPresent(builder::setTldType);
+ Optional.ofNullable(disableInvoicing).ifPresent(builder::setDisableInvoicing);
Optional.ofNullable(lordnUsername).ifPresent(u -> builder.setLordnUsername(u.orElse(null)));
Optional.ofNullable(claimsPeriodEnd).ifPresent(builder::setClaimsPeriodEnd);
Optional.ofNullable(numDnsPublishShards).ifPresent(builder::setNumDnsPublishLocks);
diff --git a/core/src/test/resources/google/registry/beam/invoicing/billing_events_test.sql b/core/src/test/resources/google/registry/beam/invoicing/billing_events_test.sql
index 04bc8cfd2..e9b36e5b9 100644
--- a/core/src/test/resources/google/registry/beam/invoicing/billing_events_test.sql
+++ b/core/src/test/resources/google/registry/beam/invoicing/billing_events_test.sql
@@ -56,7 +56,8 @@ FROM (
`my-project-id.latest_datastore_export.Registry`
WHERE
-- TODO(b/18092292): Add a filter for tldState (not PDT/PREDELEGATION)
- tldType = 'REAL') ) AS BillingEvent
+ tldType = 'REAL'
+ AND disableInvoicing is not TRUE) ) AS BillingEvent
-- Gather billing ID from registrar table
-- This is a 'JOIN' as opposed to 'LEFT JOIN' to filter out
-- non-billable registrars
diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt
index bdea2a8f0..8b30be587 100644
--- a/core/src/test/resources/google/registry/model/schema.txt
+++ b/core/src/test/resources/google/registry/model/schema.txt
@@ -494,6 +494,7 @@ enum google.registry.model.registrar.RegistrarContact$Type {
class google.registry.model.registry.Registry {
@Id java.lang.String tldStrId;
@Parent com.googlecode.objectify.Key parent;
+ boolean disableInvoicing;
boolean dnsPaused;
boolean escrowEnabled;
com.googlecode.objectify.Key premiumList;