Skip to content

Commit

Permalink
Merge branch 'master' into feat/even-more-hogql-needed
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra authored Jul 1, 2024
2 parents 1c553bd + 46d50b1 commit c977058
Show file tree
Hide file tree
Showing 97 changed files with 1,848 additions and 1,186 deletions.
90 changes: 0 additions & 90 deletions ee/api/test/test_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,93 +837,3 @@ def mock_implementation(url: str, headers: Any = None, params: Any = None) -> Ma
self.organization.refresh_from_db()

assert self.organization.customer_trust_scores == {"recordings": 0, "events": 15, "rows_synced": 0}


class TestActivateBillingAPI(APILicensedTest):
def test_activate_success(self):
url = "/api/billing-v2/activate"
data = {"products": "product_1:plan_1,product_2:plan_2", "redirect_path": "custom/path"}

response = self.client.get(url, data=data)
self.assertEqual(response.status_code, status.HTTP_302_FOUND)

self.assertIn("/activate", response.url)
self.assertIn("products=product_1:plan_1,product_2:plan_2", response.url)
url_pattern = r"redirect_uri=http://[^/]+/custom/path"
self.assertRegex(response.url, url_pattern)

def test_deprecated_activation_success(self):
url = "/api/billing-v2/activate"
data = {"products": "product_1:plan_1,product_2:plan_2", "redirect_path": "custom/path"}

response = self.client.get(url, data=data)
self.assertEqual(response.status_code, status.HTTP_302_FOUND)

self.assertIn("/activate", response.url)
self.assertIn("products=product_1:plan_1,product_2:plan_2", response.url)
url_pattern = r"redirect_uri=http://[^/]+/custom/path"
self.assertRegex(response.url, url_pattern)

def test_activate_with_default_redirect_path(self):
url = "/api/billing-v2/activate"
data = {
"products": "product_1:plan_1,product_2:plan_2",
}

response = self.client.get(url, data)

self.assertEqual(response.status_code, status.HTTP_302_FOUND)
self.assertIn("products=product_1:plan_1,product_2:plan_2", response.url)
url_pattern = r"redirect_uri=http://[^/]+/organization/billing"
self.assertRegex(response.url, url_pattern)

def test_activate_failure(self):
url = "/api/billing-v2/activate"
data = {"none": "nothing"}

response = self.client.get(url, data)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_activate_with_plan_error(self):
url = "/api/billing-v2/activate"
data = {"plan": "plan"}

response = self.client.get(url, data)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.json(),
{
"attr": "plan",
"code": "invalid_input",
"detail": "The 'plan' parameter is no longer supported. Please use the 'products' parameter instead.",
"type": "validation_error",
},
)

@patch("ee.billing.billing_manager.BillingManager.deactivate_products")
@patch("ee.billing.billing_manager.BillingManager.get_billing")
def test_deactivate_success(self, mock_get_billing, mock_deactivate_products):
mock_deactivate_products.return_value = MagicMock()
mock_get_billing.return_value = {
"available_features": [],
"products": [],
}

url = "/api/billing-v2/deactivate"
data = {"products": "product_1"}

response = self.client.get(url, data)

self.assertEqual(response.status_code, status.HTTP_200_OK)
mock_deactivate_products.assert_called_once_with(self.organization, "product_1")
mock_get_billing.assert_called_once_with(self.organization, None)

def test_deactivate_failure(self):
url = "/api/billing-v2/deactivate"
data = {"none": "nothing"}

