@vrplatform/kysely 1.3.45-1 → 1.3.45-14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,539 @@
1
+ import type { Kysely } from 'kysely';
2
+ import { sql } from 'kysely';
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ await sql`create schema if not exists billing`.execute(db);
6
+ await sql`
7
+ create type billing.listing_fact_source_type as enum (
8
+ 'listing_insert',
9
+ 'listing_update',
10
+ 'listing_delete',
11
+ 'ownership_insert',
12
+ 'ownership_update',
13
+ 'ownership_delete',
14
+ 'tenant_insert',
15
+ 'tenant_update',
16
+ 'tenant_delete',
17
+ 'daily_reconciliation',
18
+ 'legacy_tracking_import',
19
+ 'baseline_backfill'
20
+ )
21
+ `.execute(db);
22
+ await sql`
23
+ create table billing.listing_fact (
24
+ id uuid primary key default gen_random_uuid(),
25
+ tenant_id uuid not null,
26
+ billing_partner_id uuid,
27
+ active_listings integer not null,
28
+ tenant_name text not null,
29
+ data_region text not null,
30
+ effective_at timestamptz not null,
31
+ recorded_at timestamptz not null default now(),
32
+ source_type billing.listing_fact_source_type not null,
33
+ source_id uuid not null,
34
+ source_revision bigint,
35
+ reconciliation boolean not null default false,
36
+ constraint listing_fact_active_listings_check
37
+ check (active_listings >= 0),
38
+ constraint listing_fact_source_revision_check
39
+ check (source_revision is null or source_revision > 0),
40
+ constraint listing_fact_source_key
41
+ unique (tenant_id, source_type, source_id)
42
+ )
43
+ `.execute(db);
44
+ await sql`
45
+ create table billing.listing_fact_readiness (
46
+ singleton boolean primary key default true,
47
+ ready_at timestamptz,
48
+ available_from timestamptz,
49
+ verified_month timestamptz,
50
+ legacy_imported_rows integer,
51
+ legacy_gap_count integer,
52
+ parity_confirmed boolean not null default false,
53
+ constraint listing_fact_readiness_singleton_check check (singleton),
54
+ constraint listing_fact_readiness_count_check check (
55
+ legacy_imported_rows is null or legacy_imported_rows >= 0
56
+ ),
57
+ constraint listing_fact_readiness_gap_count_check check (
58
+ legacy_gap_count is null or legacy_gap_count >= 0
59
+ ),
60
+ constraint listing_fact_readiness_evidence_check check (
61
+ (
62
+ ready_at is null
63
+ and available_from is null
64
+ and verified_month is null
65
+ and legacy_imported_rows is null
66
+ and legacy_gap_count is null
67
+ and parity_confirmed = false
68
+ ) or (
69
+ ready_at is not null
70
+ and available_from is not null
71
+ and verified_month is not null
72
+ and legacy_imported_rows is not null
73
+ and legacy_gap_count is not null
74
+ and parity_confirmed = true
75
+ )
76
+ )
77
+ )
78
+ `.execute(db);
79
+ await sql`
80
+ insert into billing.listing_fact_readiness (singleton) values (true)
81
+ `.execute(db);
82
+ await sql`
83
+ create index listing_fact_tenant_effective_idx
84
+ on billing.listing_fact (tenant_id, effective_at desc, id desc)
85
+ `.execute(db);
86
+ await sql`
87
+ create index listing_fact_partner_effective_idx
88
+ on billing.listing_fact (billing_partner_id, effective_at, tenant_id)
89
+ `.execute(db);
90
+ await sql`
91
+ create index listing_fact_region_recorded_idx
92
+ on billing.listing_fact (data_region, recorded_at, id)
93
+ `.execute(db);
94
+
95
+ await sql`
96
+ create function billing.active_listing_count(
97
+ selected_tenant_id uuid
98
+ ) returns integer
99
+ language sql
100
+ stable
101
+ as $$
102
+ select count(*)::integer
103
+ from public.listing as listing
104
+ inner join public.tenant as tenant
105
+ on tenant.id = listing.tenant_id
106
+ left join public.tenant as billing_partner
107
+ on billing_partner.id = tenant.calculated_billing_partner_id
108
+ where listing.tenant_id = selected_tenant_id
109
+ and tenant.calculated_status = 'active'
110
+ and (
111
+ tenant.calculated_billing_partner_id is null
112
+ or billing_partner.calculated_status = 'active'
113
+ )
114
+ and (
115
+ (
116
+ tenant.is_general_ledger = false
117
+ and listing.calculated_status = 'active'
118
+ ) or (
119
+ tenant.is_general_ledger = true
120
+ and not exists (
121
+ select 1
122
+ from public.listing_ownership_period as ownership
123
+ where ownership.listing_id = coalesce(
124
+ listing.parent_id,
125
+ listing.id
126
+ )
127
+ and ownership.tenant_id = listing.tenant_id
128
+ and ownership.set_listing_inactive = true
129
+ and ownership.start_at <= current_date
130
+ and (
131
+ ownership.end_at is null
132
+ or ownership.end_at >= current_date
133
+ )
134
+ )
135
+ )
136
+ )
137
+ $$
138
+ `.execute(db);
139
+ await sql`
140
+ create function billing.record_listing_facts(
141
+ selected_tenant_ids uuid[],
142
+ selected_source_type billing.listing_fact_source_type,
143
+ selected_source_id uuid,
144
+ selected_effective_at timestamptz,
145
+ selected_reconciliation boolean
146
+ ) returns void
147
+ language sql
148
+ as $$
149
+ with calculated as materialized (
150
+ select tenant.id as tenant_id,
151
+ tenant.calculated_billing_partner_id as billing_partner_id,
152
+ billing.active_listing_count(tenant.id) as active_listings,
153
+ tenant.name as tenant_name,
154
+ tenant.data_region as data_region
155
+ from public.tenant as tenant
156
+ where tenant.id = any(selected_tenant_ids)
157
+ and tenant.type = 'propertyManager'
158
+ ), changed as (
159
+ select calculated.*
160
+ from calculated
161
+ left join lateral (
162
+ select fact.id,
163
+ fact.billing_partner_id,
164
+ fact.active_listings,
165
+ fact.tenant_name,
166
+ fact.data_region
167
+ from billing.listing_fact as fact
168
+ where fact.tenant_id = calculated.tenant_id
169
+ order by fact.effective_at desc, fact.recorded_at desc, fact.id desc
170
+ limit 1
171
+ ) as latest on true
172
+ where latest.id is null
173
+ or (
174
+ latest.billing_partner_id,
175
+ latest.active_listings,
176
+ latest.tenant_name,
177
+ latest.data_region
178
+ ) is distinct from (
179
+ calculated.billing_partner_id,
180
+ calculated.active_listings,
181
+ calculated.tenant_name,
182
+ calculated.data_region
183
+ )
184
+ )
185
+ insert into billing.listing_fact (
186
+ tenant_id,
187
+ billing_partner_id,
188
+ active_listings,
189
+ tenant_name,
190
+ data_region,
191
+ effective_at,
192
+ source_type,
193
+ source_id,
194
+ reconciliation
195
+ )
196
+ select tenant_id,
197
+ billing_partner_id,
198
+ active_listings,
199
+ tenant_name,
200
+ data_region,
201
+ selected_effective_at,
202
+ selected_source_type,
203
+ selected_source_id,
204
+ selected_reconciliation
205
+ from changed
206
+ on conflict (tenant_id, source_type, source_id) do nothing
207
+ $$
208
+ `.execute(db);
209
+ await sql`
210
+ create function billing.capture_listing_insert() returns trigger
211
+ language plpgsql as $$
212
+ begin
213
+ perform billing.record_listing_facts(
214
+ array(select distinct tenant_id from new_rows),
215
+ 'listing_insert',
216
+ gen_random_uuid(),
217
+ now(),
218
+ false
219
+ );
220
+ return null;
221
+ end
222
+ $$
223
+ `.execute(db);
224
+ await sql`
225
+ create function billing.capture_listing_update() returns trigger
226
+ language plpgsql as $$
227
+ begin
228
+ perform billing.record_listing_facts(
229
+ array(
230
+ select new_row.tenant_id
231
+ from new_rows as new_row
232
+ inner join old_rows as old_row on old_row.id = new_row.id
233
+ where (
234
+ new_row.tenant_id,
235
+ new_row.parent_id,
236
+ new_row.calculated_status
237
+ ) is distinct from (
238
+ old_row.tenant_id,
239
+ old_row.parent_id,
240
+ old_row.calculated_status
241
+ )
242
+ union
243
+ select old_row.tenant_id
244
+ from new_rows as new_row
245
+ inner join old_rows as old_row on old_row.id = new_row.id
246
+ where (
247
+ new_row.tenant_id,
248
+ new_row.parent_id,
249
+ new_row.calculated_status
250
+ ) is distinct from (
251
+ old_row.tenant_id,
252
+ old_row.parent_id,
253
+ old_row.calculated_status
254
+ )
255
+ ),
256
+ 'listing_update',
257
+ gen_random_uuid(),
258
+ now(),
259
+ false
260
+ );
261
+ return null;
262
+ end
263
+ $$
264
+ `.execute(db);
265
+ await sql`
266
+ create function billing.capture_listing_delete() returns trigger
267
+ language plpgsql as $$
268
+ begin
269
+ perform billing.record_listing_facts(
270
+ array(select distinct tenant_id from old_rows),
271
+ 'listing_delete',
272
+ gen_random_uuid(),
273
+ now(),
274
+ false
275
+ );
276
+ return null;
277
+ end
278
+ $$
279
+ `.execute(db);
280
+ await sql`
281
+ create function billing.capture_ownership_insert() returns trigger
282
+ language plpgsql as $$
283
+ begin
284
+ perform billing.record_listing_facts(
285
+ array(select distinct tenant_id from new_rows),
286
+ 'ownership_insert',
287
+ gen_random_uuid(),
288
+ now(),
289
+ false
290
+ );
291
+ return null;
292
+ end
293
+ $$
294
+ `.execute(db);
295
+ await sql`
296
+ create function billing.capture_ownership_update() returns trigger
297
+ language plpgsql as $$
298
+ begin
299
+ perform billing.record_listing_facts(
300
+ array(
301
+ select new_row.tenant_id
302
+ from new_rows as new_row
303
+ inner join old_rows as old_row on old_row.id = new_row.id
304
+ where (
305
+ new_row.tenant_id,
306
+ new_row.listing_id,
307
+ new_row.set_listing_inactive,
308
+ new_row.start_at,
309
+ new_row.end_at
310
+ ) is distinct from (
311
+ old_row.tenant_id,
312
+ old_row.listing_id,
313
+ old_row.set_listing_inactive,
314
+ old_row.start_at,
315
+ old_row.end_at
316
+ )
317
+ union
318
+ select old_row.tenant_id
319
+ from new_rows as new_row
320
+ inner join old_rows as old_row on old_row.id = new_row.id
321
+ where (
322
+ new_row.tenant_id,
323
+ new_row.listing_id,
324
+ new_row.set_listing_inactive,
325
+ new_row.start_at,
326
+ new_row.end_at
327
+ ) is distinct from (
328
+ old_row.tenant_id,
329
+ old_row.listing_id,
330
+ old_row.set_listing_inactive,
331
+ old_row.start_at,
332
+ old_row.end_at
333
+ )
334
+ ),
335
+ 'ownership_update',
336
+ gen_random_uuid(),
337
+ now(),
338
+ false
339
+ );
340
+ return null;
341
+ end
342
+ $$
343
+ `.execute(db);
344
+ await sql`
345
+ create function billing.capture_ownership_delete() returns trigger
346
+ language plpgsql as $$
347
+ begin
348
+ perform billing.record_listing_facts(
349
+ array(select distinct tenant_id from old_rows),
350
+ 'ownership_delete',
351
+ gen_random_uuid(),
352
+ now(),
353
+ false
354
+ );
355
+ return null;
356
+ end
357
+ $$
358
+ `.execute(db);
359
+ await sql`
360
+ create function billing.capture_tenant_insert() returns trigger
361
+ language plpgsql as $$
362
+ begin
363
+ perform billing.record_listing_facts(
364
+ array(select distinct id from new_rows),
365
+ 'tenant_insert',
366
+ gen_random_uuid(),
367
+ now(),
368
+ false
369
+ );
370
+ return null;
371
+ end
372
+ $$
373
+ `.execute(db);
374
+ await sql`
375
+ create function billing.capture_tenant_update() returns trigger
376
+ language plpgsql as $$
377
+ begin
378
+ perform billing.record_listing_facts(
379
+ array(
380
+ select new_row.id
381
+ from new_rows as new_row
382
+ inner join old_rows as old_row on old_row.id = new_row.id
383
+ where (
384
+ new_row.type,
385
+ new_row.name,
386
+ new_row.data_region,
387
+ new_row.calculated_billing_partner_id,
388
+ new_row.calculated_status,
389
+ new_row.is_general_ledger
390
+ ) is distinct from (
391
+ old_row.type,
392
+ old_row.name,
393
+ old_row.data_region,
394
+ old_row.calculated_billing_partner_id,
395
+ old_row.calculated_status,
396
+ old_row.is_general_ledger
397
+ )
398
+ ),
399
+ 'tenant_update',
400
+ gen_random_uuid(),
401
+ now(),
402
+ false
403
+ );
404
+ return null;
405
+ end
406
+ $$
407
+ `.execute(db);
408
+ await sql`
409
+ create function billing.capture_tenant_delete() returns trigger
410
+ language plpgsql as $$
411
+ begin
412
+ if old.type = 'propertyManager' then
413
+ insert into billing.listing_fact (
414
+ tenant_id,
415
+ billing_partner_id,
416
+ active_listings,
417
+ tenant_name,
418
+ data_region,
419
+ effective_at,
420
+ source_type,
421
+ source_id
422
+ ) values (
423
+ old.id,
424
+ old.calculated_billing_partner_id,
425
+ 0,
426
+ old.name,
427
+ old.data_region,
428
+ now(),
429
+ 'tenant_delete',
430
+ gen_random_uuid()
431
+ );
432
+ end if;
433
+ return old;
434
+ end
435
+ $$
436
+ `.execute(db);
437
+
438
+ await sql`
439
+ create trigger billing_listing_insert
440
+ after insert on public.listing
441
+ referencing new table as new_rows
442
+ for each statement execute function billing.capture_listing_insert()
443
+ `.execute(db);
444
+ await sql`
445
+ create trigger billing_listing_update
446
+ after update on public.listing
447
+ referencing old table as old_rows new table as new_rows
448
+ for each statement execute function billing.capture_listing_update()
449
+ `.execute(db);
450
+ await sql`
451
+ create trigger billing_listing_delete
452
+ after delete on public.listing
453
+ referencing old table as old_rows
454
+ for each statement execute function billing.capture_listing_delete()
455
+ `.execute(db);
456
+ await sql`
457
+ create trigger billing_ownership_insert
458
+ after insert on public.listing_ownership_period
459
+ referencing new table as new_rows
460
+ for each statement execute function billing.capture_ownership_insert()
461
+ `.execute(db);
462
+ await sql`
463
+ create trigger billing_ownership_update
464
+ after update on public.listing_ownership_period
465
+ referencing old table as old_rows new table as new_rows
466
+ for each statement execute function billing.capture_ownership_update()
467
+ `.execute(db);
468
+ await sql`
469
+ create trigger billing_ownership_delete
470
+ after delete on public.listing_ownership_period
471
+ referencing old table as old_rows
472
+ for each statement execute function billing.capture_ownership_delete()
473
+ `.execute(db);
474
+ await sql`
475
+ create trigger billing_tenant_insert
476
+ after insert on public.tenant
477
+ referencing new table as new_rows
478
+ for each statement execute function billing.capture_tenant_insert()
479
+ `.execute(db);
480
+ await sql`
481
+ create trigger billing_tenant_update
482
+ after update on public.tenant
483
+ referencing old table as old_rows new table as new_rows
484
+ for each statement execute function billing.capture_tenant_update()
485
+ `.execute(db);
486
+ await sql`
487
+ create trigger billing_tenant_delete
488
+ before delete on public.tenant
489
+ for each row execute function billing.capture_tenant_delete()
490
+ `.execute(db);
491
+
492
+ await sql`
493
+ do $$
494
+ begin
495
+ if exists (select 1 from pg_roles where rolname = 'application') then
496
+ grant usage on schema billing to application;
497
+ grant select, insert on billing.listing_fact to application;
498
+ grant select on billing.listing_fact_readiness to application;
499
+ grant execute on function billing.active_listing_count(uuid)
500
+ to application;
501
+ grant execute on function billing.record_listing_facts(
502
+ uuid[], billing.listing_fact_source_type, uuid, timestamptz, boolean
503
+ ) to application;
504
+ end if;
505
+ end
506
+ $$
507
+ `.execute(db);
508
+ }
509
+
510
+ export async function down(db: Kysely<unknown>): Promise<void> {
511
+ await sql`drop trigger if exists billing_tenant_delete on public.tenant`.execute(
512
+ db
513
+ );
514
+ await sql`drop trigger if exists billing_tenant_update on public.tenant`.execute(
515
+ db
516
+ );
517
+ await sql`drop trigger if exists billing_tenant_insert on public.tenant`.execute(
518
+ db
519
+ );
520
+ await sql`drop trigger if exists billing_ownership_delete on public.listing_ownership_period`.execute(
521
+ db
522
+ );
523
+ await sql`drop trigger if exists billing_ownership_update on public.listing_ownership_period`.execute(
524
+ db
525
+ );
526
+ await sql`drop trigger if exists billing_ownership_insert on public.listing_ownership_period`.execute(
527
+ db
528
+ );
529
+ await sql`drop trigger if exists billing_listing_delete on public.listing`.execute(
530
+ db
531
+ );
532
+ await sql`drop trigger if exists billing_listing_update on public.listing`.execute(
533
+ db
534
+ );
535
+ await sql`drop trigger if exists billing_listing_insert on public.listing`.execute(
536
+ db
537
+ );
538
+ await sql`drop schema if exists billing cascade`.execute(db);
539
+ }
@@ -0,0 +1,18 @@
1
+ import type { Kysely } from 'kysely';
2
+ import { sql } from 'kysely';
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ await sql`
6
+ alter table webhook.subscription_secret
7
+ add column reencryption_failed_at timestamptz,
8
+ add column reencryption_failure_code text
9
+ `.execute(db);
10
+ }
11
+
12
+ export async function down(db: Kysely<unknown>): Promise<void> {
13
+ await sql`
14
+ alter table webhook.subscription_secret
15
+ drop column reencryption_failure_code,
16
+ drop column reencryption_failed_at
17
+ `.execute(db);
18
+ }
@@ -0,0 +1,28 @@
1
+ import type { Kysely } from 'kysely';
2
+ import { sql } from 'kysely';
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ await sql`
6
+ alter table core.flow_event
7
+ add column requires_sensitive_input boolean not null default false
8
+ `.execute(db);
9
+ await sql`drop index core.flow_event_sync_idx`.execute(db);
10
+ await sql`
11
+ create index flow_event_sync_idx
12
+ on core.flow_event (sync_id, status)
13
+ where sync_id is not null
14
+ `.execute(db);
15
+ }
16
+
17
+ export async function down(db: Kysely<unknown>): Promise<void> {
18
+ await sql`drop index core.flow_event_sync_idx`.execute(db);
19
+ await sql`
20
+ create index flow_event_sync_idx
21
+ on core.flow_event (tenant_id, sync_id)
22
+ where sync_id is not null
23
+ `.execute(db);
24
+ await sql`
25
+ alter table core.flow_event
26
+ drop column requires_sensitive_input
27
+ `.execute(db);
28
+ }