Charge tax on products (#4361)

* Initial Anrok integration

* Query cache, fmt, clippy

* Fmt

* Use payment intent function in edit_subscription

* Attach Anrok client, use payments in index_billing

* Integrate Anrok with refunds

* Bug fixes

* More bugfixes

* Fix resubscriptions

* Medal promotion bugfixes

* Use stripe metadata constants everywhere

* Pre-fill values in products_tax_identifiers

* Cleanup billing route module

* Cleanup

* Email notification for tax charge

* Don't charge tax on users which haven't been notified of tax change

* Fix taxnotification.amount templates

* Update .env.docker-compose

* Update .env.local

* Clippy

* Fmt

* Query cache

* Periodically update tax amount on upcoming charges

* Fix queries

* Skip indexing tax amount on charges if no charges to process

* chore: query cache, clippy, fmt

* Fix a lot of things

* Remove test code

* chore: query cache, clippy, fmt

* Fix money formatting

* Fix conflicts

* Extra documentation, handle tax association properly

* Track loss in tax drift

* chore: query cache, clippy, fmt

* Add subscription.id variable

* chore: query cache, clippy, fmt

* chore: query cache, clippy, fmt
This commit is contained in:
François-Xavier Talbot
2025-09-25 12:29:29 +01:00
committed by GitHub
parent 47020f34b6
commit 4228a193e9
44 changed files with 3438 additions and 1330 deletions

View File

@@ -16,7 +16,9 @@ use util::cors::default_cors;
use crate::background_task::update_versions;
use crate::database::ReadOnlyPgPool;
use crate::queue::billing::{index_billing, index_subscriptions};
use crate::queue::moderation::AutomatedModerationQueue;
use crate::util::anrok;
use crate::util::env::{parse_strings_from_var, parse_var};
use crate::util::ratelimit::{AsyncRateLimiter, GCRAParameters};
use sync::friends::handle_pubsub;
@@ -58,6 +60,7 @@ pub struct LabrinthConfig {
pub automated_moderation_queue: web::Data<AutomatedModerationQueue>,
pub rate_limiter: web::Data<AsyncRateLimiter>,
pub stripe_client: stripe::Client,
pub anrok_client: anrok::Client,
pub email_queue: web::Data<EmailQueue>,
}
@@ -71,6 +74,7 @@ pub fn app_setup(
file_host: Arc<dyn file_hosting::FileHost + Send + Sync>,
maxmind: Arc<queue::maxmind::MaxMindIndexer>,
stripe_client: stripe::Client,
anrok_client: anrok::Client,
email_queue: EmailQueue,
enable_background_tasks: bool,
) -> LabrinthConfig {
@@ -161,10 +165,12 @@ pub fn app_setup(
let pool_ref = pool.clone();
let redis_ref = redis_pool.clone();
let stripe_client_ref = stripe_client.clone();
let anrok_client_ref = anrok_client.clone();
actix_rt::spawn(async move {
loop {
routes::internal::billing::index_billing(
index_billing(
stripe_client_ref.clone(),
anrok_client_ref.clone(),
pool_ref.clone(),
redis_ref.clone(),
)
@@ -175,11 +181,16 @@ pub fn app_setup(
let pool_ref = pool.clone();
let redis_ref = redis_pool.clone();
let stripe_client_ref = stripe_client.clone();
let anrok_client_ref = anrok_client.clone();
actix_rt::spawn(async move {
loop {
routes::internal::billing::index_subscriptions(
index_subscriptions(
pool_ref.clone(),
redis_ref.clone(),
stripe_client_ref.clone(),
anrok_client_ref.clone(),
)
.await;
tokio::time::sleep(Duration::from_secs(60 * 5)).await;
@@ -287,6 +298,7 @@ pub fn app_setup(
automated_moderation_queue,
rate_limiter: limiter,
stripe_client,
anrok_client,
email_queue: web::Data::new(email_queue),
}
}
@@ -322,6 +334,7 @@ pub fn app_config(
.app_data(labrinth_config.active_sockets.clone())
.app_data(labrinth_config.automated_moderation_queue.clone())
.app_data(web::Data::new(labrinth_config.stripe_client.clone()))
.app_data(web::Data::new(labrinth_config.anrok_client.clone()))
.app_data(labrinth_config.rate_limiter.clone())
.configure({
#[cfg(target_os = "linux")]
@@ -501,6 +514,9 @@ pub fn check_env_vars() -> bool {
failed |= check_var::<String>("AVALARA_1099_API_TEAM_ID");
failed |= check_var::<String>("AVALARA_1099_COMPANY_ID");
failed |= check_var::<String>("ANROK_API_URL");
failed |= check_var::<String>("ANROK_API_KEY");
failed |= check_var::<String>("COMPLIANCE_PAYOUT_THRESHOLD");
failed |= check_var::<String>("PAYOUT_ALERT_SLACK_WEBHOOK");