@voyantjs/transactions 0.1.0

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 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,eAAe,uHAQ1B,CAAA;AAEF,eAAO,MAAM,eAAe,8GAO1B,CAAA;AAEF,eAAO,MAAM,8BAA8B,uGAOzC,CAAA;AAEF,eAAO,MAAM,+BAA+B,uFAM1C,CAAA;AAEF,eAAO,MAAM,uBAAuB,mJAWlC,CAAA;AAEF,eAAO,MAAM,yBAAyB,kGAMpC,CAAA;AAEF,eAAO,MAAM,kCAAkC,+HAO7C,CAAA;AAEF,eAAO,MAAM,8BAA8B,oEAIzC,CAAA;AAEF,eAAO,MAAM,+BAA+B,6DAG1C,CAAA;AAEF,eAAO,MAAM,iBAAiB,0IAQ5B,CAAA;AAEF,eAAO,MAAM,6BAA6B,2FAKxC,CAAA;AAEF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ClB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B7B,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCtB,CAAA;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBjC,CAAA;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ClB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
package/dist/schema.js ADDED
@@ -0,0 +1,420 @@
1
+ import { typeId, typeIdRef } from "@voyantjs/db/lib/typeid-column";
2
+ import { relations } from "drizzle-orm";
3
+ import { boolean, date, index, integer, jsonb, pgEnum, pgTable, text, timestamp, uniqueIndex, } from "drizzle-orm/pg-core";
4
+ export const offerStatusEnum = pgEnum("offer_status", [
5
+ "draft",
6
+ "published",
7
+ "sent",
8
+ "accepted",
9
+ "expired",
10
+ "withdrawn",
11
+ "converted",
12
+ ]);
13
+ export const orderStatusEnum = pgEnum("order_status", [
14
+ "draft",
15
+ "pending",
16
+ "confirmed",
17
+ "fulfilled",
18
+ "cancelled",
19
+ "expired",
20
+ ]);
21
+ export const transactionParticipantTypeEnum = pgEnum("transaction_participant_type", [
22
+ "traveler",
23
+ "booker",
24
+ "contact",
25
+ "occupant",
26
+ "staff",
27
+ "other",
28
+ ]);
29
+ export const transactionTravelerCategoryEnum = pgEnum("transaction_traveler_category", [
30
+ "adult",
31
+ "child",
32
+ "infant",
33
+ "senior",
34
+ "other",
35
+ ]);
36
+ export const transactionItemTypeEnum = pgEnum("transaction_item_type", [
37
+ "unit",
38
+ "service",
39
+ "extra",
40
+ "fee",
41
+ "tax",
42
+ "discount",
43
+ "adjustment",
44
+ "accommodation",
45
+ "transport",
46
+ "other",
47
+ ]);
48
+ export const transactionItemStatusEnum = pgEnum("transaction_item_status", [
49
+ "draft",
50
+ "priced",
51
+ "confirmed",
52
+ "cancelled",
53
+ "fulfilled",
54
+ ]);
55
+ export const transactionItemParticipantRoleEnum = pgEnum("transaction_item_participant_role", [
56
+ "traveler",
57
+ "occupant",
58
+ "primary_contact",
59
+ "beneficiary",
60
+ "service_assignee",
61
+ "other",
62
+ ]);
63
+ export const transactionPiiAccessActionEnum = pgEnum("transaction_pii_access_action", [
64
+ "read",
65
+ "update",
66
+ "delete",
67
+ ]);
68
+ export const transactionPiiAccessOutcomeEnum = pgEnum("transaction_pii_access_outcome", [
69
+ "allowed",
70
+ "denied",
71
+ ]);
72
+ export const orderTermTypeEnum = pgEnum("order_term_type", [
73
+ "terms_and_conditions",
74
+ "cancellation",
75
+ "guarantee",
76
+ "payment",
77
+ "pricing",
78
+ "commission",
79
+ "other",
80
+ ]);
81
+ export const orderTermAcceptanceStatusEnum = pgEnum("order_term_acceptance_status", [
82
+ "not_required",
83
+ "pending",
84
+ "accepted",
85
+ "declined",
86
+ ]);
87
+ export const offers = pgTable("offers", {
88
+ id: typeId("offers"),
89
+ offerNumber: text("offer_number").notNull().unique(),
90
+ title: text("title").notNull(),
91
+ status: offerStatusEnum("status").notNull().default("draft"),
92
+ personId: text("person_id"),
93
+ organizationId: text("organization_id"),
94
+ opportunityId: text("opportunity_id"),
95
+ quoteId: text("quote_id"),
96
+ marketId: text("market_id"),
97
+ sourceChannelId: text("source_channel_id"),
98
+ currency: text("currency").notNull(),
99
+ baseCurrency: text("base_currency"),
100
+ fxRateSetId: text("fx_rate_set_id"),
101
+ subtotalAmountCents: integer("subtotal_amount_cents").notNull().default(0),
102
+ taxAmountCents: integer("tax_amount_cents").notNull().default(0),
103
+ feeAmountCents: integer("fee_amount_cents").notNull().default(0),
104
+ totalAmountCents: integer("total_amount_cents").notNull().default(0),
105
+ costAmountCents: integer("cost_amount_cents").notNull().default(0),
106
+ validFrom: date("valid_from"),
107
+ validUntil: date("valid_until"),
108
+ sentAt: timestamp("sent_at", { withTimezone: true }),
109
+ acceptedAt: timestamp("accepted_at", { withTimezone: true }),
110
+ convertedAt: timestamp("converted_at", { withTimezone: true }),
111
+ notes: text("notes"),
112
+ metadata: jsonb("metadata"),
113
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
114
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
115
+ }, (table) => [
116
+ index("idx_offers_status").on(table.status),
117
+ index("idx_offers_person").on(table.personId),
118
+ index("idx_offers_organization").on(table.organizationId),
119
+ index("idx_offers_opportunity").on(table.opportunityId),
120
+ index("idx_offers_quote").on(table.quoteId),
121
+ index("idx_offers_market").on(table.marketId),
122
+ index("idx_offers_channel").on(table.sourceChannelId),
123
+ index("idx_offers_fx_rate_set").on(table.fxRateSetId),
124
+ index("idx_offers_valid_until").on(table.validUntil),
125
+ ]);
126
+ export const offerParticipants = pgTable("offer_participants", {
127
+ id: typeId("offer_participants"),
128
+ offerId: typeIdRef("offer_id")
129
+ .notNull()
130
+ .references(() => offers.id, { onDelete: "cascade" }),
131
+ personId: text("person_id"),
132
+ participantType: transactionParticipantTypeEnum("participant_type")
133
+ .notNull()
134
+ .default("traveler"),
135
+ travelerCategory: transactionTravelerCategoryEnum("traveler_category"),
136
+ firstName: text("first_name").notNull(),
137
+ lastName: text("last_name").notNull(),
138
+ email: text("email"),
139
+ phone: text("phone"),
140
+ preferredLanguage: text("preferred_language"),
141
+ identityEncrypted: jsonb("identity_encrypted").$type(),
142
+ isPrimary: boolean("is_primary").notNull().default(false),
143
+ notes: text("notes"),
144
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
145
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
146
+ }, (table) => [
147
+ index("idx_offer_participants_offer").on(table.offerId),
148
+ index("idx_offer_participants_person").on(table.personId),
149
+ index("idx_offer_participants_type").on(table.participantType),
150
+ ]);
151
+ export const offerItems = pgTable("offer_items", {
152
+ id: typeId("offer_items"),
153
+ offerId: typeIdRef("offer_id")
154
+ .notNull()
155
+ .references(() => offers.id, { onDelete: "cascade" }),
156
+ productId: text("product_id"),
157
+ optionId: text("option_id"),
158
+ unitId: text("unit_id"),
159
+ slotId: text("slot_id"),
160
+ title: text("title").notNull(),
161
+ description: text("description"),
162
+ itemType: transactionItemTypeEnum("item_type").notNull().default("unit"),
163
+ status: transactionItemStatusEnum("status").notNull().default("draft"),
164
+ serviceDate: date("service_date"),
165
+ startsAt: timestamp("starts_at", { withTimezone: true }),
166
+ endsAt: timestamp("ends_at", { withTimezone: true }),
167
+ quantity: integer("quantity").notNull().default(1),
168
+ sellCurrency: text("sell_currency").notNull(),
169
+ unitSellAmountCents: integer("unit_sell_amount_cents"),
170
+ totalSellAmountCents: integer("total_sell_amount_cents"),
171
+ taxAmountCents: integer("tax_amount_cents"),
172
+ feeAmountCents: integer("fee_amount_cents"),
173
+ costCurrency: text("cost_currency"),
174
+ unitCostAmountCents: integer("unit_cost_amount_cents"),
175
+ totalCostAmountCents: integer("total_cost_amount_cents"),
176
+ notes: text("notes"),
177
+ metadata: jsonb("metadata"),
178
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
179
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
180
+ }, (table) => [
181
+ index("idx_offer_items_offer").on(table.offerId),
182
+ index("idx_offer_items_product").on(table.productId),
183
+ index("idx_offer_items_option").on(table.optionId),
184
+ index("idx_offer_items_unit").on(table.unitId),
185
+ index("idx_offer_items_slot").on(table.slotId),
186
+ index("idx_offer_items_status").on(table.status),
187
+ ]);
188
+ export const offerItemParticipants = pgTable("offer_item_participants", {
189
+ id: typeId("offer_item_participants"),
190
+ offerItemId: typeIdRef("offer_item_id")
191
+ .notNull()
192
+ .references(() => offerItems.id, { onDelete: "cascade" }),
193
+ participantId: typeIdRef("participant_id")
194
+ .notNull()
195
+ .references(() => offerParticipants.id, { onDelete: "cascade" }),
196
+ role: transactionItemParticipantRoleEnum("role").notNull().default("traveler"),
197
+ isPrimary: boolean("is_primary").notNull().default(false),
198
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
199
+ }, (table) => [
200
+ index("idx_offer_item_participants_item").on(table.offerItemId),
201
+ index("idx_offer_item_participants_participant").on(table.participantId),
202
+ uniqueIndex("uidx_offer_item_participants").on(table.offerItemId, table.participantId),
203
+ ]);
204
+ export const orders = pgTable("orders", {
205
+ id: typeId("orders"),
206
+ orderNumber: text("order_number").notNull().unique(),
207
+ offerId: typeIdRef("offer_id").references(() => offers.id, { onDelete: "set null" }),
208
+ title: text("title").notNull(),
209
+ status: orderStatusEnum("status").notNull().default("draft"),
210
+ personId: text("person_id"),
211
+ organizationId: text("organization_id"),
212
+ opportunityId: text("opportunity_id"),
213
+ quoteId: text("quote_id"),
214
+ marketId: text("market_id"),
215
+ sourceChannelId: text("source_channel_id"),
216
+ currency: text("currency").notNull(),
217
+ baseCurrency: text("base_currency"),
218
+ fxRateSetId: text("fx_rate_set_id"),
219
+ subtotalAmountCents: integer("subtotal_amount_cents").notNull().default(0),
220
+ taxAmountCents: integer("tax_amount_cents").notNull().default(0),
221
+ feeAmountCents: integer("fee_amount_cents").notNull().default(0),
222
+ totalAmountCents: integer("total_amount_cents").notNull().default(0),
223
+ costAmountCents: integer("cost_amount_cents").notNull().default(0),
224
+ orderedAt: timestamp("ordered_at", { withTimezone: true }),
225
+ confirmedAt: timestamp("confirmed_at", { withTimezone: true }),
226
+ cancelledAt: timestamp("cancelled_at", { withTimezone: true }),
227
+ expiresAt: timestamp("expires_at", { withTimezone: true }),
228
+ notes: text("notes"),
229
+ metadata: jsonb("metadata"),
230
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
231
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
232
+ }, (table) => [
233
+ index("idx_orders_offer").on(table.offerId),
234
+ index("idx_orders_status").on(table.status),
235
+ index("idx_orders_person").on(table.personId),
236
+ index("idx_orders_organization").on(table.organizationId),
237
+ index("idx_orders_opportunity").on(table.opportunityId),
238
+ index("idx_orders_quote").on(table.quoteId),
239
+ index("idx_orders_market").on(table.marketId),
240
+ index("idx_orders_channel").on(table.sourceChannelId),
241
+ index("idx_orders_fx_rate_set").on(table.fxRateSetId),
242
+ ]);
243
+ export const orderParticipants = pgTable("order_participants", {
244
+ id: typeId("order_participants"),
245
+ orderId: typeIdRef("order_id")
246
+ .notNull()
247
+ .references(() => orders.id, { onDelete: "cascade" }),
248
+ personId: text("person_id"),
249
+ participantType: transactionParticipantTypeEnum("participant_type")
250
+ .notNull()
251
+ .default("traveler"),
252
+ travelerCategory: transactionTravelerCategoryEnum("traveler_category"),
253
+ firstName: text("first_name").notNull(),
254
+ lastName: text("last_name").notNull(),
255
+ email: text("email"),
256
+ phone: text("phone"),
257
+ preferredLanguage: text("preferred_language"),
258
+ identityEncrypted: jsonb("identity_encrypted").$type(),
259
+ isPrimary: boolean("is_primary").notNull().default(false),
260
+ notes: text("notes"),
261
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
262
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
263
+ }, (table) => [
264
+ index("idx_order_participants_order").on(table.orderId),
265
+ index("idx_order_participants_person").on(table.personId),
266
+ index("idx_order_participants_type").on(table.participantType),
267
+ ]);
268
+ export const orderItems = pgTable("order_items", {
269
+ id: typeId("order_items"),
270
+ orderId: typeIdRef("order_id")
271
+ .notNull()
272
+ .references(() => orders.id, { onDelete: "cascade" }),
273
+ offerItemId: typeIdRef("offer_item_id").references(() => offerItems.id, {
274
+ onDelete: "set null",
275
+ }),
276
+ productId: text("product_id"),
277
+ optionId: text("option_id"),
278
+ unitId: text("unit_id"),
279
+ slotId: text("slot_id"),
280
+ title: text("title").notNull(),
281
+ description: text("description"),
282
+ itemType: transactionItemTypeEnum("item_type").notNull().default("unit"),
283
+ status: transactionItemStatusEnum("status").notNull().default("draft"),
284
+ serviceDate: date("service_date"),
285
+ startsAt: timestamp("starts_at", { withTimezone: true }),
286
+ endsAt: timestamp("ends_at", { withTimezone: true }),
287
+ quantity: integer("quantity").notNull().default(1),
288
+ sellCurrency: text("sell_currency").notNull(),
289
+ unitSellAmountCents: integer("unit_sell_amount_cents"),
290
+ totalSellAmountCents: integer("total_sell_amount_cents"),
291
+ taxAmountCents: integer("tax_amount_cents"),
292
+ feeAmountCents: integer("fee_amount_cents"),
293
+ costCurrency: text("cost_currency"),
294
+ unitCostAmountCents: integer("unit_cost_amount_cents"),
295
+ totalCostAmountCents: integer("total_cost_amount_cents"),
296
+ notes: text("notes"),
297
+ metadata: jsonb("metadata"),
298
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
299
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
300
+ }, (table) => [
301
+ index("idx_order_items_order").on(table.orderId),
302
+ index("idx_order_items_offer_item").on(table.offerItemId),
303
+ index("idx_order_items_product").on(table.productId),
304
+ index("idx_order_items_option").on(table.optionId),
305
+ index("idx_order_items_unit").on(table.unitId),
306
+ index("idx_order_items_slot").on(table.slotId),
307
+ index("idx_order_items_status").on(table.status),
308
+ ]);
309
+ export const orderItemParticipants = pgTable("order_item_participants", {
310
+ id: typeId("order_item_participants"),
311
+ orderItemId: typeIdRef("order_item_id")
312
+ .notNull()
313
+ .references(() => orderItems.id, { onDelete: "cascade" }),
314
+ participantId: typeIdRef("participant_id")
315
+ .notNull()
316
+ .references(() => orderParticipants.id, { onDelete: "cascade" }),
317
+ role: transactionItemParticipantRoleEnum("role").notNull().default("traveler"),
318
+ isPrimary: boolean("is_primary").notNull().default(false),
319
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
320
+ }, (table) => [
321
+ index("idx_order_item_participants_item").on(table.orderItemId),
322
+ index("idx_order_item_participants_participant").on(table.participantId),
323
+ uniqueIndex("uidx_order_item_participants").on(table.orderItemId, table.participantId),
324
+ ]);
325
+ export const orderTerms = pgTable("order_terms", {
326
+ id: typeId("order_terms"),
327
+ offerId: typeIdRef("offer_id").references(() => offers.id, { onDelete: "cascade" }),
328
+ orderId: typeIdRef("order_id").references(() => orders.id, { onDelete: "cascade" }),
329
+ termType: orderTermTypeEnum("term_type").notNull().default("terms_and_conditions"),
330
+ title: text("title").notNull(),
331
+ body: text("body").notNull(),
332
+ language: text("language"),
333
+ required: boolean("required").notNull().default(true),
334
+ sortOrder: integer("sort_order").notNull().default(0),
335
+ acceptanceStatus: orderTermAcceptanceStatusEnum("acceptance_status")
336
+ .notNull()
337
+ .default("pending"),
338
+ acceptedAt: timestamp("accepted_at", { withTimezone: true }),
339
+ acceptedBy: text("accepted_by"),
340
+ metadata: jsonb("metadata"),
341
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
342
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
343
+ }, (table) => [
344
+ index("idx_order_terms_offer").on(table.offerId),
345
+ index("idx_order_terms_order").on(table.orderId),
346
+ index("idx_order_terms_type").on(table.termType),
347
+ index("idx_order_terms_acceptance").on(table.acceptanceStatus),
348
+ ]);
349
+ export const transactionPiiAccessLog = pgTable("transaction_pii_access_log", {
350
+ id: typeId("transaction_pii_access_log"),
351
+ participantKind: text("participant_kind").notNull(),
352
+ parentId: text("parent_id"),
353
+ participantId: text("participant_id"),
354
+ actorId: text("actor_id"),
355
+ actorType: text("actor_type"),
356
+ callerType: text("caller_type"),
357
+ action: transactionPiiAccessActionEnum("action").notNull(),
358
+ outcome: transactionPiiAccessOutcomeEnum("outcome").notNull(),
359
+ reason: text("reason"),
360
+ metadata: jsonb("metadata").$type(),
361
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
362
+ }, (table) => [
363
+ index("idx_transaction_pii_access_log_parent").on(table.parentId),
364
+ index("idx_transaction_pii_access_log_participant").on(table.participantId),
365
+ index("idx_transaction_pii_access_log_actor").on(table.actorId),
366
+ index("idx_transaction_pii_access_log_created_at").on(table.createdAt),
367
+ ]);
368
+ export const offersRelations = relations(offers, ({ many }) => ({
369
+ participants: many(offerParticipants),
370
+ items: many(offerItems),
371
+ orders: many(orders),
372
+ terms: many(orderTerms),
373
+ }));
374
+ export const offerParticipantsRelations = relations(offerParticipants, ({ one, many }) => ({
375
+ offer: one(offers, { fields: [offerParticipants.offerId], references: [offers.id] }),
376
+ itemLinks: many(offerItemParticipants),
377
+ }));
378
+ export const offerItemsRelations = relations(offerItems, ({ one, many }) => ({
379
+ offer: one(offers, { fields: [offerItems.offerId], references: [offers.id] }),
380
+ participants: many(offerItemParticipants),
381
+ }));
382
+ export const offerItemParticipantsRelations = relations(offerItemParticipants, ({ one }) => ({
383
+ offerItem: one(offerItems, {
384
+ fields: [offerItemParticipants.offerItemId],
385
+ references: [offerItems.id],
386
+ }),
387
+ participant: one(offerParticipants, {
388
+ fields: [offerItemParticipants.participantId],
389
+ references: [offerParticipants.id],
390
+ }),
391
+ }));
392
+ export const ordersRelations = relations(orders, ({ one, many }) => ({
393
+ offer: one(offers, { fields: [orders.offerId], references: [offers.id] }),
394
+ participants: many(orderParticipants),
395
+ items: many(orderItems),
396
+ terms: many(orderTerms),
397
+ }));
398
+ export const orderParticipantsRelations = relations(orderParticipants, ({ one, many }) => ({
399
+ order: one(orders, { fields: [orderParticipants.orderId], references: [orders.id] }),
400
+ itemLinks: many(orderItemParticipants),
401
+ }));
402
+ export const orderItemsRelations = relations(orderItems, ({ one, many }) => ({
403
+ order: one(orders, { fields: [orderItems.orderId], references: [orders.id] }),
404
+ offerItem: one(offerItems, { fields: [orderItems.offerItemId], references: [offerItems.id] }),
405
+ participants: many(orderItemParticipants),
406
+ }));
407
+ export const orderItemParticipantsRelations = relations(orderItemParticipants, ({ one }) => ({
408
+ orderItem: one(orderItems, {
409
+ fields: [orderItemParticipants.orderItemId],
410
+ references: [orderItems.id],
411
+ }),
412
+ participant: one(orderParticipants, {
413
+ fields: [orderItemParticipants.participantId],
414
+ references: [orderParticipants.id],
415
+ }),
416
+ }));
417
+ export const orderTermsRelations = relations(orderTerms, ({ one }) => ({
418
+ offer: one(offers, { fields: [orderTerms.offerId], references: [offers.id] }),
419
+ order: one(orders, { fields: [orderTerms.orderId], references: [orders.id] }),
420
+ }));