@vrplatform/kysely 1.3.45-stage.6066 → 1.3.45-stage.607

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.
Files changed (97) hide show
  1. package/build/.data.tar +0 -0
  2. package/build/main/control-plane/index.d.ts +312 -0
  3. package/build/main/control-plane/index.js.map +1 -1
  4. package/build/main/index.d.ts +13 -2
  5. package/build/main/index.js +217 -23
  6. package/build/main/index.js.map +1 -1
  7. package/build/main/local/generate.js +2 -0
  8. package/build/main/local/generate.js.map +1 -1
  9. package/build/main/local/index.js +110 -8
  10. package/build/main/local/index.js.map +1 -1
  11. package/build/main/postgres-error.d.ts +3 -3
  12. package/build/main/postgres-error.js +4 -3
  13. package/build/main/postgres-error.js.map +1 -1
  14. package/build/main/query/listing/status.js +2 -6
  15. package/build/main/query/listing/status.js.map +1 -1
  16. package/build/main/query/tenant/status.d.ts +1 -1
  17. package/build/main/query/tenant/status.js +6 -4
  18. package/build/main/query/tenant/status.js.map +1 -1
  19. package/build/main/regional.d.ts +1 -0
  20. package/build/main/regional.js +1 -0
  21. package/build/main/regional.js.map +1 -1
  22. package/build/main/test/index.d.ts +23 -3
  23. package/build/main/test/index.js +35 -13
  24. package/build/main/test/index.js.map +1 -1
  25. package/build/main/v1.generated.d.ts +560 -8
  26. package/build/main/v1.generated.js.map +1 -1
  27. package/build/migrations-v2/0000000000015-durable-flow-events.ts +163 -0
  28. package/build/migrations-v2/0000000000016-billing-listing-facts.ts +539 -0
  29. package/build/migrations-v2/0000000000016-managed-team-access.ts +34 -0
  30. package/build/migrations-v2/0000000000017-drop-trial-until.ts +42 -0
  31. package/build/migrations-v2/0000000000017-webhook-secret-reencryption-failures.ts +18 -0
  32. package/build/migrations-v2/0000000000018-accounting-integrity-monitoring.ts +276 -0
  33. package/build/migrations-v2/0000000000018-durable-flow-event-sensitive-input.ts +28 -0
  34. package/build/migrations-v2/0000000000019-accounting-integrity-run-shards.ts +26 -0
  35. package/build/migrations-v2/0000000000019-asynchronous-operations.ts +736 -0
  36. package/build/migrations-v2/0000000000020-accounting-integrity-case-classification.ts +52 -0
  37. package/build/migrations-v2/0000000000021-payment-line-classification-monitor-indexes.ts +31 -0
  38. package/build/migrations-v2/0000000000022-accounting-integrity-controlled-repairs.ts +281 -0
  39. package/build/migrations-v2/0000000000023-line-classification-usage.ts +325 -0
  40. package/build/migrations-v2/0000000000024-tenant-region-migration.ts +108 -0
  41. package/build/migrations-v2/0000000000025-partner-ach-denial-default.ts +30 -0
  42. package/build/migrations-v2/0000000000026-line-classification-usage-capture.ts +399 -0
  43. package/build/migrations-v2/0000000000027-payout-replacement-chain.ts +27 -0
  44. package/build/migrations-v2/0000000000028-accounting-integrity-operator-workflow.ts +108 -0
  45. package/build/migrations-v2/0000000000029-accounting-integrity-definition-artifacts.ts +40 -0
  46. package/build/migrations-v2/0000000000030-accounting-integrity-review-metadata-compatibility.ts +49 -0
  47. package/build/migrations-v2/0000000000031-ui-permission-role-simplification.ts +70 -0
  48. package/build/migrations-v2/0000000000032-tenant-delete-ownership-cascades.ts +44 -0
  49. package/build/migrations-v2/0000000000033-reservation-issue-seed-bucket-index.ts +19 -0
  50. package/build/migrations-v2/0000000000034-retire-recent-classification-indexes.ts +29 -0
  51. package/build/migrations-v2/0000000000035-core-change-autovacuum.ts +24 -0
  52. package/build/migrations-v2/0000000000036-journal-entry-inactive-reason-constraint.ts +33 -0
  53. package/build/migrations-v2/0000000000037-journal-entry-inactive-reasons.ts +19 -0
  54. package/build/migrations-v2/0000000000038-journal-entry-group-inactive-reason.ts +14 -0
  55. package/build/migrations-v2/0000000000039-reservation-guest-breakdown.ts +19 -0
  56. package/build/migrations-v2/0000000000040-csv-import-source-identity-index.ts +23 -0
  57. package/build/migrations-v2/0000000000041-payment-returns.ts +38 -0
  58. package/build/migrations-v2/0000000000042-operation-resource-types.ts +609 -0
  59. package/build/migrations-v2/0000000000043-reservation-journal-freshness.ts +149 -0
  60. package/build/migrations-v2/0000000000044-reservation-journal-freshness-backfill.ts +254 -0
  61. package/build/migrations-v2/0000000000045-reservation-journal-freshness-revision-repair.ts +83 -0
  62. package/build/migrations-v2/0000000000046-materialized-reservation-journal-operations.ts +709 -0
  63. package/build/migrations-v2/0000000000047-public-audit-completion.ts +77 -0
  64. package/build/migrations-v2/0000000000048-reservation-journal-full-refresh-repair.ts +136 -0
  65. package/build/migrations-v2/0000000000049-queued-journal-operation-failures.ts +60 -0
  66. package/build/migrations-v2/0000000000050-connection-oauth-state.ts +43 -0
  67. package/build/migrations-v2/0000000000051-owner-statement-email-delivery.ts +134 -0
  68. package/build/migrations-v2/0000000000052-fee-journal-lock-skip-operations.ts +59 -0
  69. package/build/migrations-v2/0000000000053-fee-journal-lock-skip-null-attempt.ts +44 -0
  70. package/build/migrations-v2/0000000000054-journal-refresh-issue-codes.ts +16 -0
  71. package/build/migrations-v2/0000000000055-tenant-billing-subscription.ts +8 -0
  72. package/build/module/control-plane/index.d.ts +312 -0
  73. package/build/module/control-plane/index.js.map +1 -1
  74. package/build/module/index.d.ts +13 -2
  75. package/build/module/index.js +219 -24
  76. package/build/module/index.js.map +1 -1
  77. package/build/module/local/generate.js +2 -0
  78. package/build/module/local/generate.js.map +1 -1
  79. package/build/module/local/index.js +110 -8
  80. package/build/module/local/index.js.map +1 -1
  81. package/build/module/postgres-error.d.ts +3 -3
  82. package/build/module/postgres-error.js +4 -3
  83. package/build/module/postgres-error.js.map +1 -1
  84. package/build/module/query/listing/status.js +2 -6
  85. package/build/module/query/listing/status.js.map +1 -1
  86. package/build/module/query/tenant/status.d.ts +1 -1
  87. package/build/module/query/tenant/status.js +6 -4
  88. package/build/module/query/tenant/status.js.map +1 -1
  89. package/build/module/regional.d.ts +1 -0
  90. package/build/module/regional.js +1 -0
  91. package/build/module/regional.js.map +1 -1
  92. package/build/module/test/index.d.ts +23 -3
  93. package/build/module/test/index.js +34 -13
  94. package/build/module/test/index.js.map +1 -1
  95. package/build/module/v1.generated.d.ts +560 -8
  96. package/build/module/v1.generated.js.map +1 -1
  97. package/package.json +4 -2
