dodopayments 2.20.1 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +1 -1
  4. data/lib/dodopayments/models/checkout_session_preview_response.rb +30 -4
  5. data/lib/dodopayments/models/credit_entitlements/balance_create_ledger_entry_params.rb +4 -2
  6. data/lib/dodopayments/models/discount.rb +95 -3
  7. data/lib/dodopayments/models/discount_create_params.rb +110 -3
  8. data/lib/dodopayments/models/discount_list_params.rb +7 -2
  9. data/lib/dodopayments/models/discount_type.rb +1 -0
  10. data/lib/dodopayments/models/discount_update_params.rb +108 -3
  11. data/lib/dodopayments/models/payment.rb +145 -1
  12. data/lib/dodopayments/models/payment_list_params.rb +163 -1
  13. data/lib/dodopayments/models/payment_method_types.rb +0 -1
  14. data/lib/dodopayments/models/price.rb +19 -1
  15. data/lib/dodopayments/models/subscription.rb +11 -1
  16. data/lib/dodopayments/models/subscription_create_response.rb +10 -1
  17. data/lib/dodopayments/models/subscription_list_response.rb +11 -1
  18. data/lib/dodopayments/resources/credit_entitlements/balances.rb +1 -1
  19. data/lib/dodopayments/resources/discounts.rb +24 -5
  20. data/lib/dodopayments/resources/payments.rb +3 -1
  21. data/lib/dodopayments/version.rb +1 -1
  22. data/rbi/dodopayments/models/checkout_session_preview_response.rbi +33 -5
  23. data/rbi/dodopayments/models/credit_entitlements/balance_create_ledger_entry_params.rbi +6 -2
  24. data/rbi/dodopayments/models/discount.rbi +151 -2
  25. data/rbi/dodopayments/models/discount_create_params.rbi +197 -2
  26. data/rbi/dodopayments/models/discount_list_params.rbi +6 -2
  27. data/rbi/dodopayments/models/discount_type.rbi +1 -0
  28. data/rbi/dodopayments/models/discount_update_params.rbi +193 -2
  29. data/rbi/dodopayments/models/payment.rbi +347 -0
  30. data/rbi/dodopayments/models/payment_list_params.rbi +327 -0
  31. data/rbi/dodopayments/models/payment_method_types.rbi +0 -1
  32. data/rbi/dodopayments/models/price.rbi +20 -0
  33. data/rbi/dodopayments/models/subscription.rbi +15 -3
  34. data/rbi/dodopayments/models/subscription_create_response.rbi +13 -3
  35. data/rbi/dodopayments/models/subscription_list_response.rbi +15 -3
  36. data/rbi/dodopayments/resources/credit_entitlements/balances.rbi +3 -1
  37. data/rbi/dodopayments/resources/discounts.rbi +57 -3
  38. data/rbi/dodopayments/resources/payments.rbi +3 -0
  39. data/sig/dodopayments/models/checkout_session_preview_response.rbs +13 -3
  40. data/sig/dodopayments/models/discount.rbs +69 -0
  41. data/sig/dodopayments/models/discount_create_params.rbs +69 -0
  42. data/sig/dodopayments/models/discount_type.rbs +2 -1
  43. data/sig/dodopayments/models/discount_update_params.rbs +69 -0
  44. data/sig/dodopayments/models/payment.rbs +135 -0
  45. data/sig/dodopayments/models/payment_list_params.rbs +308 -0
  46. data/sig/dodopayments/models/payment_method_types.rbs +0 -2
  47. data/sig/dodopayments/models/price.rbs +10 -0
  48. data/sig/dodopayments/models/subscription.rbs +8 -3
  49. data/sig/dodopayments/models/subscription_create_response.rbs +8 -3
  50. data/sig/dodopayments/models/subscription_list_response.rbs +8 -3
  51. data/sig/dodopayments/resources/discounts.rbs +8 -0
  52. data/sig/dodopayments/resources/payments.rbs +1 -0
  53. metadata +2 -2
@@ -99,6 +99,17 @@ module Dodopayments
99
99
  sig { returns(T.nilable(Integer)) }
