-
-
Notifications
You must be signed in to change notification settings - Fork 158
Expand file tree
/
Copy pathmigration.sql
More file actions
131 lines (122 loc) · 4.13 KB
/
migration.sql
File metadata and controls
131 lines (122 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
-- DropForeignKey
ALTER TABLE "public"."Balance" DROP CONSTRAINT "Balance_friendId_fkey";
-- DropForeignKey
ALTER TABLE "public"."Balance" DROP CONSTRAINT "Balance_userId_fkey";
-- DropForeignKey
ALTER TABLE "public"."GroupBalance" DROP CONSTRAINT "GroupBalance_firendId_fkey";
-- DropForeignKey
ALTER TABLE "public"."GroupBalance" DROP CONSTRAINT "GroupBalance_groupId_fkey";
-- DropForeignKey
ALTER TABLE "public"."GroupBalance" DROP CONSTRAINT "GroupBalance_userId_fkey";
-- Adjust Splitwise imported balances to account for BalanceView only counting expenses
WITH "Differences" AS (
SELECT
B."userId",
B."friendId",
B."currency",
-- Calculate the difference
(B."amount" - COALESCE(BV."amount", 0)) AS "diff_amount",
B."createdAt",
-- Pre-generate the Expense ID
gen_random_uuid() AS "new_expense_id"
FROM
"Balance" B
LEFT JOIN (
SELECT "userId", "friendId", "currency", SUM("amount") as "amount"
FROM "BalanceView"
GROUP BY "userId", "friendId", "currency"
) BV ON B."userId" = BV."userId"
AND B."friendId" = BV."friendId"
AND B."currency" = BV."currency"
WHERE
B."importedFromSplitwise" = true
AND B."userId" < B."friendId"
AND (B."amount" - COALESCE(BV."amount", 0)) != 0
),
"InsertExpenses" AS (
INSERT INTO "Expense" (
"id",
"paidBy",
"addedBy",
"name",
"category",
"amount",
"currency",
"splitType",
"expenseDate",
"createdAt",
"updatedAt",
"groupId"
)
SELECT
"new_expense_id",
-- Determine Payer: If diff < 0, Friend is creditor. If diff > 0, User is creditor.
CASE WHEN "diff_amount" < 0 THEN "friendId" ELSE "userId" END,
CASE WHEN "diff_amount" < 0 THEN "friendId" ELSE "userId" END,
'Splitwise Balance Import',
'general',
ABS("diff_amount"), -- Expense amount is always positive
"currency",
'EXACT',
"createdAt",
"createdAt",
"createdAt",
NULL
FROM "Differences"
-- RETURNING needed info for the next step
RETURNING "id", "amount", "paidBy"
),
"InsertParticipants" AS (
INSERT INTO "ExpenseParticipant" (
"expenseId",
"userId",
"amount"
)
-- Row 1: The Payer (Creditor) -> Positive Amount
SELECT
ie."id",
ie."paidBy",
ie."amount" -- Positive flow (they paid/are owed)
FROM "InsertExpenses" ie
UNION ALL
-- Row 2: The Debtor -> Negative Amount
SELECT
ie."id",
-- The Debtor is whoever is NOT the payer.
CASE
WHEN ie."paidBy" = d."friendId" THEN d."userId"
ELSE d."friendId"
END,
-ie."amount" -- Negative flow (they owe)
FROM "InsertExpenses" ie
JOIN "Differences" d ON ie."id" = d."new_expense_id"
)
SELECT count(*) as "AdjustmentsCreated" FROM "InsertExpenses";
-- AlterTable
ALTER TABLE "public"."User" ADD COLUMN "hiddenFriendIds" INTEGER[] DEFAULT ARRAY[]::INTEGER[];
-- Function to remove a user ID from the hiddenFriendIds array
CREATE OR REPLACE FUNCTION public.auto_unhide_friend()
RETURNS TRIGGER AS $$
DECLARE
payer_id INT;
BEGIN
SELECT "paidBy" INTO payer_id FROM "Expense" WHERE id = NEW."expenseId";
-- ONLY update if the array actually contains the ID.
-- This prevents locking the row if the friend is already visible (which is 99% of cases).
UPDATE "User"
SET "hiddenFriendIds" = array_remove("hiddenFriendIds", payer_id)
WHERE id = NEW."userId"
AND "hiddenFriendIds" @> ARRAY[payer_id]; -- Only if array contains payer_id
UPDATE "User"
SET "hiddenFriendIds" = array_remove("hiddenFriendIds", NEW."userId")
WHERE id = payer_id
AND "hiddenFriendIds" @> ARRAY[NEW."userId"]; -- Only if array contains userId
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger definition
DROP TRIGGER IF EXISTS trigger_auto_unhide_friend ON "ExpenseParticipant";
CREATE TRIGGER trigger_auto_unhide_friend
AFTER INSERT ON "ExpenseParticipant"
FOR EACH ROW
EXECUTE FUNCTION public.auto_unhide_friend();