Files
cal.diy/turbo.json
T
fadfba8830 feat: Credit System (SMS) (#20126)
* Add credits section to billing

* create seperate router for credits

* add stripe checkout session

* schema changes + code improvements

* rename to creditBalance

* custom quantify input with error message

* add checkout session completed webhook endpoint

* fix typo

* UI fixes

* add payCredits handler

* add error toast message

* allow scheduling sms up as close to 15 minutes in the future

* schedule at most 2 hours in advance

* webhook to pay for sent sms

* continued work on twilio callback

* code clean up

* further implementation for credit handling

* add migration

* object as param for scheduleSMS

* object as param for sendSMS

* fix TrpcSessionUser imports

* fix imports

* add db changes

* add cron job for price setting

* twilio status callback to create expense log

* remove unused code

* set up low credit balance email

* fixes for buying credits

* fixes in api/twilio/webhook

* add test to save credits to credits balance

* fix typos

* add new helper function chargeCredits

* expand twilioProvider

* fix type errors

* adjust tests

* type errors

* clean up

* clean up

* fix subscription active check

* remove some user/org related code

* more changes to remove user/org support

* send emails seperatly to admins

* fixes for team billing page

* fix stripe success url

* fixes to creating expense log

* email imrovements and more

* get monthly team price from stripe

* fix import

* fix monthly credits calculation

* finsih low credit balance warning email

* credit balance limit reached email

* create CreditService

* cancel SMS and send as email instead

* add messageDispatcher

* fix type error

* fix type error

* fix type error

* fix import

* fix unit test

* clean up twilioProvider

* clean up chckSmsPrices/route

* add missing translations

* add skeleton loader

* add admin check to get handler

* code clean up + fixes

* improve scheduling with fallback

* fix type error

* add bookingUid to handleSendingSMS

* add unit tests for creditService

* add more tests to credit-service.test.ts

* add test for cancelScheduledMessagesAndScheduleEmails

* fix test and type error

* add back resolve

* fix empty resolve

* adjust limitReachedAt logic

* address mrge comment on styling

* add getAdminMembership to repository

* twilio/webhook clean up (feedback)

* feedback - clean up

* remove todo comment

* clean up twilio/webhook

* code clean up

* add use client

* add createOneTimeCheckout to stripe service

* refactor repository pattern

* small fixes + clean up

* fix type error

* add missing import

* fix hasAvailableCredits for user

* force-dynamic

* rename credits to creditBalance

* fix stripe import

* remove not needed code

* fix e2e tests

* improve low balance warning email

* dynamic-import CreditService

* index.ts

* fix e2e tests

* remove dynamic import CreditService

* Revert "remove dynamic import CreditService"

This reverts commit e272978a7ff3fc5a04139e656c9f8d2c84a40dda.

* no need to dynamic-import credit service

* Revert "no need to dynamic-import credit service"

This reverts commit ba5ae488d08979a65fb47b5d0722cda9f45d6ea0.

* only select id in getAdminMembership

* revert billing/package.json

* fix type checks

* fix type checks

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2025-05-13 09:11:44 +02:00

484 lines
14 KiB
JSON

{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"@calcom/prisma#build": {
"cache": false,
"dependsOn": ["post-install"]
},
"@calcom/prisma#db-migrate": {
"cache": false,
"dependsOn": ["@calcom/prisma#db-up"],
"inputs": ["./schema.prisma", "./migrations/**/*.sql"]
},
"@calcom/prisma#db-seed": {
"cache": false,
"dependsOn": ["@calcom/prisma#db-migrate"]
},
"@calcom/prisma#db-up": {
"cache": false
},
"@calcom/prisma#dx": {
"cache": false,
"dependsOn": ["@calcom/prisma#db-migrate"]
},
"@calcom/trpc#build": {
"outputs": ["./types"]
},
"@calcom/web#build": {
"dependsOn": ["^build"],
"outputs": [".next/**"],
"env": [
"NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL",
"NEXT_PUBLIC_BOOKER_NUMBER_OF_DAYS_TO_LOAD",
"NEXT_PUBLIC_IS_E2E",
"NEXT_PUBLIC_SENTRY_DSN",
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY",
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRODUCT_ID",
"NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
"NEXT_PUBLIC_STRIPE_TEAM_MONTHLY_PRICE_ID",
"NEXT_PUBLIC_WEBAPP_URL",
"NEXT_PUBLIC_WEBSITE_URL",
"SENTRY_AUTH_TOKEN",
"SENTRY_DEBUG",
"SENTRY_MAX_SPANS",
"SENTRY_ORG",
"SENTRY_PROJECT",
"SENTRY_TRACES_SAMPLE_RATE",
"SENTRY_REPLAYS_SESSION_SAMPLE_RATE",
"SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE",
"STRIPE_PREMIUM_PLAN_PRODUCT_ID",
"STRIPE_TEAM_MONTHLY_PRICE_ID",
"NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID",
"STRIPE_TEAM_PRODUCT_ID",
"STRIPE_ORG_MONTHLY_PRICE_ID",
"STRIPE_ORG_PRODUCT_ID",
"NEXT_PUBLIC_API_V2_URL",
"NEXT_PUBLIC_VAPID_PUBLIC_KEY",
"BUILD_STANDALONE",
"NEXT_PUBLIC_API_HITPAY_PRODUCTION",
"NEXT_PUBLIC_API_HITPAY_SANDBOX"
]
},
"@calcom/web#dx": {
"cache": false,
"dependsOn": ["@calcom/prisma#dx"]
},
"@calcom/web#start": {
"cache": false,
"dependsOn": []
},
"@calcom/api-v2#build": {
"dependsOn": ["^build"],
"env": [
"NODE_ENV",
"API_PORT",
"DATABASE_READ_URL",
"DATABASE_WRITE_URL",
"LOG_LEVEL",
"NEXTAUTH_SECRET"
]
},
"@calcom/ai#build": {
"env": [
"FRONTEND_URL",
"BACKEND_URL",
"APP_ID",
"APP_URL",
"SENDER_DOMAIN",
"PARSE_KEY",
"NODE_ENV",
"OPENAI_API_KEY",
"SENDGRID_API_KEY",
"DATABASE_URL"
]
},
"@calcom/website#build": {
"dependsOn": ["^build"],
"outputs": [".next/**"],
"env": [
"CSP_POLICY",
"DATABASE_URL",
"DATOCMS_API_TOKEN",
"DATOCMS_GRAPHQL_ENDPOINT",
"DATOCMS_WEBHOOK_SECRET",
"DATOCMS_PREVIEW_SECRET",
"ENVIRONMENT_URL",
"NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL",
"NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN",
"NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE",
"NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE",
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE",
"NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE",
"NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
"NEXT_PUBLIC_WEBAPP_URL",
"NEXT_PUBLIC_WEBSITE_URL",
"NEXT_PUBLIC_VERCEL_ENV",
"NEXT_PUBLIC_VERCEL_BRANCH_URL",
"NEXT_PUBLIC_POSTHOG_KEY",
"NEXT_PUBLIC_POSTHOG_HOST",
"SENDGRID_VERIFICATION_KEY",
"STRIPE_FREE_PLAN_PRODUCT_ID",
"STRIPE_PREMIUM_PLAN_PRODUCT_ID",
"STRIPE_PRO_PLAN_PRODUCT_ID",
"STRIPE_SUPPORT_TABLE",
"MOTIFLAND_REST_ENDPOINT",
"MOTIFLAND_DOCS_API_KEY",
"MOTIFLAND_DOCS_PROJECT_ID",
"PLAIN_HMAC_SECRET_KEY",
"PLAIN_API_KEY",
"PLAIN_API_URL",
"NEXT_PUBLIC_PLAIN_CHAT_ID",
"PLAIN_CHAT_HMAC_SECRET_KEY",
"NEXT_PUBLIC_PLAIN_CHAT_EXCLUDED_PATHS"
]
},
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"db-deploy": {
"cache": false,
"inputs": ["./migrations/**/*.sql", "./prisma/migrations/**/*.sql"]
},
"db-seed": {},
"deploy": {
"cache": false,
"dependsOn": ["@calcom/web#build"]
},
"clean": {
"cache": false,
"outputs": ["dist/**", "build/**"]
},
"dev": {
"dependsOn": ["//#env-check:common", "//#env-check:app-store"],
"cache": false
},
"dx": {
"dependsOn": ["//#env-check:common", "//#env-check:app-store"],
"cache": false
},
"lint": {
"cache": false
},
"lint:fix": {
"cache": false
},
"lint:report": {
"cache": false,
"outputs": ["lint-results"]
},
"post-install": {
"dependsOn": [],
"outputs": ["../../node_modules/@prisma/client/**", "../../node_modules/@prisma/admin-client/**"],
"inputs": ["./schema.prisma", "./prisma/schema.prisma"],
"env": ["PRISMA_GENERATE_DATAPROXY"]
},
"@calcom/prisma#post-install": {
"cache": false,
"outputs": ["dist/**", "build/**"]
},
"start": {
"outputs": ["dist/**", "build/**"]
},
"embed-tests": {
"cache": false,
"outputs": ["dist/**", "build/**"]
},
"embed-tests-quick": {
"cache": false,
"outputs": ["dist/**", "build/**"]
},
"type-check": {
"cache": false,
"dependsOn": ["@calcom/trpc#build"]
},
"type-check:ci": {
"cache": false,
"dependsOn": ["@calcom/trpc#build"]
},
"@calcom/prisma#db-reset": {
"cache": false,
"outputs": ["dist/**", "build/**"]
},
"@calcom/app-store-cli#build": {
"cache": false,
"inputs": ["../../app-store/**/**"],
"outputs": ["../../app-store/apps.server.generated.ts", "../../app-store/apps.browser.generated.tsx"]
},
"@calcom/embed-react#type-check": {
"dependsOn": ["@calcom/embed-core#build", "@calcom/embed-snippet#build"],
"outputs": ["dist/**", "build/**"]
},
"@calcom/embed-core#build": {
"cache": false,
"outputs": ["../../../apps/web/public/embed/**"],
"env": [
"EMBED_PUBLIC_VERCEL_URL",
"EMBED_PUBLIC_WEBAPP_URL",
"EMBED_PUBLIC_EMBED_FINGER_PRINT",
"EMBED_PUBLIC_EMBED_VERSION"
]
},
"embed-tests-update-snapshots:ci": {
"cache": false,
"dependsOn": [
"@calcom/prisma#db-seed",
"@calcom/web#build",
"^build",
"^embed-tests-update-snapshots:ci"
],
"outputs": ["dist/**", "build/**"]
},
"//#env-check:common": {
"cache": false,
"inputs": ["./.env.example", "./.env"],
"outputs": ["./.env"]
},
"//#env-check:app-store": {
"cache": false,
"inputs": ["./.env.appStore.example", "./.env.appStore"],
"outputs": ["./.env.appStore"]
},
"//#test": {
"cache": false
}
},
"globalDependencies": ["yarn.lock"],
"globalEnv": [
"ALLOWED_HOSTNAMES",
"ANALYZE",
"API_KEY_PREFIX",
"APP_USER_NAME",
"BASECAMP3_CLIENT_ID",
"BASECAMP3_CLIENT_SECRET",
"BASECAMP3_USER_AGENT",
"BLACKLISTED_GUEST_EMAILS",
"AUTH_BEARER_TOKEN_VERCEL",
"BUILD_ID",
"CAL_SIGNATURE_TOKEN",
"CALCOM_PRIVATE_API_ROUTE",
"CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY",
"CALCOM_CREDENTIAL_SYNC_ENDPOINT",
"CALCOM_CREDENTIAL_SYNC_SECRET",
"CALCOM_CREDENTIAL_SYNC_SECRET_HEADER_NAME",
"CALCOM_ENV",
"CALCOM_LICENSE_KEY",
"CALCOM_QA_EMAIL",
"CALCOM_QA_PASSWORD",
"CALCOM_TELEMETRY_DISABLED",
"CALCOM_CREDENTIAL_SYNC_HEADER_NAME",
"CALENDSO_ENCRYPTION_KEY",
"CALCOM_CREDENTIAL_SYNC_SECRET",
"CI",
"CLOSECOM_CLIENT_ID",
"CLOSECOM_CLIENT_SECRET",
"CRON_API_KEY",
"CRON_SECRET",
"CRON_ENABLE_APP_SYNC",
"CLOUDFLARE_TURNSTILE_SECRET",
"DAILY_API_KEY",
"DAILY_SCALE_PLAN",
"DAILY_WEBHOOK_SECRET",
"DAILY_MEETING_ENDED_WEBHOOK_SECRET",
"DATABASE_CHUNK_SIZE",
"DATABASE_DIRECT_URL",
"DATABASE_URL",
"DEBUG",
"DUB_API_KEY",
"NEXT_PUBLIC_DUB_PROGRAM_ID",
"E2E_TEST_APPLE_CALENDAR_EMAIL",
"E2E_TEST_APPLE_CALENDAR_PASSWORD",
"E2E_TEST_CALCOM_QA_EMAIL",
"E2E_TEST_CALCOM_QA_PASSWORD",
"E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS",
"E2E_TEST_CALCOM_GCAL_KEYS",
"E2E_TEST_MAILHOG_ENABLED",
"E2E_TEST_OIDC_CLIENT_ID",
"E2E_TEST_OIDC_CLIENT_SECRET",
"E2E_TEST_OIDC_PROVIDER_DOMAIN",
"E2E_TEST_OIDC_USER_EMAIL",
"E2E_TEST_OIDC_USER_PASSWORD",
"E2E_TEST_SAML_ADMIN_EMAIL",
"E2E_TEST_SAML_ADMIN_PASSWORD",
"EMAIL_FROM",
"EMAIL_FROM_NAME",
"EMAIL_SERVER_HOST",
"EMAIL_SERVER_PASSWORD",
"EMAIL_SERVER_PORT",
"EMAIL_SERVER_USER",
"EMAIL_SERVER",
"ENABLE_EXPANDED_CACHE",
"EXCHANGE_DEFAULT_EWS_URL",
"FORMBRICKS_FEEDBACK_SURVEY_ID",
"AVATARAPI_USERNAME",
"AVATARAPI_PASSWORD",
"GIPHY_API_KEY",
"GITHUB_API_REPO_TOKEN",
"GOOGLE_API_CREDENTIALS",
"GOOGLE_LOGIN_ENABLED",
"GOOGLE_WEBHOOK_TOKEN",
"HEROKU_APP_NAME",
"HUBSPOT_CLIENT_ID",
"HUBSPOT_CLIENT_SECRET",
"IFFY_API_KEY",
"INTEGRATION_TEST_MODE",
"IS_E2E",
"INTERCOM_SECRET",
"INTERCOM_SECRET",
"INSIGHTS_DATABASE_URL",
"IP_BANLIST",
"LARK_OPEN_APP_ID",
"LARK_OPEN_APP_SECRET",
"LARK_OPEN_VERIFICATION_TOKEN",
"MOCK_PAYMENT_APP_ENABLED",
"MS_GRAPH_CLIENT_ID",
"MS_GRAPH_CLIENT_SECRET",
"NEXT_PUBLIC_API_URL",
"NEXT_PUBLIC_APP_NAME",
"NEXT_PUBLIC_AUTH_URL",
"NEXT_PUBLIC_CALCOM_VERSION",
"NEXT_PUBLIC_COMPANY_NAME",
"NEXT_PUBLIC_CONSOLE_URL",
"NEXT_PUBLIC_LOGGER_LEVEL",
"NEXT_PUBLIC_DISABLE_SIGNUP",
"NEXT_PUBLIC_EMBED_LIB_URL",
"NEXT_PUBLIC_FORMBRICKS_HOST_URL",
"NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID",
"NEXT_PUBLIC_HOSTED_CAL_FEATURES",
"NEXT_PUBLIC_MINUTES_TO_BOOK",
"NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED",
"NEXT_PUBLIC_SENDER_ID",
"NEXT_PUBLIC_SENDGRID_SENDER_NAME",
"NEXT_PUBLIC_STRIPE_PRICING_TABLE_ID",
"NEXT_PUBLIC_STRIPE_PRICING_TABLE_PUBLISHABLE_KEY",
"NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS",
"NEXT_PUBLIC_SWAGGER_DOCS_URL",
"NEXT_PUBLIC_TEAM_IMPERSONATION",
"NEXT_PUBLIC_VERCEL_URL",
"NEXT_PUBLIC_CLOUDFLARE_SITEKEY",
"NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER",
"NEXT_PUBLIC_VERCEL_ENV",
"NEXT_PUBLIC_VERCEL_BRANCH_URL",
"NEXT_PUBLIC_GTM_ID",
"NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS",
"NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW",
"NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL",
"NEXT_PUBLIC_WEBSITE_TERMS_URL",
"NEXT_RUNTIME",
"NEXTAUTH_COOKIE_DOMAIN",
"NEXTAUTH_SECRET",
"NEXTAUTH_URL",
"NODE_ENV",
"ORGANIZATIONS_ENABLED",
"ORGANIZATIONS_AUTOLINK",
"PAYMENT_FEE_FIXED",
"PAYMENT_FEE_PERCENTAGE",
"PLAYWRIGHT_HEADLESS",
"PLAYWRIGHT_TEST_BASE_URL",
"PRISMA_FIELD_ENCRYPTION_KEY",
"PRISMA_GENERATE_DATAPROXY",
"PROJECT_ID_VERCEL",
"QUICK",
"RAILWAY_STATIC_URL",
"RENDER_EXTERNAL_URL",
"RESERVED_SUBDOMAINS",
"RETELL_AI_KEY",
"SALESFORCE_CONSUMER_KEY",
"SALESFORCE_CONSUMER_SECRET",
"SAML_ADMINS",
"SAML_CLIENT_SECRET_VERIFIER",
"SAML_DATABASE_URL",
"SEND_FEEDBACK_EMAIL",
"SENDGRID_API_KEY",
"SENDGRID_EMAIL",
"SENDGRID_SYNC_API_KEY",
"SKIP_DB_MIGRATIONS",
"SLACK_CLIENT_ID",
"SLACK_CLIENT_SECRET",
"SLACK_SIGNING_SECRET",
"STRIPE_CLIENT_ID",
"STRIPE_PRIVATE_KEY",
"STRIPE_PRODUCT_ID_ESSENTIALS",
"STRIPE_PRODUCT_ID_SCALE",
"STRIPE_PRODUCT_ID_STARTER",
"STRIPE_WEBHOOK_SECRET",
"STRIPE_WEBHOOK_SECRET_APPS",
"STRIPE_WEBHOOK_SECRET_BILLING",
"TANDEM_BASE_URL",
"TANDEM_CLIENT_ID",
"TANDEM_CLIENT_SECRET",
"TASKER_ENABLE_WEBHOOKS",
"TEAM_ID_VERCEL",
"TELEMETRY_DEBUG",
"TWILIO_MESSAGING_SID",
"TWILIO_OPT_OUT_ENABLED",
"TWILIO_PHONE_NUMBER",
"TWILIO_WHATSAPP_PHONE_NUMBER",
"TWILIO_SID",
"TWILIO_TOKEN",
"TWILIO_VERIFY_SID",
"UPSTASH_REDIS_REST_TOKEN",
"UPSTASH_REDIS_REST_URL",
"UNKEY_ROOT_KEY",
"USERNAME_BLACKLIST_URL",
"VERCEL_ENV",
"VERCEL_URL",
"VITAL_API_KEY",
"VITAL_DEVELOPMENT_MODE",
"VITAL_REGION",
"VITAL_WEBHOOK_SECRET",
"ZAPIER_INVITE_LINK",
"ZOHOCRM_CLIENT_ID",
"ZOHOCRM_CLIENT_SECRET",
"ZOOM_CLIENT_ID",
"ZOOM_CLIENT_SECRET",
"REVERT_API_KEY",
"REVERT_API_URL",
"REVERT_PUBLIC_TOKEN",
"RESEND_API_KEY",
"LOCAL_TESTING_DOMAIN_VERCEL",
"AUTH_BEARER_TOKEN_CLOUDFLARE",
"CLOUDFLARE_ZONE_ID",
"NEXT_PUBLIC_MINTLIFY_CHAT_API_KEY",
"NEXT_PUBLIC_CHAT_API_URL",
"NEXT_PUBLIC_DOCS_URL",
"CLOUDFLARE_VERCEL_CNAME",
"CLOUDFLARE_DNS",
"EMBED_PUBLIC_EMBED_FINGER_PRINT",
"EMBED_PUBLIC_EMBED_VERSION",
"EMBED_PUBLIC_WEBAPP_URL",
"EMBED_PUBLIC_VERCEL_URL",
"EMBED_PUBLIC_EMBED_LIB_URL",
"NEXT_PUBLIC_ENABLE_PROFILE_SWITCHER",
"NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS",
"NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS",
"NEXT_PUBLIC_QUERY_RESERVATION_STALE_TIME_SECONDS",
"NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM",
"NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT",
"NEXT_PUBLIC_HEAD_SCRIPTS",
"NEXT_PUBLIC_BODY_SCRIPTS",
"NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED",
"NEXT_PUBLIC_API_V2_ROOT_URL",
"NEXT_PUBLIC_VAPID_PUBLIC_KEY",
"VAPID_PRIVATE_KEY",
"CAL_VIDEO_BUCKET_NAME",
"CAL_VIDEO_BUCKET_REGION",
"CAL_VIDEO_ASSUME_ROLE_ARN",
"CAL_VIDEO_MEETING_LINK_FOR_TESTING",
"NEXT_PUBLIC_POSTHOG_KEY",
"NEXT_PUBLIC_POSTHOG_HOST",
"VAPID_PRIVATE_KEY",
"HUDDLE01_API_TOKEN",
"LINGO_DOT_DEV_API_KEY",
"DIRECTORY_IDS_TO_LOG",
"NEXT_PUBLIC_SINGLE_ORG_SLUG",
"GOOGLE_REFRESH_TOKEN",
"GOOGLE_CLIENT_ID",
"GOOGLE_CLIENT_SECRET",
"ZOOM_REFRESH_TOKEN",
"CALCOM_ADMIN_API_KEY",
"NEXT_PUBLIC_SINGLE_ORG_MODE_ENABLED",
"CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY"
]
}