@sellout/models 0.0.435 → 0.0.437

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 (61) hide show
  1. package/.dist/graphql/fragments/order.fragment.js +1 -0
  2. package/.dist/graphql/fragments/order.fragment.js.map +1 -1
  3. package/.dist/graphql/mutations/batchPrintBreakApartOrder.mutation.js +1 -0
  4. package/.dist/graphql/mutations/batchPrintBreakApartOrder.mutation.js.map +1 -1
  5. package/.dist/graphql/mutations/breakApartOrder.js +1 -0
  6. package/.dist/graphql/mutations/breakApartOrder.js.map +1 -1
  7. package/.dist/graphql/mutations/createEvent.mutation.js +1 -0
  8. package/.dist/graphql/mutations/createEvent.mutation.js.map +1 -1
  9. package/.dist/graphql/mutations/duplicateEvent.mutation.js +1 -0
  10. package/.dist/graphql/mutations/duplicateEvent.mutation.js.map +1 -1
  11. package/.dist/graphql/mutations/multipleBreakApartOrder.mutation.js +1 -0
  12. package/.dist/graphql/mutations/multipleBreakApartOrder.mutation.js.map +1 -1
  13. package/.dist/graphql/mutations/publishEvent.mutation.js +1 -0
  14. package/.dist/graphql/mutations/publishEvent.mutation.js.map +1 -1
  15. package/.dist/graphql/mutations/updateEvent.mutation.js +1 -0
  16. package/.dist/graphql/mutations/updateEvent.mutation.js.map +1 -1
  17. package/.dist/graphql/queries/event.query.js +1 -0
  18. package/.dist/graphql/queries/event.query.js.map +1 -1
  19. package/.dist/graphql/queries/order.query.js +1 -0
  20. package/.dist/graphql/queries/order.query.js.map +1 -1
  21. package/.dist/graphql/queries/orders.query.js +1 -0
  22. package/.dist/graphql/queries/orders.query.js.map +1 -1
  23. package/.dist/graphql/queries/ordersTableOptimized.query.js +2 -0
  24. package/.dist/graphql/queries/ordersTableOptimized.query.js.map +1 -1
  25. package/.dist/graphql/queries/publicEvent.query.js +1 -0
  26. package/.dist/graphql/queries/publicEvent.query.js.map +1 -1
  27. package/.dist/interfaces/IEvent.d.ts +5 -0
  28. package/.dist/interfaces/IEvent.js +6 -1
  29. package/.dist/interfaces/IEvent.js.map +1 -1
  30. package/.dist/interfaces/IScan.d.ts +1 -0
  31. package/.dist/schemas/Event.d.ts +6 -1
  32. package/.dist/schemas/Event.js +5 -0
  33. package/.dist/schemas/Event.js.map +1 -1
  34. package/.dist/schemas/Order.d.ts +8 -0
  35. package/.dist/schemas/Order.js +3 -0
  36. package/.dist/schemas/Order.js.map +1 -1
  37. package/.dist/sellout-proto.js +110 -0
  38. package/.dist/utils/EventUtil.d.ts +12 -0
  39. package/.dist/utils/EventUtil.js +88 -0
  40. package/.dist/utils/EventUtil.js.map +1 -1
  41. package/package.json +3 -3
  42. package/src/graphql/fragments/order.fragment.ts +1 -0
  43. package/src/graphql/mutations/batchPrintBreakApartOrder.mutation.ts +1 -0
  44. package/src/graphql/mutations/breakApartOrder.ts +1 -0
  45. package/src/graphql/mutations/createEvent.mutation.ts +1 -0
  46. package/src/graphql/mutations/duplicateEvent.mutation.ts +1 -0
  47. package/src/graphql/mutations/multipleBreakApartOrder.mutation.ts +1 -0
  48. package/src/graphql/mutations/publishEvent.mutation.ts +1 -0
  49. package/src/graphql/mutations/updateEvent.mutation.ts +1 -0
  50. package/src/graphql/queries/event.query.ts +1 -0
  51. package/src/graphql/queries/order.query.ts +1 -0
  52. package/src/graphql/queries/orders.query.ts +1 -0
  53. package/src/graphql/queries/ordersTableOptimized.query.ts +2 -0
  54. package/src/graphql/queries/publicEvent.query.ts +1 -0
  55. package/src/interfaces/IEvent.ts +6 -0
  56. package/src/interfaces/IScan.ts +1 -0
  57. package/src/proto/event.proto +3 -0
  58. package/src/proto/order.proto +2 -0
  59. package/src/schemas/Event.ts +6 -1
  60. package/src/schemas/Order.ts +3 -0
  61. package/src/utils/EventUtil.ts +114 -0