100
100
  attr_accessor :total_tax
101
101
 
102
+ # Per-unit trial amount after discounts, in the price currency's minor units
103
+ # (pre-quantity, pre-tax; see `current_breakup` for the taxed total due today).
104
+ # Only present for a paid trial; `None` for a free trial or no trial.
105
+ sig { returns(T.nilable(Integer)) }
106
+ attr_accessor :trial_amount
107
+
108
+ # Effective trial duration in days for the subscription line, when there's a trial
109
+ # (free or paid). `None` if no subscription or no trial.
110
+ sig { returns(T.nilable(Integer)) }
111
+ attr_accessor :trial_period_days
112
+
102
113
  # Data returned by the calculate checkout session API
103
114
  sig do
104
115
  params(
@@ -120,7 +131,9 @@ module Dodopayments
120
131
  tax_id_business_name: T.nilable(String),
121
132
  tax_id_err_msg: T.nilable(String),
122
133
  tax_id_format_name: T.nilable(String),
123
- total_tax: T.nilable(Integer)
134
+ total_tax: T.nilable(Integer),
135
+ trial_amount: T.nilable(Integer),
136
+ trial_period_days: T.nilable(Integer)
124
137
  ).returns(T.attached_class)
125
138
  end
126
139
  def self.new(
@@ -153,7 +166,14 @@ module Dodopayments
153
166
  # The matched tax ID notation (e.g. "VAT Number", "GSTIN") when valid
154
167
  tax_id_format_name: nil,
155
168
  # Total tax
156
- total_tax: nil
169
+ total_tax: nil,
170
+ # Per-unit trial amount after discounts, in the price currency's minor units
171
+ # (pre-quantity, pre-tax; see `current_breakup` for the taxed total due today).
172
+ # Only present for a paid trial; `None` for a free trial or no trial.
173
+ trial_amount: nil,
174
+ # Effective trial duration in days for the subscription line, when there's a trial
175
+ # (free or paid). `None` if no subscription or no trial.
176
+ trial_period_days: nil
157
177
  )
158
178
  end
159
179
 
@@ -178,7 +198,9 @@ module Dodopayments
178
198
  tax_id_business_name: T.nilable(String),
179
199
  tax_id_err_msg: T.nilable(String),
180
200
  tax_id_format_name: T.nilable(String),
181
- total_tax: T.nilable(Integer)
201
+ total_tax: T.nilable(Integer),
202
+ trial_amount: T.nilable(Integer),
203
+ trial_period_days: T.nilable(Integer)
182
204
  }
183
205
  )
184
206
  end
@@ -330,7 +352,8 @@ module Dodopayments
330
352
  sig { returns(T.nilable(String)) }
331
353
  attr_accessor :description
332
354
 
333
- # discount percentage
355
+ # Percentage rate (basis points) of the applicable percentage code; null for flat
356
+ # codes (their deduction is `og_price - discounted_price`).
334
357
  sig { returns(T.nilable(Integer)) }
335
358
  attr_accessor :discount_amount
336
359
 
@@ -407,7 +430,8 @@ module Dodopayments
407
430
  tax_rate:,
408
431
  addons: nil,
409
432
  description: nil,
410
- # discount percentage
433
+ # Percentage rate (basis points) of the applicable percentage code; null for flat
434
+ # codes (their deduction is `og_price - discounted_price`).
411
435
  discount_amount: nil,
412
436
  # number of cycles the discount will apply
413
437
  discount_cycle: nil,
@@ -619,6 +643,8 @@ module Dodopayments
619
643
  sig { returns(T.nilable(String)) }
620
644
  attr_accessor :description
621
645
 
646
+ # Percentage rate (basis points) of the applicable percentage code; null for flat
647
+ # codes (their deduction is `og_price - discounted_price`).
622
648
  sig { returns(T.nilable(Integer)) }
623
649
  attr_accessor :discount_amount
624
650
 
@@ -656,6 +682,8 @@ module Dodopayments
656
682
  tax_inclusive:,
657
683
  tax_rate:,
658
684
  description: nil,