response = self.client.get(url, data)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
Original file line number Diff line number Diff line change
Expand Up @@ -227,97 +227,26 @@
# ---
# name: ClickhouseTestFunnelExperimentResults.test_experiment_flow_with_event_results_and_events_out_of_time_range_timezones.1
'''
/* user_id:0 request:_snapshot_ */
SELECT array(replaceRegexpAll(JSONExtractRaw(properties, '$feature/a-b-test'), '^"|"$', '')) AS value,
count(*) as count
FROM events e
WHERE team_id = 2
AND event IN ['$pageleave', '$pageview']
AND toTimeZone(timestamp, 'Europe/Amsterdam') >= toDateTime('2020-01-01 14:20:21', 'Europe/Amsterdam')
AND toTimeZone(timestamp, 'Europe/Amsterdam') <= toDateTime('2020-01-06 10:00:00', 'Europe/Amsterdam')
GROUP BY value
ORDER BY count DESC, value DESC
LIMIT 26
OFFSET 0
/* celery:posthog.tasks.tasks.sync_insight_caching_state */
SELECT team_id,
date_diff('second', max(timestamp), now()) AS age
FROM events
WHERE timestamp > date_sub(DAY, 3, now())
AND timestamp < now()
GROUP BY team_id
ORDER BY age;
'''
# ---
# name: ClickhouseTestFunnelExperimentResults.test_experiment_flow_with_event_results_and_events_out_of_time_range_timezones.2
'''
/* user_id:0 request:_snapshot_ */
SELECT countIf(steps = 1) step_1,
countIf(steps = 2) step_2,
avg(step_1_average_conversion_time_inner) step_1_average_conversion_time,
median(step_1_median_conversion_time_inner) step_1_median_conversion_time,
prop
FROM
(SELECT aggregation_target,
steps,
avg(step_1_conversion_time) step_1_average_conversion_time_inner,
median(step_1_conversion_time) step_1_median_conversion_time_inner ,
prop
FROM
(SELECT aggregation_target,
steps,
max(steps) over (PARTITION BY aggregation_target,
prop) as max_steps,
step_1_conversion_time ,
prop
FROM
(SELECT *,
if(latest_0 <= latest_1
AND latest_1 <= latest_0 + INTERVAL 14 DAY, 2, 1) AS steps ,
if(isNotNull(latest_1)
AND latest_1 <= latest_0 + INTERVAL 14 DAY, dateDiff('second', toDateTime(latest_0), toDateTime(latest_1)), NULL) step_1_conversion_time,
prop
FROM
(SELECT aggregation_target, timestamp, step_0,
latest_0,
step_1,
min(latest_1) over (PARTITION by aggregation_target,
prop
ORDER BY timestamp DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) latest_1 ,
if(has([['test'], ['control']], prop), prop, ['Other']) as prop
FROM
(SELECT *,
if(notEmpty(arrayFilter(x -> notEmpty(x), prop_vals)), prop_vals, ['']) as prop
FROM
(SELECT e.timestamp as timestamp,
pdi.person_id as aggregation_target,
pdi.person_id as person_id,
if(event = '$pageview', 1, 0) as step_0,
if(step_0 = 1, timestamp, null) as latest_0,
if(event = '$pageleave', 1, 0) as step_1,
if(step_1 = 1, timestamp, null) as latest_1,
array(replaceRegexpAll(JSONExtractRaw(properties, '$feature/a-b-test'), '^"|"$', '')) AS prop_basic,
prop_basic as prop,
argMinIf(prop, timestamp, notEmpty(arrayFilter(x -> notEmpty(x), prop))) over (PARTITION by aggregation_target) as prop_vals
FROM events e
INNER JOIN
(SELECT distinct_id,
argMax(person_id, version) as person_id
FROM person_distinct_id2
WHERE team_id = 2
AND distinct_id IN
(SELECT distinct_id
FROM events
WHERE team_id = 2
AND event IN ['$pageleave', '$pageview']
AND toTimeZone(timestamp, 'Europe/Amsterdam') >= toDateTime('2020-01-01 14:20:21', 'Europe/Amsterdam')
AND toTimeZone(timestamp, 'Europe/Amsterdam') <= toDateTime('2020-01-06 10:00:00', 'Europe/Amsterdam') )
GROUP BY distinct_id
HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id
WHERE team_id = 2
AND event IN ['$pageleave', '$pageview']
AND toTimeZone(timestamp, 'Europe/Amsterdam') >= toDateTime('2020-01-01 14:20:21', 'Europe/Amsterdam')
AND toTimeZone(timestamp, 'Europe/Amsterdam') <= toDateTime('2020-01-06 10:00:00', 'Europe/Amsterdam')
AND (step_0 = 1
OR step_1 = 1) )))
WHERE step_0 = 1 ))
GROUP BY aggregation_target,
steps,
prop
HAVING steps = max_steps)
GROUP BY prop
/* celery:posthog.tasks.tasks.sync_insight_caching_state */
SELECT team_id,
date_diff('second', max(timestamp), now()) AS age
FROM events
WHERE timestamp > date_sub(DAY, 3, now())
AND timestamp < now()
GROUP BY team_id
ORDER BY age;
'''
# ---
# name: ClickhouseTestFunnelExperimentResults.test_experiment_flow_with_event_results_and_events_out_of_time_range_timezones.3
Expand Down
1 change: 0 additions & 1 deletion ee/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def extend_api_router(
project_feature_flags_router: NestedRegistryItem,
) -> None:
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)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { actions, kea, listeners, path, reducers } from 'kea'

