Commit Graph

15 Commits

Author SHA1 Message Date
Stephon Brown
e5419a7662 [PM-37597] Set Automatic Tax and Prevent Tax Exempt Mutations (#7662)
* feat(billing): add feature flag for automatic tax enforcement

* refactor(billing): remove unused SubscriptionUpdateOptionsExtensions

* refactor(billing): inject IFeatureService into billing services and commands

* feat(billing): conditionalize customer tax exemption logic with feature flag

* feat(billing): conditionally enable Stripe automatic tax in OrganizationBillingService

* test(billing): add unit tests for Stripe automatic tax feature flag

* fix(billing): Run dotnet format

* test(Premium): use class-level IFeatureService mock in UpgradePremiumToOrganizationCommandTests

* refactor(billing): consolidate customer return conditions for automatic tax

* refactor(billing): broaden postal code validation for organization creation

* refactor(billing): remove PM37597 feature flag for automatic tax logic

* Revert "refactor(billing): broaden postal code validation for organization creation"

This reverts commit cddbda838c.

* fix(test): remove outdated test
2026-05-19 13:18:06 -05:00
Conner Turnbull
aad805a976 [PM-34866][PM-34865] Fix EnableAutomaticTaxAsync to update schedule phases (#7437)
* [PM-34866] Fix EnableAutomaticTaxAsync to update schedule phases

* Use test clock frozen time for phase filtering

* Expand test_clock on customer subscription fetches
2026-04-10 15:50:41 +00:00
Conner Turnbull
c604379f04 [PM-33901] Implement schedule-aware tax handling (#7319)
Make tax-related subscription updates schedule-aware during the ~15-day
window between invoice.upcoming and renewal. When a subscription schedule
is present and the feature flag is enabled, update default_settings.automatic_tax
on the schedule instead of the subscription directly.

Modified paths:
- UpcomingInvoiceHandler: AlignOrganizationTaxConcernsAsync,
  AlignPremiumUsersTaxConcernsAsync, new shared EnableAutomaticTaxAsync helper
- UpdateBillingAddressCommand: EnableAutomaticTaxAsync, added IFeatureService
2026-03-27 14:27:36 -04:00
Stephon Brown
8302509bf9 [PM-31645] Implement Swiss Tax Logic (#7186)
* feat(tax): introduce direct tax country utilities and Switzerland constant

* refactor(tax): use `TaxHelpers.IsDirectTaxCountry` for country checks

* feat(tax): implement customer tax exempt status alignment

* test(tax): add comprehensive unit tests for tax exempt alignment logic

* tests(billing): clarify tests

* fix(billing): run dotnet format

* fix(billing): run dotnet format

* fix(billing): Prevent NullReferenceException when accessing customer country

* test(billing): Add Stripe adapter mocks for AdjustSubscription scenarios

* refactor(billing): apply null-conditional operator for address country access

* feat(billing): update missing tax exemption determinations

* test(billing): add unit tests for tax exemption updates

* fix(billing) run dotnet format

* fix(billing): add nullability

* style(files): normalize file encoding for billing utilities

* refactor(TaxHelpers): simplify tax exempt status determination

* test(Tax): update tax exempt determination tests

* fix(billing): revert postal code validation

* test(billing): update tax exempt tests

* fix(billing): run dotnet format
2026-03-17 14:09:41 -04:00
Stephon Brown
ee84237643 [PM-30271] Create Retrieve Eligible Subscription Discounts Endpoint (#7063)
* feat(billing): add subscription discount response model

* feat(billing): implement discount audience filters

* feat(billing): introduce subscription discount service

* feat(billing): add query for applicable discounts

* feat(api): add endpoint for applicable discounts

* chore(billing): register new billing services and queries

* refactor(tests): rename discount audience filter test methods for clarity

* refactor(billing): remove unused Id property from SubscriptionDiscountResponseModel

* feat(billing): add feature flag to GetApplicableDiscountsAsync endpoint

* format(billing): dotnet format and remove pricing import

* refactor(billing): change discount audience filter factory to singleton

* test(discount): add test to verify filter retrieval for all audience types

* feat(billing): add DiscountTierType enum

* feat(billing): define Stripe product IDs and tier mapping

* feat(billing): introduce DiscountEligibility record

* feat(billing): update IDiscountAudienceFilter for tier eligibility

* feat(billing): add ListSubscriptionsAsync to IStripeAdapter

* feat(billing): implement ListSubscriptionsAsync in StripeAdapter

* feat(billing): implement AllUsersFilter for discount audience

* feat(billing): refactor UserHasNoPreviousSubscriptionsFilter for tier eligibility

* feat(billing): update DiscountAudienceFilterFactory for DI

* feat(billing): update ISubscriptionDiscountService for tier eligibility

* feat(billing): implement SubscriptionDiscountService tier eligibility

* feat(billing): update SubscriptionDiscountResponseModel with tier eligibility

* feat(billing): add GetTierEligibilityDictionary utility

* feat(billing): update GetApplicableDiscountsQuery to use tier eligibility

* chore(billing): update DI registrations for discount services

* test(billing): add/update unit tests for discount features

* fix(billing): remove unneeded import

* fix(billing): run dotnet format

* refactor(billing): remove unused Teams and Enterprise discount tiers

* refactor(billing): move DiscountEligibility to Models namespace

* refactor(billing): update discount audience filter DI to scoped

* perf(billing): optimize UserHasNoPreviousSubscriptionsFilter with caching

* refactor(billing): remove StripeProductIds from subscription discount response model

* test(billing): update GetApplicableDiscountsQueryTests after StripeProductIds removal

* fix(billing): Run dotnet format
2026-03-03 13:39:10 -05:00
Alex Morask
cfd5bedae0 [PM-31040] Replace ISetupIntentCache with customer-based approach (#6954)
* docs(billing): add design document for replacing SetupIntent cache

* docs(billing): add implementation plan for replacing SetupIntent cache

* feat(db): add gateway lookup stored procedures for Organization, Provider, and User

* feat(db): add gateway lookup indexes to Organization, Provider, and User table definitions

* chore(db): add SQL Server migration for gateway lookup indexes and stored procedures

* feat(repos): add gateway lookup methods to IOrganizationRepository and Dapper implementation

* feat(repos): add gateway lookup methods to IProviderRepository and Dapper implementation

* feat(repos): add gateway lookup methods to IUserRepository and Dapper implementation

* feat(repos): add EF OrganizationRepository gateway lookup methods and index configuration

* feat(repos): add EF ProviderRepository gateway lookup methods and index configuration

* feat(repos): add EF UserRepository gateway lookup methods and index configuration

* chore(db): add EF migrations for gateway lookup indexes

* refactor(billing): update SetupIntentSucceededHandler to use repository instead of cache

* refactor(billing): simplify StripeEventService by expanding customer on SetupIntent

* refactor(billing): query Stripe for SetupIntents by customer ID in GetPaymentMethodQuery

* refactor(billing): query Stripe for SetupIntents by customer ID in HasPaymentMethodQuery

* refactor(billing): update OrganizationBillingService to set customer on SetupIntent

* refactor(billing): update ProviderBillingService to set customer on SetupIntent and query by customer

* refactor(billing): update UpdatePaymentMethodCommand to set customer on SetupIntent

* refactor(billing): remove bank account support from CreatePremiumCloudHostedSubscriptionCommand

* refactor(billing): remove OrganizationBillingService.UpdatePaymentMethod dead code

* refactor(billing): remove ProviderBillingService.UpdatePaymentMethod

* refactor(billing): remove PremiumUserBillingService.UpdatePaymentMethod and UserService.ReplacePaymentMethodAsync

* refactor(billing): remove SubscriberService.UpdatePaymentSource and related dead code

* refactor(billing): update SubscriberService.GetPaymentSourceAsync to query Stripe by customer ID

Add Task 15a to plan - this was a missed requirement for updating
GetPaymentSourceAsync which still used the cache.

* refactor(billing): complete removal of PremiumUserBillingService.Finalize and UserService.SignUpPremiumAsync

* refactor(billing): remove ISetupIntentCache and SetupIntentDistributedCache

* chore: remove temporary planning documents

* chore: run dotnet format

* fix(billing): add MaxLength(50) to Provider gateway ID properties

* chore(db): add EF migrations for Provider gateway column lengths

* chore: run dotnet format

* chore: rename SQL migration for chronological order
2026-02-18 13:20:25 -06:00
Alex Morask
4667af6cf9 [PM-30444] Handle missing Braintree customer in GetPaymentMethodQuery (#6899)
* Handle missing Braintree customer in GetPaymentMethodQuery

* Allow addition of PayPal payment method when bad Braintree customer ID is linked

* Run dotnet format
2026-02-04 07:48:06 -06:00
cyprain-okeke
76a8f0fd95 [PM 29610]Update Account Storage Endpoint (#6750)
* update account storage endpoint

* Fix the failing test

* Added flag and refactor base on pr comments

* fix the lint error

* Resolve the pr comments

* Fix the failing test

* Fix the failing test

* Return none

* Resolve the lint error

* Fix the failing test

* Add the missing test

* Formatting issues fixed
2026-01-05 10:52:52 -06:00
Kyle Denney
99e1326039 [PM-24616] refactor stripe adapter (#6527)
* move billing services+tests to billing namespaces

* reorganized methods in file and added comment headers

* renamed StripeAdapter methods for better clarity

* clean up redundant qualifiers

* Upgrade Stripe.net to v48.4.0

* Update PreviewTaxAmountCommand

* Remove unused UpcomingInvoiceOptionExtensions

* Added SubscriptionExtensions with GetCurrentPeriodEnd

* Update PremiumUserBillingService

* Update OrganizationBillingService

* Update GetOrganizationWarningsQuery

* Update BillingHistoryInfo

* Update SubscriptionInfo

* Remove unused Sql Billing folder

* Update StripeAdapter

* Update StripePaymentService

* Update InvoiceCreatedHandler

* Update PaymentFailedHandler

* Update PaymentSucceededHandler

* Update ProviderEventService

* Update StripeEventUtilityService

* Update SubscriptionDeletedHandler

* Update SubscriptionUpdatedHandler

* Update UpcomingInvoiceHandler

* Update ProviderSubscriptionResponse

* Remove unused Stripe Subscriptions Admin Tool

* Update RemoveOrganizationFromProviderCommand

* Update ProviderBillingService

* Update RemoveOrganizatinoFromProviderCommandTests

* Update PreviewTaxAmountCommandTests

* Update GetCloudOrganizationLicenseQueryTests

* Update GetOrganizationWarningsQueryTests

* Update StripePaymentServiceTests

* Update ProviderBillingControllerTests

* Update ProviderEventServiceTests

* Update SubscriptionDeletedHandlerTests

* Update SubscriptionUpdatedHandlerTests

* Resolve Billing test failures

I completely removed tests for the StripeEventService as they were using a system I setup a while back that read JSON files of the Stripe event structure. I did not anticipate how frequently these structures would change with each API version and the cost of trying to update these specific JSON files to test a very static data retrieval service far outweigh the benefit.

* Resolve Core test failures

* Run dotnet format

* Remove unused provider migration

* Fixed failing tests

* Run dotnet format

* Replace the old webhook secret key with new one (#6223)

* Fix compilation failures in additions

* Run dotnet format

* Bump Stripe API version

* Fix recent addition: CreatePremiumCloudHostedSubscriptionCommand

* Fix new code in main according to Stripe update

* Fix InvoiceExtensions

* Bump SDK version to match API Version

* cleanup

* fixing items missed after the merge

* use expression body for all simple returns

* forgot fixes, format, and pr feedback

* claude pr feedback

* pr feedback and cleanup

* more claude feedback

---------

Co-authored-by: Alex Morask <amorask@bitwarden.com>
Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
2025-12-12 15:32:43 -06:00
Alex Morask
62a0936c2e [PM-25183] Update the BitPay purchasing procedure (#6396)
* Revise BitPay controller

* Run dotnet format

* Kyle's feedback

* Run dotnet format

* Temporary logging

* Whoops

* Undo temporary logging
2025-10-28 09:31:59 -05:00
Stephon Brown
ff4b3eb9e5 [PM-27123] Account Credit not Showing for Premium Upgrade Payment (#6484)
* feat(billing): add PaymentMethod union

* feat(billing):  add nontokenized payment method

* feat(billing): add validation for tokinized and nontokenized payments

* feat(billing): update and add payment method requests

* feat(billing): update command with new union object

* test(billing): add tests for account credit for user.

* feat(billing): update premium cloud hosted subscription request

* fix(billing): dotnet format

* tests(billing): include payment method tests

* fix(billing): clean up tests and converter method
2025-10-23 14:47:23 -04:00
Alex Morask
34f5ffd981 [PM-26692] Count unverified setup intent as payment method during organization subscription creation (#6433)
* Updated check that determines whether org has payment method to include bank account when determining how to set trial_settings

* Run dotnet format
2025-10-09 13:20:28 -05:00
Alex Morask
3dd5accb56 [PM-24964] Stripe-hosted bank account verification (#6263)
* Implement bank account hosted URL verification with webhook handling notification

* Fix tests

* Run dotnet format

* Remove unused VerifyBankAccount operation

* Stephon's feedback

* Removing unused test

* TEMP: Add logging for deployment check

* Run dotnet format

* fix test

* Revert "fix test"

This reverts commit b8743ab3b5.

* Revert "Run dotnet format"

This reverts commit 5c861b0b72.

* Revert "TEMP: Add logging for deployment check"

This reverts commit 0a88acd6a1.

* Resolve GetPaymentMethodQuery order of operations
2025-09-09 12:22:42 -05:00
Alex Morask
d914ab8a98 [PM-23687] Support free organizations on Payment Details page (#6084)
* Resolve JSON serialization bug in OneOf converters and organize pricing models

* Support free organizations for payment method and billing address flows

* Run dotnet format
2025-07-14 12:39:49 -05:00
Alex Morask
7f65a655d4 [PM-21881] Manage payment details outside of checkout (#6032)
* Add feature flag

* Further establish billing command pattern and use in PreviewTaxAmountCommand

* Add billing address models/commands/queries/tests

* Update TypeReadingJsonConverter to account for new union types

* Add payment method models/commands/queries/tests

* Add credit models/commands/queries/tests

* Add command/query registrations

* Add new endpoints to support new command model and payment functionality

* Run dotnet format

* Add InjectUserAttribute for easier AccountBillilngVNextController handling

* Add InjectOrganizationAttribute for easier OrganizationBillingVNextController handling

* Add InjectProviderAttribute for easier ProviderBillingVNextController handling

* Add XML documentation for billing command pipeline

* Fix StripeConstants post-nullability

* More nullability cleanup

* Run dotnet format
2025-07-10 08:32:25 -05:00