685
+ # Percentage rate (basis points) of the applicable percentage code; null for flat
686
+ # codes (their deduction is `og_price - discounted_price`).
659
687
  discount_amount: nil,
660
688
  tax: nil
661
689
  )
@@ -21,7 +21,9 @@ module Dodopayments
21
21
  sig { returns(String) }
22
22
  attr_accessor :customer_id
23
23
 
24
- # Amount to credit or debit
24
+ # Amount to credit or debit. Bounded to a `NUMERIC(38,28)` column, so the integer
25
+ # part must have fewer than 10 digits (< 10^10); larger values previously reached
26
+ # the DB and failed with a 22003 overflow surfaced as a 500.
25
27
  sig { returns(String) }
26
28
  attr_accessor :amount
27
29
 
@@ -70,7 +72,9 @@ module Dodopayments
70
72
  def self.new(
71
73
  credit_entitlement_id:,
72
74
  customer_id:,
73
- # Amount to credit or debit
75
+ # Amount to credit or debit. Bounded to a `NUMERIC(38,28)` column, so the integer
76
+ # part must have fewer than 10 digits (< 10^10); larger values previously reached
77
+ # the DB and failed with a 22003 overflow surfaced as a 500.
74
78
  amount:,
75
79
  # Entry type: credit or debit
76
80
  entry_type:,
@@ -24,6 +24,10 @@ module Dodopayments
24
24
  sig { returns(Time) }
25
25
  attr_accessor :created_at
26
26
 
27
+ # Who may redeem this discount code.
28
+ sig { returns(Dodopayments::Discount::CustomerEligibility::TaggedSymbol) }
29
+ attr_accessor :customer_eligibility
30
+
27
31
  # The unique discount ID
28
32
  sig { returns(String) }
29
33
  attr_accessor :discount_id
@@ -45,10 +49,25 @@ module Dodopayments
45
49
  sig { returns(Integer) }
46
50
  attr_accessor :times_used
47
51
 
48
- # The type of discount. Currently only `percentage` is supported.
52
+ # The type of discount (`percentage` or `flat`).
49
53
  sig { returns(Dodopayments::DiscountType::TaggedSymbol) }
50
54
  attr_accessor :type
51
55
 
56
+ # Per-currency options (flat deduction / percentage cap + minimum subtotal). Empty
57
+ # for discounts without any configured currency options.
58
+ sig do
59
+ returns(T.nilable(T::Array[Dodopayments::Discount::CurrencyOption]))
60
+ end
61
+ attr_reader :currency_options
62
+
63
+ sig do
64
+ params(
65
+ currency_options:
66
+ T::Array[Dodopayments::Discount::CurrencyOption::OrHash]
67
+ ).void
68
+ end
69
+ attr_writer :currency_options
70
+
52
71
  # Optional date/time after which discount is expired.
53
72
  sig { returns(T.nilable(Time)) }
54
73
  attr_accessor :expires_at
@@ -57,6 +76,15 @@ module Dodopayments
57
76
  sig { returns(T.nilable(String)) }
58
77
  attr_accessor :name
59
78
 
79
+ # Maximum number of times a single customer may redeem this discount, if any.
80
+ sig { returns(T.nilable(Integer)) }
81
+ attr_accessor :per_customer_usage_limit
82
+
83
+ # Optional date/time before which the discount is not yet active. NULL = active
84
+ # immediately.
85
+ sig { returns(T.nilable(Time)) }
86
+ attr_accessor :starts_at
87
+
60
88
  # Number of subscription billing cycles this discount is valid for. If not
61
89
  # provided, the discount will be applied indefinitely to all recurring payments
62
90
  # related to the subscription.
@@ -73,14 +101,20 @@ module Dodopayments
73
101
  business_id: String,
74
102
  code: String,
75
103
  created_at: Time,
104
+ customer_eligibility:
105
+ Dodopayments::Discount::CustomerEligibility::OrSymbol,
76
106
  discount_id: String,
77
107
  metadata: T::Hash[Symbol, Dodopayments::MetadataItem::Variants],
78
108
  preserve_on_plan_change: T::Boolean,
79
109
  restricted_to: T::Array[String],
80
110
  times_used: Integer,
81
111
  type: Dodopayments::DiscountType::OrSymbol,
112
+ currency_options:
113
+ T::Array[Dodopayments::Discount::CurrencyOption::OrHash],
82
114
  expires_at: T.nilable(Time),
83
115
  name: T.nilable(String),
116
+ per_customer_usage_limit: T.nilable(Integer),
117
+ starts_at: T.nilable(Time),
84
118
  subscription_cycles: T.nilable(Integer),
85
119
  usage_limit: T.nilable(Integer)
86
120
  ).returns(T.attached_class)