import { BillingV2PlanType } from '~/types'
import { BillingPlanType } from '~/types'

import type { confirmUpgradeModalLogicType } from './confirmUpgradeModalLogicType'

export const confirmUpgradeModalLogic = kea<confirmUpgradeModalLogicType>([
path(['lib', 'components', 'ConfirmUpgradeModal', 'confirmUpgradeModalLogic']),
actions({
showConfirmUpgradeModal: (
upgradePlan: BillingV2PlanType,
upgradePlan: BillingPlanType,
confirmCallback: () => void,
cancelCallback: () => void
) => ({
Expand All @@ -22,7 +22,7 @@ export const confirmUpgradeModalLogic = kea<confirmUpgradeModalLogicType>([
}),
reducers({
upgradePlan: [
null as BillingV2PlanType | null,
null as BillingPlanType | null,
{
showConfirmUpgradeModal: (_, { upgradePlan }) => upgradePlan,
hideConfirmUpgradeModal: () => null,
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/lib/components/PayGateMini/PayGateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { FEATURE_FLAGS } from 'lib/constants'
import { featureFlagLogic, FeatureFlagsSet } from 'lib/logic/featureFlagLogic'
import { urls } from 'scenes/urls'

import { BillingProductV2AddonType, BillingProductV2Type, BillingV2FeatureType, BillingV2Type } from '~/types'
import { BillingFeatureType, BillingProductV2AddonType, BillingProductV2Type, BillingType } from '~/types'

interface PayGateButtonProps {
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null
productWithFeature: BillingProductV2AddonType | BillingProductV2Type
featureInfo: BillingV2FeatureType
featureInfo: BillingFeatureType
onCtaClick: () => void
billing: BillingV2Type | null
billing: BillingType | null
isAddonProduct?: boolean
scrollToProduct: boolean
}
Expand Down Expand Up @@ -50,9 +50,9 @@ export const PayGateButton = ({
const getCtaLink = (
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null,
productWithFeature: BillingProductV2AddonType | BillingProductV2Type,
featureInfo: BillingV2FeatureType,
featureInfo: BillingFeatureType,
featureFlags: FeatureFlagsSet,
subscriptionLevel?: BillingV2Type['subscription_level'],
subscriptionLevel?: BillingType['subscription_level'],
isAddonProduct?: boolean,
scrollToProduct: boolean = true
): string | undefined => {
Expand All @@ -77,7 +77,7 @@ const getCtaLink = (

const getCtaLabel = (
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null,
billing: BillingV2Type | null,
billing: BillingType | null,
featureFlags: FeatureFlagsSet
): string => {
if (
Expand Down
22 changes: 11 additions & 11 deletions frontend/src/lib/components/PayGateMini/PayGateMini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import { getProductIcon } from 'scenes/products/Products'

import {
AvailableFeature,
BillingFeatureType,
BillingProductV2AddonType,
BillingProductV2Type,
BillingV2FeatureType,
BillingV2Type,
BillingType,
} from '~/types'

import { upgradeModalLogic } from '../UpgradeModal/upgradeModalLogic'
Expand Down Expand Up @@ -139,14 +139,14 @@ export function PayGateMini({
interface PayGateContentProps {
className?: string
background: boolean
featureInfo: BillingV2FeatureType
featureAvailableOnOrg?: BillingV2FeatureType | null
featureInfo: BillingFeatureType
featureAvailableOnOrg?: BillingFeatureType | null
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null
productWithFeature: BillingProductV2AddonType | BillingProductV2Type
isGrandfathered?: boolean
isAddonProduct?: boolean
billing: BillingV2Type | null
featureInfoOnNextPlan?: BillingV2FeatureType
billing: BillingType | null
featureInfoOnNextPlan?: BillingFeatureType
children: React.ReactNode
handleCtaClick: () => void
}
Expand Down Expand Up @@ -197,12 +197,12 @@ function PayGateContent({
}

const renderUsageLimitMessage = (
featureAvailableOnOrg: BillingV2FeatureType | null | undefined,
featureInfoOnNextPlan: BillingV2FeatureType | undefined,
featureAvailableOnOrg: BillingFeatureType | null | undefined,
featureInfoOnNextPlan: BillingFeatureType | undefined,
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null,
featureInfo: BillingV2FeatureType,
featureInfo: BillingFeatureType,
productWithFeature: BillingProductV2AddonType | BillingProductV2Type,
billing: BillingV2Type | null,
billing: BillingType | null,
featureFlags: FeatureFlagsSet,
isAddonProduct?: boolean,
handleCtaClick?: () => void
Expand Down Expand Up @@ -263,7 +263,7 @@ const renderUsageLimitMessage = (
const renderGateVariantMessage = (
gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null,
productWithFeature: BillingProductV2AddonType | BillingProductV2Type,
billing: BillingV2Type | null,
billing: BillingType | null,
featureFlags: FeatureFlagsSet,
isAddonProduct?: boolean
): JSX.Element => {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ export const FEATURE_FLAGS = {
INSIGHT_LOADING_BAR: 'insight-loading-bar', // owner: @aspicer
PROXY_AS_A_SERVICE: 'proxy-as-a-service', // owner: #team-infrastructure
LIVE_EVENTS: 'live-events', // owner: @zach or @jams
SESSION_REPLAY_NETWORK_VIEW: 'session-replay-network-view', // owner: #team-replay
SETTINGS_PERSONS_JOIN_MODE: 'settings-persons-join-mode', // owner: @robbie-c
SETTINGS_PERSONS_ON_EVENTS_HIDDEN: 'settings-persons-on-events-hidden', // owner: @Twixes
HOG: 'hog', // owner: @mariusandra
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/utils/eventUsageLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ function sanitizeQuery(query: Node | null): Record<string, string | number | boo
payload.event_entity_count = getSeries(querySource)?.filter((e) => isEventsNode(e)).length
payload.action_entity_count = getSeries(querySource)?.filter((e) => isActionsNode(e)).length
payload.data_warehouse_entity_count = getSeries(querySource)?.filter((e) => isDataWarehouseNode(e)).length
payload.has_data_warehouse_series = !!getSeries(querySource)?.find((e) => isDataWarehouseNode(e))

// properties
payload.has_properties = !!properties
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/mocks/features.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { AvailableFeature, BillingV2FeatureType } from '~/types'
import { AvailableFeature, BillingFeatureType } from '~/types'

let features: AvailableFeature[] = []
export const useAvailableFeatures = (f: AvailableFeature[]): void => {
features = f
}
export const getAvailableProductFeatures = (): BillingV2FeatureType[] => {
export const getAvailableProductFeatures = (): BillingFeatureType[] => {
return features.map((feature) => {
return {
key: feature,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/mocks/fixtures/_billing.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { dayjs } from 'lib/dayjs'

import { BillingV2Type } from '~/types'
import { BillingType } from '~/types'

export const billingJson: BillingV2Type = {
export const billingJson: BillingType = {
customer_id: 'cus_Pg7PIL8MsKi6bx',
deactivated: false,
has_active_subscription: true,
Expand Down
Loading

0 comments on commit c977058

Please sign in to comment.