sql
This commit is contained in:
@@ -1,37 +1,59 @@
|
||||
Manual billing SQL for QR Master
|
||||
================================
|
||||
QR Master automatic billing alarm SQL
|
||||
=====================================
|
||||
|
||||
Use these statements for manual plan changes in the database.
|
||||
Replace USER_EMAIL_HERE before running.
|
||||
Run this SQL once in the database.
|
||||
|
||||
Do not use a naked UPDATE like:
|
||||
UPDATE "User" SET "plan" = 'PRO' WHERE email = '...';
|
||||
After it is installed, every database update of "User"."plan" automatically
|
||||
creates a "UserLifecycleLog" entry.
|
||||
|
||||
That changes the plan but creates no billing log. Always use the matching full
|
||||
transaction below so UserLifecycleLog gets the alert entry.
|
||||
That means:
|
||||
- FREE -> PRO or BUSINESS creates reason = subscription_created
|
||||
- PRO/BUSINESS -> FREE creates reason = subscription_deleted
|
||||
- PRO -> BUSINESS or BUSINESS -> PRO creates reason = subscription_updated
|
||||
|
||||
Upgrade user to PRO
|
||||
===================
|
||||
No customer email needs to be typed into this file.
|
||||
No manual log insert is needed after this is installed.
|
||||
|
||||
BEGIN;
|
||||
|
||||
WITH old_user AS (
|
||||
SELECT *
|
||||
FROM "User"
|
||||
WHERE email = 'USER_EMAIL_HERE'
|
||||
FOR UPDATE
|
||||
),
|
||||
updated_user AS (
|
||||
UPDATE "User"
|
||||
SET
|
||||
"plan" = 'PRO',
|
||||
"lifecycleStage" = 'paid',
|
||||
"lastScoredAt" = NOW(),
|
||||
"lastQualifiedAt" = NOW(),
|
||||
"updatedAt" = NOW()
|
||||
WHERE "id" = (SELECT "id" FROM old_user)
|
||||
RETURNING *
|
||||
)
|
||||
CREATE OR REPLACE FUNCTION qrmaster_log_plan_change()
|
||||
RETURNS trigger AS $$
|
||||
DECLARE
|
||||
next_stage TEXT;
|
||||
log_reason TEXT;
|
||||
BEGIN
|
||||
IF NEW."plan" IS NOT DISTINCT FROM OLD."plan" THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
IF NEW."plan"::TEXT IN ('PRO', 'BUSINESS') THEN
|
||||
next_stage := 'paid';
|
||||
ELSIF COALESCE(NEW."leadScore", 0) >= 70 THEN
|
||||
next_stage := 'upgrade_candidate';
|
||||
ELSIF COALESCE(NEW."leadScore", 0) >= 55 THEN
|
||||
next_stage := 'hot';
|
||||
ELSIF COALESCE(NEW."leadScore", 0) >= 30 THEN
|
||||
next_stage := 'warm';
|
||||
ELSIF NEW."activationAt" IS NOT NULL THEN
|
||||
next_stage := 'activated';
|
||||
ELSE
|
||||
next_stage := 'cold';
|
||||
END IF;
|
||||
|
||||
IF OLD."plan"::TEXT = 'FREE' AND NEW."plan"::TEXT IN ('PRO', 'BUSINESS') THEN
|
||||
log_reason := 'subscription_created';
|
||||
ELSIF OLD."plan"::TEXT IN ('PRO', 'BUSINESS') AND NEW."plan"::TEXT = 'FREE' THEN
|
||||
log_reason := 'subscription_deleted';
|
||||
ELSE
|
||||
log_reason := 'subscription_updated';
|
||||
END IF;
|
||||
|
||||
NEW."lifecycleStage" := next_stage;
|
||||
NEW."lastScoredAt" := NOW();
|
||||
|
||||
IF next_stage IN ('paid', 'hot', 'upgrade_candidate') THEN
|
||||
NEW."lastQualifiedAt" := NOW();
|
||||
END IF;
|
||||
|
||||
INSERT INTO "UserLifecycleLog" (
|
||||
"id",
|
||||
"userId",
|
||||
@@ -43,121 +65,26 @@ INSERT INTO "UserLifecycleLog" (
|
||||
"reason",
|
||||
"createdAt"
|
||||
)
|
||||
SELECT
|
||||
CONCAT('manual_', MD5(updated_user."id" || clock_timestamp()::TEXT || random()::TEXT)),
|
||||
updated_user."id",
|
||||
old_user."lifecycleStage",
|
||||
'paid',
|
||||
updated_user."fitScore",
|
||||
updated_user."intentScore",
|
||||
updated_user."leadScore",
|
||||
'subscription_created',
|
||||
VALUES (
|
||||
CONCAT('planlog_', MD5(NEW."id" || clock_timestamp()::TEXT || random()::TEXT)),
|
||||
NEW."id",
|
||||
OLD."lifecycleStage",
|
||||
next_stage,
|
||||
COALESCE(NEW."fitScore", 0),
|
||||
COALESCE(NEW."intentScore", 0),
|
||||
COALESCE(NEW."leadScore", 0),
|
||||
log_reason,
|
||||
NOW()
|
||||
FROM updated_user
|
||||
JOIN old_user ON old_user."id" = updated_user."id";
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
Upgrade user to BUSINESS
|
||||
========================
|
||||
|
||||
BEGIN;
|
||||
DROP TRIGGER IF EXISTS qrmaster_user_plan_change_alarm ON "User";
|
||||
|
||||
WITH old_user AS (
|
||||
SELECT *
|
||||
FROM "User"
|
||||
WHERE email = 'USER_EMAIL_HERE'
|
||||
FOR UPDATE
|
||||
),
|
||||
updated_user AS (
|
||||
UPDATE "User"
|
||||
SET
|
||||
"plan" = 'BUSINESS',
|
||||
"lifecycleStage" = 'paid',
|
||||
"lastScoredAt" = NOW(),
|
||||
"lastQualifiedAt" = NOW(),
|
||||
"updatedAt" = NOW()
|
||||
WHERE "id" = (SELECT "id" FROM old_user)
|
||||
RETURNING *
|
||||
)
|
||||
INSERT INTO "UserLifecycleLog" (
|
||||
"id",
|
||||
"userId",
|
||||
"fromStage",
|
||||
"toStage",
|
||||
"fitScore",
|
||||
"intentScore",
|
||||
"leadScore",
|
||||
"reason",
|
||||
"createdAt"
|
||||
)
|
||||
SELECT
|
||||
CONCAT('manual_', MD5(updated_user."id" || clock_timestamp()::TEXT || random()::TEXT)),
|
||||
updated_user."id",
|
||||
old_user."lifecycleStage",
|
||||
'paid',
|
||||
updated_user."fitScore",
|
||||
updated_user."intentScore",
|
||||
updated_user."leadScore",
|
||||
'subscription_created',
|
||||
NOW()
|
||||
FROM updated_user
|
||||
JOIN old_user ON old_user."id" = updated_user."id";
|
||||
|
||||
COMMIT;
|
||||
|
||||
Set user to FREE after deabo / subscription ended
|
||||
=================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
WITH old_user AS (
|
||||
SELECT *
|
||||
FROM "User"
|
||||
WHERE email = 'USER_EMAIL_HERE'
|
||||
FOR UPDATE
|
||||
),
|
||||
updated_user AS (
|
||||
UPDATE "User"
|
||||
SET
|
||||
"plan" = 'FREE',
|
||||
"stripeSubscriptionId" = NULL,
|
||||
"stripePriceId" = NULL,
|
||||
"stripeCurrentPeriodEnd" = NULL,
|
||||
"lifecycleStage" = CASE
|
||||
WHEN COALESCE("leadScore", 0) >= 70 THEN 'upgrade_candidate'
|
||||
WHEN COALESCE("leadScore", 0) >= 55 THEN 'hot'
|
||||
WHEN COALESCE("leadScore", 0) >= 30 THEN 'warm'
|
||||
WHEN "activationAt" IS NOT NULL THEN 'activated'
|
||||
ELSE 'cold'
|
||||
END,
|
||||
"lastScoredAt" = NOW(),
|
||||
"updatedAt" = NOW()
|
||||
WHERE "id" = (SELECT "id" FROM old_user)
|
||||
RETURNING *
|
||||
)
|
||||
INSERT INTO "UserLifecycleLog" (
|
||||
"id",
|
||||
"userId",
|
||||
"fromStage",
|
||||
"toStage",
|
||||
"fitScore",
|
||||
"intentScore",
|
||||
"leadScore",
|
||||
"reason",
|
||||
"createdAt"
|
||||
)
|
||||
SELECT
|
||||
CONCAT('manual_', MD5(updated_user."id" || clock_timestamp()::TEXT || random()::TEXT)),
|
||||
updated_user."id",
|
||||
old_user."lifecycleStage",
|
||||
updated_user."lifecycleStage",
|
||||
updated_user."fitScore",
|
||||
updated_user."intentScore",
|
||||
updated_user."leadScore",
|
||||
'subscription_deleted',
|
||||
NOW()
|
||||
FROM updated_user
|
||||
JOIN old_user ON old_user."id" = updated_user."id";
|
||||
|
||||
COMMIT;
|
||||
CREATE TRIGGER qrmaster_user_plan_change_alarm
|
||||
BEFORE UPDATE OF "plan" ON "User"
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION qrmaster_log_plan_change();
|
||||
|
||||
Reference in New Issue
Block a user