@@ -94,6 +128,8 @@ module Dodopayments
94
128
  code:,
95
129
  # Timestamp when the discount is created
96
130
  created_at:,
131
+ # Who may redeem this discount code.
132
+ customer_eligibility:,
97
133
  # The unique discount ID
98
134
  discount_id:,
99
135
  # Arbitrary key-value metadata. Values can be string, integer, number, or boolean.
@@ -105,12 +141,20 @@ module Dodopayments
105
141
  restricted_to:,
106
142
  # How many times this discount has been used.
107
143
  times_used:,
108
- # The type of discount. Currently only `percentage` is supported.
144
+ # The type of discount (`percentage` or `flat`).
109
145
  type:,
146
+ # Per-currency options (flat deduction / percentage cap + minimum subtotal). Empty
147
+ # for discounts without any configured currency options.
148
+ currency_options: nil,
110
149
  # Optional date/time after which discount is expired.
111
150
  expires_at: nil,
112
151
  # Name for the Discount
113
152
  name: nil,
153
+ # Maximum number of times a single customer may redeem this discount, if any.
154
+ per_customer_usage_limit: nil,
155
+ # Optional date/time before which the discount is not yet active. NULL = active
156
+ # immediately.
157
+ starts_at: nil,
114
158
  # Number of subscription billing cycles this discount is valid for. If not
115
159
  # provided, the discount will be applied indefinitely to all recurring payments
116
160
  # related to the subscription.
@@ -127,14 +171,19 @@ module Dodopayments
127
171
  business_id: String,
128
172
  code: String,
129
173
  created_at: Time,
174
+ customer_eligibility:
175
+ Dodopayments::Discount::CustomerEligibility::TaggedSymbol,
130
176
  discount_id: String,
131
177
  metadata: T::Hash[Symbol, Dodopayments::MetadataItem::Variants],
132
178
  preserve_on_plan_change: T::Boolean,
133
179
  restricted_to: T::Array[String],
134
180
  times_used: Integer,
135
181
  type: Dodopayments::DiscountType::TaggedSymbol,
182
+ currency_options: T::Array[Dodopayments::Discount::CurrencyOption],
136
183
  expires_at: T.nilable(Time),
137
184
  name: T.nilable(String),
185
+ per_customer_usage_limit: T.nilable(Integer),
186
+ starts_at: T.nilable(Time),
138
187
  subscription_cycles: T.nilable(Integer),
139
188
  usage_limit: T.nilable(Integer)
140
189
  }
@@ -142,6 +191,106 @@ module Dodopayments
142
191
  end
143
192
  def to_hash
144
193
  end