@@ -0,0 +1,149 @@
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
+ create table accounting.reservation_journal_freshness_control (
7
+ tenant_id uuid primary key references public.tenant(id) on delete cascade,
8
+ guards_enabled_at timestamptz,
9
+ created_at timestamptz not null default now(),
10
+ updated_at timestamptz not null default now()
11
+ )
12
+ `.execute(db);
13
+ await sql`
14
+ create table accounting.reservation_journal_state (
15
+ tenant_id uuid not null references public.tenant(id) on delete cascade,
16
+ reservation_id uuid primary key references public.reservation(id) on delete cascade,
17
+ desired_revision bigint not null default 0,
18
+ applied_revision bigint not null default 0,
19
+ stale_since timestamptz,
20
+ calculated_at timestamptz,
21
+ created_at timestamptz not null default now(),
22
+ updated_at timestamptz not null default now()
23
+ )
24
+ `.execute(db);
25
+ await sql`
26
+ create index reservation_journal_state_tenant_stale_idx
27
+ on accounting.reservation_journal_state (
28
+ tenant_id,
29
+ stale_since,
30
+ reservation_id
31
+ )
32
+ where desired_revision > applied_revision
33
+ `.execute(db);
34
+ await sql`
35
+ create function accounting.initialize_reservation_journal_state()
36
+ returns trigger
37
+ language plpgsql
38
+ as $$
39
+ begin
40
+ if new.tenant_id is not null then
41
+ insert into accounting.reservation_journal_state (
42
+ tenant_id,
43
+ reservation_id
44
+ ) values (
45
+ new.tenant_id,
46
+ new.id
47
+ )
48
+ on conflict (reservation_id) do nothing;
49
+ end if;
50
+ return new;
51
+ end;
52
+ $$
53
+ `.execute(db);
54
+ await sql`
55
+ create table accounting.reservation_journal_invalidation (
56
+ id uuid primary key default gen_random_uuid(),
57
+ tenant_id uuid not null references public.tenant(id) on delete cascade,
58
+ reservation_id uuid not null references public.reservation(id) on delete cascade,
59
+ revision bigint not null,
60
+ action_id uuid references audit.action(id) on delete set null,
61
+ effect_id uuid references audit.effect(id) on delete set null,
62
+ source_resource_type core.operation_resource_type,
63
+ source_resource_id uuid,
64
+ applied_at timestamptz,
65
+ covered_by_effect_id uuid references audit.effect(id) on delete set null,
66
+ created_at timestamptz not null default now(),
67
+ unique (tenant_id, reservation_id, revision),
68
+ unique (effect_id)
69
+ )
70
+ `.execute(db);
71
+ await sql`
72
+ create index reservation_journal_invalidation_reservation_pending_idx
73
+ on accounting.reservation_journal_invalidation (
74
+ tenant_id,
75
+ reservation_id,
76
+ revision,
77
+ effect_id
78
+ )
79
+ where applied_at is null
80
+ `.execute(db);
81
+ await sql`
82
+ create index reservation_journal_invalidation_source_pending_idx
83
+ on accounting.reservation_journal_invalidation (
84
+ tenant_id,
85
+ source_resource_type,
86
+ source_resource_id,
87
+ revision
88
+ )
89
+ where applied_at is null
90
+ `.execute(db);
91
+
92
+ await sql`
93
+ create table accounting.reservation_journal_statement_impact (
94
+ invalidation_id uuid not null
95
+ references accounting.reservation_journal_invalidation(id) on delete cascade,
96
+ tenant_id uuid not null references public.tenant(id) on delete cascade,
97
+ listing_id uuid not null references public.listing(id) on delete cascade,
98
+ listing_ownership_period_id uuid not null
99
+ references public.listing_ownership_period(id) on delete cascade,
100
+ month date not null,
101
+ currency text not null,
102
+ created_at timestamptz not null default now(),
103
+ primary key (
104
+ invalidation_id,
105
+ listing_id,
106
+ listing_ownership_period_id,
107
+ month,
108
+ currency
109
+ )
110
+ )
111
+ `.execute(db);
112
+ await sql`
113
+ create index reservation_journal_statement_impact_scope_idx
114
+ on accounting.reservation_journal_statement_impact (
115
+ tenant_id,
116
+ listing_ownership_period_id,
117
+ month,
118
+ currency,
119
+ invalidation_id
120
+ )
121
+ `.execute(db);
122
+ await sql`
123
+ create trigger initialize_reservation_journal_state
124
+ after insert on public.reservation
125
+ for each row execute function accounting.initialize_reservation_journal_state()
126
+ `.execute(db);
127
+ }
128
+
129
+ export async function down(db: Kysely<unknown>): Promise<void> {
130
+ await sql`
131
+ drop table if exists accounting.reservation_journal_statement_impact
132
+ `.execute(db);
133
+ await sql`
134
+ drop table if exists accounting.reservation_journal_invalidation
135
+ `.execute(db);
136
+ await sql`
137
+ drop trigger if exists initialize_reservation_journal_state
138
+ on public.reservation
139
+ `.execute(db);
140
+ await sql`
141
+ drop function if exists accounting.initialize_reservation_journal_state
142
+ `.execute(db);
143
+ await sql`
144
+ drop table if exists accounting.reservation_journal_state
145
+ `.execute(db);
146
+ await sql`
147
+ drop table if exists accounting.reservation_journal_freshness_control
148
+ `.execute(db);
149
+ }
@@ -0,0 +1,254 @@
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
+ insert into accounting.reservation_journal_state (
7
+ tenant_id,
8
+ reservation_id,
9
+ calculated_at
10
+ )
11
+ select reservation.tenant_id, reservation.id, now()
12
+ from public.reservation as reservation
13
+ where reservation.tenant_id is not null
14
+ on conflict (reservation_id) do nothing
15
+ `.execute(db);
16
+
17
+ await sql`
18
+ with outstanding as (
19
+ select
20
+ effect.tenant_id,
21
+ effect.entity_id::uuid as reservation_id,
22
+ effect.action_id,
23
+ effect.id as effect_id,
24
+ effect.root_entity_type,
25
+ effect.root_entity_id,
26
+ effect.created_at,
27
+ effect.completed_at,
28
+ effect.status,
29
+ (
30
+ select attempt.status
31
+ from audit.effect_attempt as attempt
32
+ where attempt.tenant_id = effect.tenant_id
33
+ and attempt.effect_id = effect.id
34
+ order by attempt.attempt_num desc
35
+ limit 1
36
+ ) as latest_attempt_status,
37
+ row_number() over (
38
+ partition by effect.tenant_id, effect.entity_id
39
+ order by effect.created_at, effect.id
40
+ ) as revision
41
+ from audit.effect as effect
42
+ inner join public.reservation as reservation
43
+ on reservation.id = effect.entity_id
44
+ and reservation.tenant_id = effect.tenant_id
45
+ where effect.effect_type = 'REFRESH_RESERVATION_JOURNAL'
46
+ and effect.entity_type = 'reservation'
47
+ )
48
+ insert into accounting.reservation_journal_invalidation (
49
+ tenant_id,
50
+ reservation_id,
51
+ revision,
52
+ action_id,
53
+ effect_id,
54
+ source_resource_type,
55
+ source_resource_id,
56
+ applied_at,
57
+ covered_by_effect_id,
58
+ created_at
59
+ )
60
+ select
61
+ outstanding.tenant_id,
62
+ outstanding.reservation_id,
63
+ outstanding.revision,
64
+ outstanding.action_id,
65
+ outstanding.effect_id,
66
+ case outstanding.root_entity_type
67
+ when 'recurringFee' then 'recurring-fee'::core.operation_resource_type
68
+ when 'reservation' then 'reservation'::core.operation_resource_type
69
+ when 'listing' then 'listing'::core.operation_resource_type
70
+ when 'ownerStatement' then 'statement'::core.operation_resource_type
71
+ else 'team'::core.operation_resource_type
72
+ end,
73
+ case
74
+ when outstanding.root_entity_type in (
75
+ 'recurringFee',
76
+ 'reservation',
77
+ 'listing',
78
+ 'ownerStatement'
79
+ ) then outstanding.root_entity_id
80
+ else outstanding.tenant_id
81
+ end,
82
+ case
83
+ when outstanding.status = 'completed'
84
+ and outstanding.latest_attempt_status is distinct from 'skipped_locked'
85
+ then outstanding.completed_at
86
+ else null
87
+ end,
88
+ case
89
+ when outstanding.status = 'completed'
90
+ and outstanding.latest_attempt_status is distinct from 'skipped_locked'
91
+ then outstanding.effect_id
92
+ else null
93
+ end,
94
+ outstanding.created_at
95
+ from outstanding
96
+ on conflict (effect_id) do nothing
97
+ `.execute(db);
98
+
99
+ await sql`
100
+ update accounting.reservation_journal_state as state
101
+ set
102
+ desired_revision = revisions.desired_revision,
103
+ applied_revision = revisions.applied_revision,
104
+ stale_since = revisions.stale_since,
105
+ calculated_at = coalesce(revisions.calculated_at, state.calculated_at),
106
+ updated_at = now()
107
+ from (
108
+ select
109
+ tenant_id,
110
+ reservation_id,
111
+ max(revision) as desired_revision,
112
+ coalesce(
113
+ min(revision) filter (where applied_at is null) - 1,
114
+ max(revision)
115
+ ) as applied_revision,
116
+ min(created_at) filter (where applied_at is null) as stale_since,
117
+ max(applied_at) as calculated_at
118
+ from accounting.reservation_journal_invalidation
119
+ group by tenant_id, reservation_id
120
+ ) as revisions
121
+ where state.tenant_id = revisions.tenant_id
122
+ and state.reservation_id = revisions.reservation_id
123
+ `.execute(db);
124
+
125
+ await sql`
126
+ with reservation_scope as (
127
+ select
128
+ invalidation.id as invalidation_id,
129
+ invalidation.tenant_id,
130
+ reservation.id as reservation_id,
131
+ listing_scope.listing_id,
132
+ coalesce(reservation.currency, tenant.default_currency) as currency,
133
+ least(
134
+ reservation.effective_check_in,
135
+ reservation.effective_check_out,
136
+ reservation.booked_at,
137
+ reservation.general_ledger_posting_at,
138
+ reservation.created_at,
139
+ line_bounds.minimum_at,
140
+ entry_bounds.minimum_at
141
+ ) as minimum_at,
142
+ greatest(
143
+ reservation.effective_check_in,
144
+ reservation.effective_check_out,
145
+ reservation.booked_at,
146
+ reservation.general_ledger_posting_at,
147
+ reservation.created_at,
148
+ line_bounds.maximum_at,
149
+ entry_bounds.maximum_at
150
+ ) as maximum_at
151
+ from accounting.reservation_journal_invalidation as invalidation
152
+ inner join public.reservation as reservation
153
+ on reservation.id = invalidation.reservation_id
154
+ and reservation.tenant_id = invalidation.tenant_id
155
+ inner join public.tenant as tenant
156
+ on tenant.id = invalidation.tenant_id
157
+ inner join lateral (
158
+ select coalesce(listing.parent_id, reservation.listing_id) as listing_id
159
+ from public.listing as listing
160
+ where listing.id = reservation.listing_id
161
+ union
162
+ select distinct coalesce(entry_listing.parent_id, entry.listing_id)
163
+ from accounting.journal_entry as entry
164
+ left join public.listing as entry_listing
165
+ on entry_listing.id = entry.listing_id
166
+ where entry.tenant_id = invalidation.tenant_id
167
+ and entry.reservation_id = invalidation.reservation_id
168
+ and entry.listing_id is not null
169
+ ) as listing_scope on true
170
+ left join lateral (
171
+ select
172
+ min(line.general_ledger_posting_at) as minimum_at,
173
+ max(line.general_ledger_posting_at) as maximum_at
174
+ from public.payment_line as line
175
+ where line.tenant_id = invalidation.tenant_id
176
+ and line.reservation_id = invalidation.reservation_id
177
+ ) as line_bounds on true
178
+ left join lateral (
179
+ select
180
+ min(entry.txn_at) as minimum_at,
181
+ max(entry.txn_at) as maximum_at
182
+ from accounting.journal_entry as entry
183
+ where entry.tenant_id = invalidation.tenant_id
184
+ and entry.reservation_id = invalidation.reservation_id
185
+ ) as entry_bounds on true
186
+ where invalidation.applied_at is null
187
+ and listing_scope.listing_id is not null
188
+ ), currencies as (
189
+ select
190
+ scope.invalidation_id,
191
+ scope.tenant_id,
192
+ scope.listing_id,
193
+ scope.minimum_at,
194
+ scope.maximum_at,
195
+ scope.currency
196
+ from reservation_scope as scope
197
+ where scope.currency is not null
198
+ union
199
+ select
200
+ scope.invalidation_id,
201
+ scope.tenant_id,
202
+ scope.listing_id,
203
+ scope.minimum_at,
204
+ scope.maximum_at,
205
+ entry.currency
206
+ from reservation_scope as scope
207
+ inner join accounting.journal_entry as entry
208
+ on entry.tenant_id = scope.tenant_id
209
+ and entry.reservation_id = scope.reservation_id
210
+ ), months as (
211
+ select
212
+ currencies.*,
213
+ month::date as month
214
+ from currencies
215
+ cross join lateral generate_series(
216
+ date_trunc('month', currencies.minimum_at),
217
+ date_trunc('month', currencies.maximum_at),
218
+ interval '1 month'
219
+ ) as month
220
+ where currencies.minimum_at is not null
221
+ and currencies.maximum_at is not null
222
+ )
223
+ insert into accounting.reservation_journal_statement_impact (
224
+ invalidation_id,
225
+ tenant_id,
226
+ listing_id,
227
+ listing_ownership_period_id,
228
+ month,
229
+ currency
230
+ )
231
+ select distinct
232
+ months.invalidation_id,
233
+ months.tenant_id,
234
+ months.listing_id,
235
+ ownership.id,
236
+ months.month,
237
+ months.currency
238
+ from months
239
+ inner join public.listing_ownership_period as ownership
240
+ on ownership.tenant_id = months.tenant_id
241
+ and ownership.listing_id = months.listing_id
242
+ and (
243
+ ownership.start_at is null
244
+ or ownership.start_at < months.month + interval '1 month'
245
+ )
246
+ and (
247
+ ownership.end_at is null
248
+ or ownership.end_at > months.month
249
+ )
250
+ on conflict do nothing
251
+ `.execute(db);
252
+ }
253
+
254
+ export async function down(_db: Kysely<unknown>): Promise<void> {}
@@ -0,0 +1,83 @@
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
+ with desired_revisions as (
7
+ select
8
+ state.tenant_id,
9
+ state.reservation_id,
10
+ max(invalidation.revision) as desired_revision
11
+ from accounting.reservation_journal_state as state
12
+ inner join accounting.reservation_journal_invalidation as invalidation
13
+ on invalidation.tenant_id = state.tenant_id
14
+ and invalidation.reservation_id = state.reservation_id
15
+ and invalidation.revision > state.desired_revision
16
+ group by state.tenant_id, state.reservation_id
17
+ )
18
+ update accounting.reservation_journal_state as state
19
+ set
20
+ desired_revision = greatest(
21
+ state.desired_revision,
22
+ desired_revisions.desired_revision
23
+ ),
24
+ updated_at = now()
25
+ from desired_revisions
26
+ where state.tenant_id = desired_revisions.tenant_id
27
+ and state.reservation_id = desired_revisions.reservation_id
28
+ and state.desired_revision < desired_revisions.desired_revision
29
+ `.execute(db);
30
+
31
+ await sql`
32
+ with advancement as (
33
+ select
34
+ state.tenant_id,
35
+ state.reservation_id,
36
+ coalesce(
37
+ min(invalidation.revision) filter (
38
+ where invalidation.applied_at is null
39
+ ) - 1,
40
+ max(invalidation.revision),
41
+ state.applied_revision
42
+ ) as applied_revision,
43
+ min(invalidation.created_at) filter (
44
+ where invalidation.applied_at is null
45
+ ) as stale_since,
46
+ max(invalidation.applied_at) as calculated_at
47
+ from accounting.reservation_journal_state as state
48
+ left join accounting.reservation_journal_invalidation as invalidation
49
+ on invalidation.tenant_id = state.tenant_id
50
+ and invalidation.reservation_id = state.reservation_id
51
+ where state.desired_revision > state.applied_revision
52
+ group by
53
+ state.tenant_id,
54
+ state.reservation_id,
55
+ state.applied_revision
56
+ )
57
+ update accounting.reservation_journal_state as state
58
+ set
59
+ applied_revision = greatest(
60
+ state.applied_revision,
61
+ advancement.applied_revision
62
+ ),
63
+ stale_since = case
64
+ when greatest(
65
+ state.applied_revision,
66
+ advancement.applied_revision
67
+ ) >= state.desired_revision then null
68
+ else coalesce(state.stale_since, advancement.stale_since)
69
+ end,
70
+ calculated_at = case
71
+ when advancement.applied_revision > state.applied_revision
72
+ then greatest(state.calculated_at, advancement.calculated_at)
73
+ else state.calculated_at
74
+ end,
75
+ updated_at = now()
76
+ from advancement
77
+ where state.tenant_id = advancement.tenant_id
78
+ and state.reservation_id = advancement.reservation_id
79
+ and state.applied_revision < advancement.applied_revision
80
+ `.execute(db);
81
+ }
82
+
83
+ export async function down(_db: Kysely<unknown>): Promise<void> {}