0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-21 13:39:22 +01:00

chore: Swap to just /api/billing (#22545)

This commit is contained in:
Ben White 2024-05-30 13:25:02 +01:00 committed by GitHub
parent acd747aa8e
commit f930bf59cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 66 additions and 67 deletions

View File

@ -5974,15 +5974,15 @@
"api/test/test_authentication.py::TestEESAMLAuthenticationAPI::test_saml_jit_provisioning_and_assertion_with_different_attribute_names": 0.18937384700001303,
"api/test/test_billing.py::TestBillingAPI::test_billing_ignores_invalid_license": 0.23069630899999538,
"api/test/test_billing.py::TestBillingAPI::test_billing_stores_valid_license": 0.02972609799996917,
"api/test/test_billing.py::TestBillingAPI::test_billing_v2_calls_the_service_with_appropriate_token": 0.08096698800000013,
"api/test/test_billing.py::TestBillingAPI::test_billing_v2_fails_for_old_license_type": 0.02822808900009477,
"api/test/test_billing.py::TestBillingAPI::test_billing_v2_returns_if_billing_exists": 0.03943313500002432,
"api/test/test_billing.py::TestBillingAPI::test_billing_v2_returns_if_doesnt_exist": 0.038199266999981774,
"api/test/test_billing.py::TestBillingAPI::test_billing_calls_the_service_with_appropriate_token": 0.08096698800000013,
"api/test/test_billing.py::TestBillingAPI::test_billing_fails_for_old_license_type": 0.02822808900009477,
"api/test/test_billing.py::TestBillingAPI::test_billing_returns_if_billing_exists": 0.03943313500002432,
"api/test/test_billing.py::TestBillingAPI::test_billing_returns_if_doesnt_exist": 0.038199266999981774,
"api/test/test_billing.py::TestBillingAPI::test_license_is_updated_on_billing_load": 0.10390741700001627,
"api/test/test_billing.py::TestBillingAPI::test_organization_available_features_updated_if_different": 0.03626448700003948,
"api/test/test_billing.py::TestBillingAPI::test_organization_usage_count_with_demo_project": 1.0296154379999507,
"api/test/test_billing.py::TestBillingAPI::test_organization_usage_update": 0.054931941000006645,
"api/test/test_billing.py::TestUnlicensedBillingAPI::test_billing_v2_calls_the_service_without_token": 0.6085545820000107,
"api/test/test_billing.py::TestUnlicensedBillingAPI::test_billing_calls_the_service_without_token": 0.6085545820000107,
"api/test/test_capture.py::TestCaptureAPI::test_capture_event_with_uuid_in_payload": 0.22503733999997166,
"api/test/test_capture.py::TestCaptureAPI::test_kafka_connection_error": 0.018643948000033106,
"api/test/test_capture.py::TestCaptureAPI::test_partition_key_override": 0.01963480899996739,

View File

@ -2,14 +2,14 @@ const UNSUBSCRIBE_SURVEY_ID = '018b6e13-590c-0000-decb-c727a2b3f462'
describe('Billing', () => {
beforeEach(() => {
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing.json' })
cy.visit('/organization/billing')
})
it('Show and submit unsubscribe survey', () => {
cy.intercept('/api/billing-v2/deactivate?products=product_analytics', {
fixture: 'api/billing-v2/billing-v2-unsubscribed-product-analytics.json',
cy.intercept('/api/billing/deactivate?products=product_analytics', {
fixture: 'api/billing/billing-unsubscribed-product-analytics.json',
}).as('unsubscribeProductAnalytics')
cy.get('[data-attr=more-button]').first().click()

View File

@ -5,7 +5,7 @@ import * as fflate from 'fflate'
describe('Billing Upgrade CTA', () => {
beforeEach(() => {
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2-unsubscribed.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing-unsubscribed.json' })
})
it('Check that events are being sent on each page visit', () => {
@ -20,7 +20,7 @@ describe('Billing Upgrade CTA', () => {
})
// Mock billing response with subscription
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing.json' })
cy.reload()
cy.get('[data-attr=session_replay-upgrade-cta] .LemonButton__content').should('have.text', 'Subscribe')
@ -32,7 +32,7 @@ describe('Billing Upgrade CTA', () => {
expect(matchingEvents.length).to.equal(3)
})
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2-unsubscribed.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing-unsubscribed.json' })
// Navigate to the onboarding billing step
cy.visit('/products')
cy.get('[data-attr=product_analytics-onboarding-card]').click()

View File

@ -2,7 +2,7 @@ import { decideResponse } from '../fixtures/api/decide'
describe('Onboarding', () => {
beforeEach(() => {
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2-unsubscribed.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing-unsubscribed.json' })
cy.intercept('**/decide/*', (req) =>
req.reply(

View File

@ -16,10 +16,10 @@ Cypress.Commands.add('clickNavMenu', (name) => {
Cypress.Commands.add('useSubscriptionStatus', (condition) => {
if (condition === 'unsubscribed') {
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2-unsubscribed.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing-unsubscribed.json' })
cy.reload()
} else if (condition === 'subscribed') {
cy.intercept('/api/billing-v2/', { fixture: 'api/billing-v2/billing-v2-subscribed-all.json' })
cy.intercept('/api/billing/', { fixture: 'api/billing/billing-subscribed-all.json' })
cy.reload()
}
})

View File

@ -244,7 +244,7 @@ def create_billing_products_response(**kwargs) -> dict[str, list[CustomerProduct
class TestUnlicensedBillingAPI(APIBaseTest):
@patch("ee.api.billing.requests.get")
@freeze_time("2022-01-01")
def test_billing_v2_calls_the_service_without_token(self, mock_request):
def test_billing_calls_the_service_without_token(self, mock_request):
def mock_implementation(url: str, headers: Any = None, params: Any = None) -> MagicMock:
mock = MagicMock()
mock.status_code = 404
@ -264,7 +264,7 @@ class TestUnlicensedBillingAPI(APIBaseTest):
mock_request.side_effect = mock_implementation
TEST_clear_instance_license_cache()
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 200
assert res.json() == {
"available_product_features": [],
@ -273,18 +273,18 @@ class TestUnlicensedBillingAPI(APIBaseTest):
class TestBillingAPI(APILicensedTest):
def test_billing_v2_fails_for_old_license_type(self):
def test_billing_fails_for_old_license_type(self):
self.license.key = "test_key"
self.license.save()
TEST_clear_instance_license_cache()
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 404
assert res.json()["detail"] == "Billing V2 is not supported for this license type"
@patch("ee.api.billing.requests.get")
@freeze_time("2022-01-01")
def test_billing_v2_calls_the_service_with_appropriate_token(self, mock_request):
def test_billing_calls_the_service_with_appropriate_token(self, mock_request):
def mock_implementation(url: str, headers: Any = None, params: Any = None) -> MagicMock:
mock = MagicMock()
mock.status_code = 404
@ -302,7 +302,7 @@ class TestBillingAPI(APILicensedTest):
TEST_clear_instance_license_cache()
self.client.get("/api/billing-v2")
self.client.get("/api/billing")
assert mock_request.call_args_list[0].args[0].endswith("/api/billing")
token = mock_request.call_args_list[0].kwargs["headers"]["Authorization"].split(" ")[1]
@ -325,7 +325,7 @@ class TestBillingAPI(APILicensedTest):
}
@patch("ee.api.billing.requests.get")
def test_billing_v2_returns_if_billing_exists(self, mock_request):
def test_billing_returns_if_billing_exists(self, mock_request):
def mock_implementation(url: str, headers: Any = None, params: Any = None) -> MagicMock:
mock = MagicMock()
mock.status_code = 404
@ -342,7 +342,7 @@ class TestBillingAPI(APILicensedTest):
mock_request.side_effect = mock_implementation
TEST_clear_instance_license_cache()
response = self.client.get("/api/billing-v2")
response = self.client.get("/api/billing")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
@ -456,7 +456,7 @@ class TestBillingAPI(APILicensedTest):
}
@patch("ee.api.billing.requests.get")
def test_billing_v2_returns_if_doesnt_exist(self, mock_request):
def test_billing_returns_if_doesnt_exist(self, mock_request):
def mock_implementation(url: str, headers: Any = None, params: Any = None) -> MagicMock:
mock = MagicMock()
mock.status_code = 404
@ -475,7 +475,7 @@ class TestBillingAPI(APILicensedTest):
mock_request.side_effect = mock_implementation
response = self.client.get("/api/billing-v2")
response = self.client.get("/api/billing")
assert response.status_code == status.HTTP_200_OK
assert response.json() == {
"customer_id": "cus_123",
@ -592,7 +592,7 @@ class TestBillingAPI(APILicensedTest):
}
}
response = self.client.patch(
"/api/billing-v2/license",
"/api/billing/license",
{
"license": "test::test",
},
@ -612,7 +612,7 @@ class TestBillingAPI(APILicensedTest):
mock_request.return_value.status_code = 403
mock_request.return_value.json.return_value = {}
response = self.client.patch(
"/api/billing-v2/license",
"/api/billing/license",
{
"license": "test::test",
},
@ -638,7 +638,7 @@ class TestBillingAPI(APILicensedTest):
}
assert self.license.plan == "enterprise"
self.client.get("/api/billing-v2")
self.client.get("/api/billing")
self.license.refresh_from_db()
self.license.valid_until = datetime(2022, 1, 2, 0, 0, 0, tzinfo=ZoneInfo("UTC"))
@ -656,7 +656,7 @@ class TestBillingAPI(APILicensedTest):
"customer": create_billing_customer(),
}
self.client.get("/api/billing-v2")
self.client.get("/api/billing")
license = get_cached_instance_license()
assert license.plan == "enterprise"
# Should be extended by 30 days
@ -690,7 +690,7 @@ class TestBillingAPI(APILicensedTest):
self.organization.save()
assert self.organization.available_product_features == []
self.client.get("/api/billing-v2")
self.client.get("/api/billing")
self.organization.refresh_from_db()
assert self.organization.available_product_features == [
{
@ -729,7 +729,7 @@ class TestBillingAPI(APILicensedTest):
mock_request.side_effect = mock_implementation
assert not self.organization.usage
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 200
self.organization.refresh_from_db()
assert self.organization.usage == {
@ -754,7 +754,7 @@ class TestBillingAPI(APILicensedTest):
self.organization.usage = {"events": {"limit": None, "usage": 1000, "todays_usage": 1100000}}
self.organization.save()
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 200
res_json = res.json()
# Should update product usage to reflect today's usage
@ -791,7 +791,7 @@ class TestBillingAPI(APILicensedTest):
mock_request.side_effect = mock_implementation_missing_customer
# Test unsubscribed config
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
self.organization.refresh_from_db()
assert self.organization.usage == {
"events": {
@ -859,7 +859,7 @@ class TestBillingAPI(APILicensedTest):
flush_persons_and_events()
assert not self.organization.usage
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 200
self.organization.refresh_from_db()
@ -894,7 +894,7 @@ class TestBillingAPI(APILicensedTest):
self.organization.customer_trust_scores = {"recordings": 0, "events": 0, "rows_synced": 0}
self.organization.save()
res = self.client.get("/api/billing-v2")
res = self.client.get("/api/billing")
assert res.status_code == 200
self.organization.refresh_from_db()

View File

@ -17,7 +17,7 @@ def send_license_usage():
if not license:
return
# New type of license key for billing-v2
# New type of license key for billing
if license.is_v2_license:
return

View File

@ -33,7 +33,8 @@ def extend_api_router(
project_dashboards_router: NestedRegistryItem,
project_feature_flags_router: NestedRegistryItem,
) -> None:
root_router.register(r"billing-v2", billing.BillingViewset, "billing")
root_router.register(r"billing", billing.BillingViewset, "billing")
root_router.register(r"billing-v2", billing.BillingViewset, "billing") # Legacy transition route
root_router.register(r"license", license.LicenseViewSet)
root_router.register(r"time_to_see_data", time_to_see_data.TimeToSeeDataViewSet, "query_metrics")
root_router.register(r"integrations", integration.PublicIntegrationViewSet)

View File

@ -15,7 +15,7 @@ import { ResponseComposition, RestContext, RestRequest } from 'msw'
import { SharingConfigurationType } from '~/types'
import { getAvailableProductFeatures } from './features'
import { billingJson } from './fixtures/_billing_v2'
import { billingJson } from './fixtures/_billing'
import { Mocks, MockSignature, mocksToHandlers } from './utils'
export const EMPTY_PAGINATED_RESPONSE = { count: 0, results: [] as any[], next: null, previous: null }
@ -120,7 +120,7 @@ export const defaultMocks: Mocks = {
'https://us.i.posthog.com/api/early_access_features': {
earlyAccessFeatures: [],
},
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
},

View File

@ -103,7 +103,7 @@
"8929-insight-editor-panels": false
},
"$console_log_recording_enabled_server_side": true,
"pathname": "/api/billing-v2/",
"pathname": "/api/billing/",
"method": "GET",
"duration": 266,
"status": 404,

View File

@ -1,9 +1,9 @@
import { Meta } from '@storybook/react'
import { mswDecorator, useStorybookMocks } from '~/mocks/browser'
import { billingJson } from '~/mocks/fixtures/_billing_v2'
import billingJsonWith100PercentDiscount from '~/mocks/fixtures/_billing_v2_with_100_percent_discount.json'
import billingJsonWithDiscount from '~/mocks/fixtures/_billing_v2_with_discount.json'
import { billingJson } from '~/mocks/fixtures/_billing'
import billingJsonWith100PercentDiscount from '~/mocks/fixtures/_billing_with_100_percent_discount.json'
import billingJsonWithDiscount from '~/mocks/fixtures/_billing_with_discount.json'
import preflightJson from '~/mocks/fixtures/_preflight.json'
import organizationCurrent from '~/mocks/fixtures/api/organizations/@current/@current.json'
import batchExports from '~/mocks/fixtures/api/organizations/@current/batchExports.json'
@ -35,7 +35,7 @@ export default meta
export const _BillingV2 = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
},
@ -47,7 +47,7 @@ export const _BillingV2 = (): JSX.Element => {
export const BillingV2WithDiscount = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJsonWithDiscount,
},
},
@ -59,7 +59,7 @@ export const BillingV2WithDiscount = (): JSX.Element => {
export const BillingV2WithLimitAnd100PercentDiscount = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJsonWith100PercentDiscount,
},
},
@ -71,7 +71,7 @@ export const BillingV2WithLimitAnd100PercentDiscount = (): JSX.Element => {
export const BillingUnsubscribeModal = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
},
@ -82,7 +82,7 @@ export const BillingUnsubscribeModal = (): JSX.Element => {
export const BillingUnsubscribeModal_DataPipelines = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
'/api/organizations/@current/plugins/exports_unsubscribe_configs/': exportsUnsubscribeConfigs,

View File

@ -188,7 +188,7 @@ export const PlanComparison = ({
{!plan.current_plan && !plan.free_allocation && includeAddons && product.addons?.length > 0 && (
<p className="text-center ml-0 mt-2 mb-0">
<Link
to={`/api/billing-v2/activation?products=${product.type}:${plan.plan_key}&redirect_path=${redirectPath}`}
to={`/api/billing/activation?products=${product.type}:${plan.plan_key}&redirect_path=${redirectPath}`}
className="text-muted text-xs"
disableClientSideRouting
>

View File

@ -1,8 +1,8 @@
import { dayjs } from 'lib/dayjs'
import tk from 'timekeeper'
import { billingJson } from '~/mocks/fixtures/_billing_v2'
import billingJsonWithFlatFee from '~/mocks/fixtures/_billing_v2_with_flat_fee.json'
import { billingJson } from '~/mocks/fixtures/_billing'
import billingJsonWithFlatFee from '~/mocks/fixtures/_billing_with_flat_fee.json'
import {
convertAmountToUsage,

View File

@ -164,7 +164,7 @@ export const getUpgradeProductLink = (
redirectPath?: string,
includeAddons: boolean = true
): string => {
let url = '/api/billing-v2/activation?products='
let url = '/api/billing/activation?products='
url += `${product.type}:${upgradeToPlanKey},`
if (includeAddons && product.addons?.length) {
for (const addon of product.addons) {

View File

@ -184,13 +184,13 @@ export const billingLogic = kea<billingLogicType>([
null as BillingV2Type | null,
{
loadBilling: async () => {
const response = await api.get('api/billing-v2')
const response = await api.get('api/billing')
return parseBillingResponse(response)
},
updateBillingLimits: async (limits: { [key: string]: string | null }) => {
const response = await api.update('api/billing-v2', { custom_limits_usd: limits })
const response = await api.update('api/billing', { custom_limits_usd: limits })
lemonToast.success('Billing limits updated')
return parseBillingResponse(response)
@ -199,7 +199,7 @@ export const billingLogic = kea<billingLogicType>([
deactivateProduct: async (key: string) => {
actions.resetUnsubscribeError()
try {
const response = await api.getResponse('api/billing-v2/deactivate?products=' + key)
const response = await api.getResponse('api/billing/deactivate?products=' + key)
const jsonRes = await getJSONOrNull(response)
lemonToast.success('Product unsubscribed')
actions.reportProductUnsubscribed(key)
@ -250,7 +250,7 @@ export const billingLogic = kea<billingLogicType>([
getInvoices: async () => {
// First check to see if there are open invoices
try {
const res = await api.getResponse('api/billing-v2/get_invoices?status=open')
const res = await api.getResponse('api/billing/get_invoices?status=open')
const jsonRes = await getJSONOrNull(res)
const numOpenInvoices = jsonRes['count']
if (numOpenInvoices > 0) {
@ -283,7 +283,7 @@ export const billingLogic = kea<billingLogicType>([
[] as BillingProductV2Type[],
{
loadProducts: async () => {
const response = await api.get('api/billing-v2/available_products')
const response = await api.get('api/billing/available_products')
return response
},
},
@ -372,7 +372,7 @@ export const billingLogic = kea<billingLogicType>([
submit: async ({ license }, breakpoint) => {
await breakpoint(500)
try {
await api.update('api/billing-v2/license', {
await api.update('api/billing/license', {
license,
})

View File

@ -342,7 +342,7 @@ export const billingProductLogic = kea<billingProductLogicType>([
}
},
handleProductUpgrade: ({ plan, product, redirectPath }) => {
window.location.href = `/api/billing-v2/activation?products=${product.type}:${plan?.plan_key}${
window.location.href = `/api/billing/activation?products=${product.type}:${plan?.plan_key}${
redirectPath && `&redirect_path=${redirectPath}`
}`
},

View File

@ -15,10 +15,10 @@ describe('billingLogic', () => {
initKeaTests()
useMocks({
get: {
'api/billing-v2/': {
'api/billing/': {
results: billingResponseWithBillingLimits,
},
'api/billing-v2/get_invoices': {
'api/billing/get_invoices': {
results: [{}],
},
},

View File

@ -6,8 +6,8 @@ import { App } from 'scenes/App'
import { urls } from 'scenes/urls'
import { mswDecorator, useStorybookMocks } from '~/mocks/browser'
import { billingJson } from '~/mocks/fixtures/_billing'
import billingUnsubscribedJson from '~/mocks/fixtures/_billing_unsubscribed.json'
import { billingJson } from '~/mocks/fixtures/_billing_v2'
import preflightJson from '~/mocks/fixtures/_preflight.json'
import { OnboardingProduct, ProductKey } from '~/types'
@ -36,7 +36,7 @@ export default meta
export const _OnboardingSDKs = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
},
@ -55,7 +55,7 @@ export const _OnboardingSDKs = (): JSX.Element => {
export const _OnboardingBilling = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingUnsubscribedJson,
},
},

View File

@ -5,7 +5,7 @@ import { App } from 'scenes/App'
import { urls } from 'scenes/urls'
import { mswDecorator, useStorybookMocks } from '~/mocks/browser'
import { billingJson } from '~/mocks/fixtures/_billing_v2'
import { billingJson } from '~/mocks/fixtures/_billing'
import preflightJson from '~/mocks/fixtures/_preflight.json'
const meta: Meta = {
@ -31,7 +31,7 @@ export default meta
export const _Products = (): JSX.Element => {
useStorybookMocks({
get: {
'/api/billing-v2/': {
'/api/billing/': {
...billingJson,
},
},

View File

@ -104,8 +104,6 @@ HOOK_EVENTS: dict[str, str] = {}
# Support creating multiple organizations in a single instance. Requires a premium license.
MULTI_ORG_ENABLED: bool = get_from_env("MULTI_ORG_ENABLED", False, type_cast=str_to_bool)
BILLING_V2_ENABLED: bool = get_from_env("BILLING_V2_ENABLED", False, type_cast=str_to_bool)
AUTO_LOGIN: bool = get_from_env("AUTO_LOGIN", False, type_cast=str_to_bool)
CONTAINER_HOSTNAME: str = os.getenv("HOSTNAME", "unknown")