194
+
195
+ # Who may redeem this discount code.
196
+ module CustomerEligibility
197
+ extend Dodopayments::Internal::Type::Enum
198
+
199
+ TaggedSymbol =
200
+ T.type_alias do
201
+ T.all(Symbol, Dodopayments::Discount::CustomerEligibility)
202
+ end
203
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
204
+
205
+ ANY =
206
+ T.let(:any, Dodopayments::Discount::CustomerEligibility::TaggedSymbol)
207
+ FIRST_TIME =
208
+ T.let(
209
+ :first_time,
210
+ Dodopayments::Discount::CustomerEligibility::TaggedSymbol
211
+ )
212
+ EXISTING =
213
+ T.let(
214
+ :existing,
215
+ Dodopayments::Discount::CustomerEligibility::TaggedSymbol
216
+ )
217
+ SPECIFIC =
218
+ T.let(
219
+ :specific,
220
+ Dodopayments::Discount::CustomerEligibility::TaggedSymbol
221
+ )
222
+
223
+ sig do
224
+ override.returns(
225
+ T::Array[Dodopayments::Discount::CustomerEligibility::TaggedSymbol]
226
+ )
227
+ end
228
+ def self.values
229
+ end
230
+ end
231
+
232
+ class CurrencyOption < Dodopayments::Internal::Type::BaseModel
233
+ OrHash =
234
+ T.type_alias do
235
+ T.any(
236
+ Dodopayments::Discount::CurrencyOption,
237
+ Dodopayments::Internal::AnyHash
238
+ )
239
+ end
240
+
241
+ # The currency this option applies to.
242
+ sig { returns(Dodopayments::Currency::TaggedSymbol) }
243
+ attr_accessor :currency
244
+
245
+ # Whether this is the default row FX conversions pivot from.
246
+ sig { returns(T::Boolean) }
247
+ attr_accessor :is_default
248
+
249
+ # Eligible-cart threshold in this currency's subunits (0 = no minimum).
250
+ sig { returns(Integer) }
251
+ attr_accessor :minimum_subtotal
252
+
253
+ # The most this code discounts in this currency's subunits (flat deduction or
254
+ # percentage cap).
255
+ sig { returns(T.nilable(Integer)) }
256
+ attr_accessor :max_amount_possible
257
+
258
+ # A per-currency discount option (response shape). `max_amount_possible` mirrors
259
+ # the DB column of the same name.
260
+ sig do
261
+ params(
262
+ currency: Dodopayments::Currency::OrSymbol,
263
+ is_default: T::Boolean,
264
+ minimum_subtotal: Integer,
265
+ max_amount_possible: T.nilable(Integer)
266
+ ).returns(T.attached_class)
267
+ end
268
+ def self.new(
269
+ # The currency this option applies to.
270
+ currency:,
271
+ # Whether this is the default row FX conversions pivot from.
272
+ is_default:,
273
+ # Eligible-cart threshold in this currency's subunits (0 = no minimum).
274
+ minimum_subtotal:,
275
+ # The most this code discounts in this currency's subunits (flat deduction or
276
+ # percentage cap).
277
+ max_amount_possible: nil
278
+ )
279
+ end
280
+
281
+ sig do
282
+ override.returns(
283
+ {
284
+ currency: Dodopayments::Currency::TaggedSymbol,
285
+ is_default: T::Boolean,
286
+ minimum_subtotal: Integer,
287
+ max_amount_possible: T.nilable(Integer)
288
+ }
289
+ )
290
+ end
291
+ def to_hash
292
+ end
293
+ end
145
294
  end
146
295
  end
147
296
  end
@@ -21,7 +21,7 @@ module Dodopayments
21
21
  sig { returns(Integer) }
22
22
  attr_accessor :amount
23
23
 
24
- # The discount type. Currently only `percentage` is supported.
24
+ # The discount type: `percentage` or `flat` (`flat_per_unit` stays blocked).
25
25
  sig { returns(Dodopayments::DiscountType::OrSymbol) }
26
26
  attr_accessor :type
27
27
 
@@ -32,6 +32,31 @@ module Dodopayments
32
32
  sig { returns(T.nilable(String)) }
33
33
  attr_accessor :code
34
34
 
35
+ # Per-currency options (flat deduction / percentage cap + minimum subtotal).
36
+ # Required for `flat` codes (must include a resolvable default); optional
37
+ # per-currency caps for `percentage` codes. Per-row invariants are checked in
38
+ # `normalize_currency_options`, not via `#[validate(nested)]`.
39
+ sig do
40
+ returns(
41
+ T.nilable(
42
+ T::Array[Dodopayments::DiscountCreateParams::CurrencyOption]
43
+ )
44
+ )
45
+ end
46
+ attr_accessor :currency_options
47
+
48
+ # Who may redeem this discount code. Defaults to `any` (unrestricted). `specific`
49
+ # starts with zero attached customers (fails closed) until customers are attached
50
+ # via `POST /discounts/{id}/customers`.
51
+ sig do
52
+ returns(
53
+ T.nilable(
54
+ Dodopayments::DiscountCreateParams::CustomerEligibility::OrSymbol
55
+ )
56
+ )
57
+ end
58
+ attr_accessor :customer_eligibility
59
+
35
60
  # When the discount expires, if ever.