@@ -49,6 +49,7 @@ Order.fragments = {
49
49
  scannedAt
50
50
  scannedBy
51
51
  startsAt
52
+ endsAt
52
53
  scannerName
53
54
  }
54
55
  parentTicketId
@@ -18,6 +18,7 @@ mutation batchPrintBreakApartOrder($orderId: [String]!) {
18
18
  event {
19
19
  _id
20
20
  isMultipleDays
21
+ multiDayEntry
21
22
  name
22
23
  subtitle
23
24
  performances {
@@ -8,6 +8,7 @@ const mutation = gql`
8
8
  event {
9
9
  _id
10
10
  isMultipleDays
11
+ multiDayEntry
11
12
  name
12
13
  subtitle
13
14
  performances {
@@ -28,6 +28,7 @@ const mutation = gql`
28
28
  physicalDeliveryInstructions
29
29
  ticketDeliveryType
30
30
  isMultipleDays
31
+ multiDayEntry
31
32
  totalDays
32
33
  cancel
33
34
  sendQRCode
@@ -25,6 +25,7 @@ const mutation = gql`
25
25
  age
26
26
  taxDeduction
27
27
  isMultipleDays
28
+ multiDayEntry
28
29
  totalDays
29
30
  cancel
30
31
  sendQRCode
@@ -18,6 +18,7 @@ mutation multipleBreakApartOrder($orderId: [String]!) {
18
18
  event {
19
19
  _id
20
20
  isMultipleDays
21
+ multiDayEntry
21
22
  name
22
23
  subtitle
23
24
  performances {
@@ -34,6 +34,7 @@ const mutation = gql`
34
34
  seatingChartKey
35
35
  age
36
36
  isMultipleDays
37
+ multiDayEntry
37
38
  totalDays
38
39
  cancel
39
40
  sendQRCode
@@ -25,6 +25,7 @@ const mutation = gql`
25
25
  seatingChartKey
26
26
  age
27
27
  isMultipleDays
28
+ multiDayEntry
28
29
  totalDays
29
30
  cancel
30
31
  sendQRCode
@@ -25,6 +25,7 @@ const query = gql`
25
25
  seatingChartKey
26
26
  age
27
27
  isMultipleDays
28
+ multiDayEntry
28
29
  totalDays
29
30
  cancel
30
31
  sendQRCode
@@ -53,6 +53,7 @@ const query = gql`
53
53
  subtitle
54
54
  seasonId
55
55
  isMultipleDays
56
+ multiDayEntry
56
57
  posterImageUrl {
57
58
  original
58
59
  medium
@@ -30,6 +30,7 @@ const query = gql`
30
30
  small
31
31
  }
32
32
  isMultipleDays
33
+ multiDayEntry
33
34
  schedule {
34
35
  startsAt
35
36
  endsAt
@@ -21,6 +21,7 @@ const query = gql`
21
21
  name
22
22
  subtitle
23
23
  isMultipleDays
24
+ multiDayEntry
24
25
  posterImageUrl {
25
26
  original
26
27
  medium
@@ -62,6 +63,7 @@ const query = gql`
62
63
  scan {
63
64
  scanned
64
65
  startsAt
66
+ endsAt
65
67
  }
66
68
  }
67
69
  upgrades {
@@ -26,6 +26,7 @@ const query = gql`
26
26
  seatingPublicKey
27
27
  age
28
28
  isMultipleDays
29
+ multiDayEntry
29
30
  totalDays
30
31
  taxDeduction
31
32
  sendQRCode
@@ -52,6 +52,11 @@ export enum MultidayEventDates {
52
52
  DaySeven = "7"
53
53
 
54
54
  }
55
+ export enum MultiDayEntryEnum {
56
+ Single = "Single",
57
+ Daily = "Daily",
58
+ }
59
+
55
60
  export enum EventTicketDelivery {
56
61
  Digital = "Digital only",
57
62
  Physical = "Will-call only",
@@ -112,6 +117,7 @@ export default interface IEvent {
112
117
  salesBeginImmediately?: boolean;
113
118
  isMultipleDays?: boolean;
114
119
  totalDays?: MultidayEventDates;
120
+ multiDayEntry?: MultiDayEntryEnum;
115
121
  cancel?: boolean;
116
122
  fees: IFee[];
117
123
  seasonId?: string;
@@ -3,5 +3,6 @@ export default interface IScan {
3
3
  scannedAt: number;
4
4
  scannedBy: string;
5
5
  startsAt?: number;
6
+ endsAt?: number;
6
7
  scannerName?: string;
7
8
  }
@@ -56,6 +56,7 @@ message Event {
56
56
  repeated string additionalPhotos = 48;
57
57
  repeated string tagIds = 49;
58
58
  repeated GuestListEntry guestList = 50;
59
+ string multiDayEntry = 51;
59
60
  }
60
61
 
61
62
  message PublicEvent {
@@ -999,6 +1000,8 @@ message MobileCheckInEvent {
999
1000
  string userAgreement = 9;
1000
1001
  repeated EventCustomFields customFields = 10;
1001
1002
  repeated MobileCheckInGuestListEntry guestList = 11;
1003
+ bool isMultipleDays = 12;
1004
+ string multiDayEntry = 13;
1002
1005
  }
1003
1006
 
1004
1007
  message MobileCheckInHoldTicketRequest {
@@ -162,6 +162,7 @@ message Scan {
162
162
  string scannedBy = 2;
163
163
  int32 startsAt = 3;
164
164
  string scannerName = 4;
165
+ int32 endsAt = 5;
165
166
  }
166
167
 
167
168
  message Refund {
@@ -1066,6 +1067,7 @@ message MobileCheckInScan {
1066
1067
  bool scanned = 1;
1067
1068
  int32 scannedAt = 2;
1068
1069
  int32 startsAt = 3;
1070
+ int32 endsAt = 4;
1069
1071
  }
1070
1072
 
1071
1073
  message MobileCheckInTicket {
@@ -1,5 +1,5 @@
1
1
  import shortid from 'shortid';
2
- import { EventAgeEnum, SendQRCodeEnum, EventProcessAsEnum, EventTicketDelivery } from '../interfaces/IEvent';
2
+ import { EventAgeEnum, SendQRCodeEnum, EventProcessAsEnum, EventTicketDelivery, MultiDayEntryEnum } from '../interfaces/IEvent';
3
3
  import { UpgradeTypeComplimentaryWithEnum } from "../interfaces/IEventUpgrade";
4
4
  import Address from './Address';
5
5
  import Metrics from './Metrics';
@@ -642,6 +642,11 @@ export default {
642
642
  required: true,
643
643
  default: false
644
644
  },
645
+ multiDayEntry: {
646
+ type: String,
647
+ required: false,
648
+ default: MultiDayEntryEnum.Daily
649
+ },
645
650
  age: {
646
651
  type: String,
647
652
  required: true,
@@ -64,6 +64,9 @@ const Scan = {
64
64
  }, startsAt: {
65
65
  type: Number,
66
66
  required: false,
67
+ }, endsAt: {
68
+ type: Number,
69
+ required: false,
67
70
  }
68
71
  };
69
72
  const Fees = {
@@ -5,6 +5,7 @@ import IRefundModal from "../interfaces/IRefundModal";
5
5
  import IEvent, {
6
6
  EventProcessAsEnum,
7
7
  EventTypeEnum,
8
+ MultiDayEntryEnum,
8
9
  } from "../interfaces/IEvent";
9
10
  import { CustomFieldTypeEnum } from "../enums/CustomFieldTypeEnum";
10
11
  import IOrderCustomField from "../interfaces/IOrderCustomField";
@@ -20,6 +21,7 @@ import IGuestListEntry from "../interfaces/IGuestListEntry";
20
21
  import IGuestListCheckIn from "../interfaces/IGuestListCheckIn";
21
22
  import IGuestListSession from "../interfaces/IGuestListSession";
22
23
  import IEmailHolders from "../interfaces/IEmailHolders";
24
+ import IScan from "../interfaces/IScan";
23
25
 
24
26
  export default {
25
27
  /****************************************************************************************
@@ -255,6 +257,46 @@ export default {
255
257
  },
256
258
 
257
259
  guestListSessions(event: IEvent): IGuestListSession[] {
260
+ const sessions = this.scheduleSessions(event);
261
+
262
+ if (!this.isSingleEntry(event) || sessions.length < 2) return sessions;
263
+
264
+ // Single entry: one check-in covers the whole event, the same as tickets,
265
+ // so the guest is checked in once and stays checked in for the rest.
266
+ return [this.eventSession(event) as IGuestListSession];
267
+ },
268
+
269
+ // The whole event as one session: the first day's start to the latest end.
270
+ eventSession(event: IEvent): IGuestListSession | null {
271
+ const sessions = this.scheduleSessions(event);
272
+
273
+ if (!sessions.length) return null;
274
+
275
+ const endsAt = sessions
276
+ .map((session) => session.endsAt)
277
+ .filter((value): value is number => Boolean(value));
278
+
279
+ return {
280
+ startsAt: sessions[0].startsAt,
281
+ endsAt: endsAt.length ? Math.max(...endsAt) : null,
282
+ };
283
+ },
284
+
285
+ // When single-entry check-in opens: doors on the first day, or the first
286
+ // start time when no doors time is set.
287
+ eventCheckInOpensAt(event: IEvent): number | null {
288
+ const session = this.eventSession(event);
289
+
290
+ if (!session) return null;
291
+
292
+ const doorsAt = (event?.performances?.[0]?.schedule ?? [])
293
+ .filter((day) => day?.startsAt === session.startsAt && day?.doorsAt)
294
+ .map((day) => day.doorsAt as number);
295
+
296
+ return Math.min(session.startsAt, ...doorsAt);
297
+ },
298
+
299
+ scheduleSessions(event: IEvent): IGuestListSession[] {
258
300
  const scheduled = (event?.performances?.[0]?.schedule ?? [])
259
301
  .filter((day) => Boolean(day?.startsAt))
260
302
  .map((day) => ({
@@ -291,6 +333,67 @@ export default {
291
333
  : [];
292
334
  },
293
335
 
336
+ /****************************************************************************************
337
+ * Multi-day Entry
338
+ ****************************************************************************************/
339
+
340
+ isSingleEntry(event: IEvent): boolean {
341
+ return (
342
+ Boolean(event?.isMultipleDays) &&
343
+ event?.multiDayEntry === MultiDayEntryEnum.Single
344
+ );
345
+ },
346
+
347
+ // Daily: one scan per day the ticket is valid for. Single: one scan for the
348
+ // whole event, whatever days the ticket covers. The client treats it as a
349
+ // registration-desk check-in, open from the first day to the last.
350
+ ticketScans(event: IEvent, dayIds: string[] = []): IScan[] {
351
+ const unscanned = { scanned: false, scannedAt: 0, scannedBy: "" };
352
+
353
+ if (!this.isSingleEntry(event)) {
354
+ if (!dayIds?.length) {
355
+ return [{ ...unscanned, startsAt: event?.schedule?.startsAt }];
356
+ }
357
+ return dayIds.map((day) => ({ ...unscanned, startsAt: parseInt(day) }));
358
+ }
359
+
360
+ const session = this.eventSession(event);
361
+
362
+ return [
363
+ {
364
+ ...unscanned,
365
+ startsAt:
366
+ this.eventCheckInOpensAt(event) ?? event?.schedule?.startsAt,
367
+ endsAt: session?.endsAt ?? event?.schedule?.endsAt ?? undefined,
368
+ },
369
+ ];
370
+ },
371
+
372
+ // The days a ticket gets its own entry for (day-of reminder, printed ticket):
373
+ // every day for Daily, only the event's first day for Single.
374
+ entryDays(event: IEvent, dayIds: string[] = []): string[] {
375
+ if (!this.isSingleEntry(event) || !dayIds?.length) return dayIds ?? [];
376
+ const session = this.eventSession(event);
377
+ return session ? [String(session.startsAt)] : dayIds.slice(0, 1);
378
+ },
379
+
380
+ // A daily scan is valid on its own calendar day. A single-entry scan is valid
381
+ // from doors on the first day (its startsAt) to the end of the last day.
382
+ scanIsValidOn(scan: IScan, at: number, timezone: string): boolean {
383
+ if (!scan?.startsAt) return false;
384
+
385
+ if (scan.endsAt) return scan.startsAt <= at && at <= scan.endsAt;
386
+
387
+ const day = (seconds: number) =>
388
+ Time.format(seconds, "YYYY-MM-DD", timezone);
389
+ return day(scan.startsAt) === day(at);
390
+ },
391
+
392
+ // A single-entry scan that was never used and whose window is over.
393
+ scanIsClosed(scan: IScan, at: number): boolean {
394
+ return Boolean(scan?.endsAt) && at > (scan.endsAt as number);
395
+ },
396
+
294
397
  GUEST_LIST_MAX_GROUP_SIZE: 100,
295
398
  guestListHighestNumber(
296
399
  guestList: IGuestListEntry[],
@@ -405,6 +508,17 @@ export default {
405
508
  timezone: string,
406
509
  at: number = Time.now()
407
510
  ): number | null {
511
+ // Single entry: guests check in from doors on the first day to the end of
512
+ // the last day, the same window as tickets.
513
+ if (this.isSingleEntry(event)) {
514
+ const session = this.eventSession(event);
515
+ const opensAt = this.eventCheckInOpensAt(event);
516
+
517
+ if (session?.endsAt && opensAt !== null) {
518
+ return opensAt <= at && at <= session.endsAt ? session.startsAt : null;
519
+ }
520
+ }
521
+
408
522
  const day = (seconds: number) => Time.format(seconds, "YYYY-MM-DD", timezone);
409
523
  const today = day(at);
410
524
  const sessions = this.guestListSessions(event);