36
61
  sig { returns(T.nilable(Time)) }
37
62
  attr_accessor :expires_at
@@ -54,6 +79,11 @@ module Dodopayments
54
79
  sig { returns(T.nilable(String)) }
55
80
  attr_accessor :name
56
81
 
82
+ # Maximum number of times a single customer may redeem this discount. Must be
83
+ # `<= usage_limit` when both are set.
84
+ sig { returns(T.nilable(Integer)) }
85
+ attr_accessor :per_customer_usage_limit
86
+
57
87
  # Whether this discount should be preserved when a subscription changes plans.
58
88
  # Default: false (discount is removed on plan change)
59
89
  sig { returns(T.nilable(T::Boolean)) }
@@ -66,6 +96,11 @@ module Dodopayments
66
96
  sig { returns(T.nilable(T::Array[String])) }
67
97
  attr_accessor :restricted_to
68
98
 
99
+ # When the discount becomes active, if scheduled for the future. NULL = active
100
+ # immediately. Must be strictly before `expires_at` when both are set.
101
+ sig { returns(T.nilable(Time)) }
102
+ attr_accessor :starts_at
103
+
69
104
  # Number of subscription billing cycles this discount is valid for. If not
70
105
  # provided, the discount will be applied indefinitely to all recurring payments
71
106
  # related to the subscription.
@@ -81,11 +116,23 @@ module Dodopayments
81
116
  amount: Integer,
82
117
  type: Dodopayments::DiscountType::OrSymbol,
83
118
  code: T.nilable(String),
119
+ currency_options:
120
+ T.nilable(
121
+ T::Array[
122
+ Dodopayments::DiscountCreateParams::CurrencyOption::OrHash
123
+ ]
124
+ ),
125
+ customer_eligibility:
126
+ T.nilable(
127
+ Dodopayments::DiscountCreateParams::CustomerEligibility::OrSymbol
128
+ ),
84
129
  expires_at: T.nilable(Time),
85
130
  metadata: T::Hash[Symbol, Dodopayments::MetadataItem::Variants],
86
131
  name: T.nilable(String),
132
+ per_customer_usage_limit: T.nilable(Integer),
87
133
  preserve_on_plan_change: T::Boolean,
88
134
  restricted_to: T.nilable(T::Array[String]),
135
+ starts_at: T.nilable(Time),
89
136
  subscription_cycles: T.nilable(Integer),
90
137
  usage_limit: T.nilable(Integer),
91
138
  request_options: Dodopayments::RequestOptions::OrHash
@@ -97,23 +144,38 @@ module Dodopayments
97
144
  #
98
145
  # Must be at least 1.
99
146
  amount:,
100
- # The discount type. Currently only `percentage` is supported.
147
+ # The discount type: `percentage` or `flat` (`flat_per_unit` stays blocked).
101
148
  type:,
102
149
  # Optionally supply a code (will be uppercased).
103
150
  #
104
151
  # - Must be at least 3 characters if provided.
105
152
  # - If omitted, a random 16-character code is generated.
106
153
  code: nil,
154
+ # Per-currency options (flat deduction / percentage cap + minimum subtotal).
155
+ # Required for `flat` codes (must include a resolvable default); optional
156
+ # per-currency caps for `percentage` codes. Per-row invariants are checked in
157
+ # `normalize_currency_options`, not via `#[validate(nested)]`.
158
+ currency_options: nil,
159
+ # Who may redeem this discount code. Defaults to `any` (unrestricted). `specific`
160
+ # starts with zero attached customers (fails closed) until customers are attached
161
+ # via `POST /discounts/{id}/customers`.
162
+ customer_eligibility: nil,
107
163
  # When the discount expires, if ever.
108
164
  expires_at: nil,
109
165
  # Additional metadata for the discount
110
166
  metadata: nil,
111
167
  name: nil,
168
+ # Maximum number of times a single customer may redeem this discount. Must be
169
+ # `<= usage_limit` when both are set.
170
+ per_customer_usage_limit: nil,
112
171
  # Whether this discount should be preserved when a subscription changes plans.
113
172
  # Default: false (discount is removed on plan change)
114
173
  preserve_on_plan_change: nil,
115
174
  # List of product IDs to restrict usage (if any).
116
175
  restricted_to: nil,
176
+ # When the discount becomes active, if scheduled for the future. NULL = active
177
+ # immediately. Must be strictly before `expires_at` when both are set.
178
+ starts_at: nil,
117
179
  # Number of subscription billing cycles this discount is valid for. If not
118
180
  # provided, the discount will be applied indefinitely to all recurring payments
119
181
  # related to the subscription.
@@ -130,11 +192,21 @@ module Dodopayments
130
192
  amount: Integer,
131
193
  type: Dodopayments::DiscountType::OrSymbol,
132
194
  code: T.nilable(String),
195
+ currency_options:
196
+ T.nilable(
197
+ T::Array[Dodopayments::DiscountCreateParams::CurrencyOption]
198
+ ),
199
+ customer_eligibility:
200
+ T.nilable(
201
+ Dodopayments::DiscountCreateParams::CustomerEligibility::OrSymbol
202
+ ),
133
203
  expires_at: T.nilable(Time),
134
204
  metadata: T::Hash[Symbol, Dodopayments::MetadataItem::Variants],
135
205
  name: T.nilable(String),
206
+ per_customer_usage_limit: T.nilable(Integer),
136
207
  preserve_on_plan_change: T::Boolean,
137
208
  restricted_to: T.nilable(T::Array[String]),
209
+ starts_at: T.nilable(Time),
138
210
  subscription_cycles: T.nilable(Integer),
139
211
  usage_limit: T.nilable(Integer),
140
212
  request_options: Dodopayments::RequestOptions
@@ -143,6 +215,129 @@ module Dodopayments
143
215
  end
144
216
  def to_hash
145
217
  end
218
+
219
+ class CurrencyOption < Dodopayments::Internal::Type::BaseModel
220
+ OrHash =
221
+ T.type_alias do
222
+ T.any(
223
+ Dodopayments::DiscountCreateParams::CurrencyOption,
224
+ Dodopayments::Internal::AnyHash
225
+ )
226
+ end
227
+
228
+ # The currency this option applies to.
229
+ sig { returns(Dodopayments::Currency::OrSymbol) }
230
+ attr_accessor :currency
231
+
232
+ # Whether this row is the default to convert from for unconfigured currencies. At
233
+ # most one row per discount may be default.
234
+ sig { returns(T.nilable(T::Boolean)) }
235
+ attr_reader :is_default
236
+
237
+ sig { params(is_default: T::Boolean).void }
238
+ attr_writer :is_default
239
+
240
+ # The most this code discounts in this currency's subunits. For `flat` codes this
241
+ # is the deduction; for `percentage` codes it is the max-discount cap. Must be > 0
242
+ # if provided.
243
+ sig { returns(T.nilable(Integer)) }
244
+ attr_accessor :max_amount_possible
245
+
246
+ # Eligible-cart threshold in this currency's subunits (0 = no minimum).
247
+ sig { returns(T.nilable(Integer)) }
248
+ attr_reader :minimum_subtotal
249
+
250
+ sig { params(minimum_subtotal: Integer).void }
251
+ attr_writer :minimum_subtotal
252
+
253
+ # A per-currency discount option (request shape).
254
+ #
255
+ # `max_amount_possible` is the most this code discounts in this currency — the
256
+ # flat deduction for `flat` codes, or the max-discount cap for `percentage` codes.
257
+ # Maps to the DB column of the same name.
258
+ sig do
259
+ params(
260
+ currency: Dodopayments::Currency::OrSymbol,
261
+ is_default: T::Boolean,
262
+ max_amount_possible: T.nilable(Integer),
263
+ minimum_subtotal: Integer
264
+ ).returns(T.attached_class)
265
+ end
266
+ def self.new(
267
+ # The currency this option applies to.
268
+ currency:,
269
+ # Whether this row is the default to convert from for unconfigured currencies. At
270
+ # most one row per discount may be default.
271
+ is_default: nil,
272
+ # The most this code discounts in this currency's subunits. For `flat` codes this
273
+ # is the deduction; for `percentage` codes it is the max-discount cap. Must be > 0
274
+ # if provided.
275
+ max_amount_possible: nil,
276
+ # Eligible-cart threshold in this currency's subunits (0 = no minimum).
277
+ minimum_subtotal: nil
278
+ )
279
+ end
280
+
281
+ sig do
282
+ override.returns(
283
+ {
284
+ currency: Dodopayments::Currency::OrSymbol,
285
+ is_default: T::Boolean,
286
+ max_amount_possible: T.nilable(Integer),
287
+ minimum_subtotal: Integer
288
+ }
289
+ )
290
+ end
291
+ def to_hash
292
+ end
293
+ end
294
+
295
+ # Who may redeem this discount code. Defaults to `any` (unrestricted). `specific`
296
+ # starts with zero attached customers (fails closed) until customers are attached
297
+ # via `POST /discounts/{id}/customers`.
298
+ module CustomerEligibility
299
+ extend Dodopayments::Internal::Type::Enum
300
+
301
+ TaggedSymbol =
302
+ T.type_alias do
303
+ T.all(
304
+ Symbol,
305
+ Dodopayments::DiscountCreateParams::CustomerEligibility
306
+ )
307
+ end
308
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
309
+
310
+ ANY =
311
+ T.let(
312
+ :any,
313
+ Dodopayments::DiscountCreateParams::CustomerEligibility::TaggedSymbol
314
+ )
315
+ FIRST_TIME =
316
+ T.let(
317
+ :first_time,
318
+ Dodopayments::DiscountCreateParams::CustomerEligibility::TaggedSymbol
319
+ )
320
+ EXISTING =
321
+ T.let(
322
+ :existing,
323
+ Dodopayments::DiscountCreateParams::CustomerEligibility::TaggedSymbol
324
+ )
325
+ SPECIFIC =
326
+ T.let(
327
+ :specific,
328
+ Dodopayments::DiscountCreateParams::CustomerEligibility::TaggedSymbol
329
+ )
330
+
331
+ sig do
332
+ override.returns(
333
+ T::Array[
334
+ Dodopayments::DiscountCreateParams::CustomerEligibility::TaggedSymbol
335
+ ]
336
+ )
337
+ end
338
+ def self.values
339
+ end
340
+ end
146
341
  end
147
342
  end
148
343
  end
@@ -14,7 +14,9 @@ module Dodopayments
14
14
  )
15
15
  end
16
16
 
17
- # Filter by active status (true = not expired, false = expired)
17
+ # Filter by active status. `true` = currently redeemable (started, not expired,
18
+ # not usage-exhausted). `false` = not currently redeemable (expired,
19
+ # usage-exhausted, or pending a future `starts_at`).
18
20
  sig { returns(T.nilable(T::Boolean)) }
19
21
  attr_reader :active
20
22
 
@@ -68,7 +70,9 @@ module Dodopayments
68
70
  ).returns(T.attached_class)
69
71
  end
70
72
  def self.new(
71
- # Filter by active status (true = not expired, false = expired)
73
+ # Filter by active status. `true` = currently redeemable (started, not expired,
74
+ # not usage-exhausted). `false` = not currently redeemable (expired,
75
+ # usage-exhausted, or pending a future `starts_at`).
72
76
  active: nil,
73
77
  # Filter by discount code (partial match, case-insensitive)
74
78
  code: nil,
@@ -8,6 +8,7 @@ module Dodopayments
8
8
  TaggedSymbol = T.type_alias { T.all(Symbol, Dodopayments::DiscountType) }
9
9
  OrSymbol = T.type_alias { T.any(Symbol, String) }
10
10
 
11
+ FLAT = T.let(:flat, Dodopayments::DiscountType::TaggedSymbol)
11
12
  PERCENTAGE = T.let(:percentage, Dodopayments::DiscountType::TaggedSymbol)
12
13
 
13
14
  sig do