@updraft-solutions/mcrit-sdk 0.1.0 → 0.2.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.
@@ -3,6 +3,7 @@ import {
3
3
  BaseModel,
4
4
  companySchema,
5
5
  contactAttributeSchema,
6
+ mediaCollection,
6
7
  mediaSchema,
7
8
  userSchema,
8
9
  zContactDTO,
@@ -19,11 +20,24 @@ export const baseMembershipSchema = z.object({
19
20
  company_id: z.number(),
20
21
  company: companySchema.nullable().optional(),
21
22
  name: z.string(),
23
+ phone: z.string().nullable().optional(),
22
24
  status: z.string(),
23
25
  instructor: z.boolean(),
24
26
  admin: z.boolean(),
25
27
  accountant: z.boolean(),
26
28
  student: z.boolean(),
29
+ content_creator: z.boolean(),
30
+ charter_client: z.boolean(),
31
+ roles: z
32
+ .array(
33
+ z
34
+ .object({
35
+ id: z.number(),
36
+ name: z.string(),
37
+ })
38
+ .passthrough(),
39
+ )
40
+ .optional(),
27
41
  created_at: z.string(),
28
42
  updated_at: z.string(),
29
43
  can: z
@@ -105,6 +119,7 @@ export const courseFeeSchema = feeSchema.extend({
105
119
  count: z.number().optional(),
106
120
  variant: z.string().optional(),
107
121
  is_optional: z.boolean().optional(),
122
+ is_initial_payment: z.boolean().optional(),
108
123
  });
109
124
 
110
125
  export const airplaneSchema = BaseModel.extend({
@@ -113,20 +128,23 @@ export const airplaneSchema = BaseModel.extend({
113
128
  company_id: z.number(),
114
129
  registration: z.string(),
115
130
  model: z.string(),
116
- media: z
117
- .object({
118
- avatar: mediaSchema.nullable().optional(),
119
- header: mediaSchema.nullable().optional(),
120
- images: z.array(mediaSchema).nullable().optional(),
121
- documents: z.array(mediaSchema).nullable().optional(),
122
- })
123
- .nullable()
124
- .optional()
125
- .optional(),
131
+ media: mediaCollection.optional(),
126
132
  fee: feeSchema.optional(),
127
133
  booking_fee: feeSchema.optional(),
128
134
  hasFavorited: z.boolean().optional(),
129
135
  homebase_id: z.number().nullable().optional(),
136
+ hangar_location_map_feature_id: z.number().nullable().optional(),
137
+ parking_lng: z.number().nullable().optional(),
138
+ parking_lat: z.number().nullable().optional(),
139
+ hangar: z
140
+ .object({
141
+ id: z.number(),
142
+ name: z.string().nullable(),
143
+ kind: z.string(),
144
+ location_map_id: z.number(),
145
+ })
146
+ .nullable()
147
+ .optional(),
130
148
  description: z.string().optional(),
131
149
  capacity: z.number().optional(),
132
150
  manufacturer: z.string().optional(),
@@ -142,7 +160,7 @@ export const airplaneSchema = BaseModel.extend({
142
160
  viewMaintenanceEvents: zNullableBool,
143
161
  createMaintenanceEvents: zNullableBool,
144
162
  createBooking: zNullableBool,
145
- manageAirplanePermissions: zNullableBool,
163
+ createAirplanePermissions: zNullableBool,
146
164
  }),
147
165
  });
148
166
 
@@ -338,11 +356,9 @@ export const bookingSchema = BaseModel.extend({
338
356
  ifr: z.boolean().default(false),
339
357
  airplane_id: z.number(),
340
358
  author: userSchema.optional(),
341
- attendants: z.array(userSchema).optional(),
342
359
  company_id: z.number(),
343
360
  company: companySchema.optional(),
344
361
  airplane: airplaneSchema.optional(),
345
- attendant_ids: z.array(z.number()).optional(),
346
362
  etdZ: z.string(),
347
363
  etaZ: z.string(),
348
364
  duration_minutes: z.number().optional(),
@@ -353,6 +369,28 @@ export const bookingSchema = BaseModel.extend({
353
369
  next_booking_id: z.number().nullable().optional(),
354
370
  previous_booking_id: z.number().nullable().optional(),
355
371
  maintenance: z.number().optional(),
372
+ is_solo: z.boolean().optional().default(false),
373
+ course_enrollment_id: z.number().nullable().optional(),
374
+ // Minimal linked enrollment, present on booking show/store/update payloads.
375
+ // Used by the form prefill registry to derive the J2 Flugauftrag course.
376
+ course_enrollment: z
377
+ .object({
378
+ id: z.number(),
379
+ course_id: z.number().nullable().optional(),
380
+ })
381
+ .nullable()
382
+ .optional(),
383
+ crew_assignments: z
384
+ .array(
385
+ z.object({
386
+ id: z.number().optional(),
387
+ membership_id: z.number(),
388
+ role: z.string(),
389
+ is_pic: z.boolean().optional(),
390
+ membership: z.any().optional(),
391
+ }),
392
+ )
393
+ .optional(),
356
394
  contact: zContactDTO.optional(),
357
395
  remarks: z.string().optional(),
358
396
  can: z
@@ -400,11 +438,22 @@ export const documentSchema = z.object({
400
438
  .optional(),
401
439
  });
402
440
 
441
+ // Post merge-phase-3a a requirement references a FormTemplate
442
+ // (`form_template_id` + nested `form_template`) instead of a DocumentType
443
+ // FQCN. Schema NAMES keep the `document*` prefix, matching the backend's
444
+ // kept `documentRequirementGroups` route names (the legacy document domain
445
+ // itself was deleted in merge Phase 4).
403
446
  export const documentRequirement = z.object({
404
447
  id: z.number(),
405
- document_requirement_group_id: z.number(),
406
- document_type_class: z.string(),
407
- document_type: documentType.optional(),
448
+ form_requirement_group_id: z.number(),
449
+ form_template_id: z.number(),
450
+ form_template: z
451
+ .object({
452
+ id: z.number(),
453
+ name: z.string(),
454
+ slug: z.string().nullable().optional(),
455
+ })
456
+ .optional(),
408
457
  logical_group: z.string().nullable().optional(),
409
458
  group_operator: z.enum(["AND", "OR"]).nullable().optional(),
410
459
  metadata: z
@@ -429,10 +478,10 @@ export const documentRequirementGroup = z.object({
429
478
  company_id: z.number().nullable().optional(),
430
479
  is_default_template: z.boolean().default(false),
431
480
  is_active: z.boolean().default(true),
432
- requirements: z.array(documentRequirement).optional(),
433
- documentRequirements: z.array(documentRequirement).optional(),
481
+ requirements: z.array(documentRequirement).optional(), // Backend uses 'requirements'
482
+ documentRequirements: z.array(documentRequirement).optional(), // Frontend compatibility
434
483
  group_operator: z.enum(["AND", "OR"]).default("AND"),
435
- requirements_count: z.number().optional(),
484
+ documentRequirements_count: z.number().optional(),
436
485
  assignments_count: z.number().optional(),
437
486
  created_by: z.number().nullable().optional(),
438
487
  updated_by: z.number().nullable().optional(),
@@ -451,9 +500,9 @@ export const documentRequirementGroupAssignment = z.object({
451
500
  id: z.number(),
452
501
  assignable_type: z.string(),
453
502
  assignable_id: z.number(),
454
- document_requirement_group_id: z.number(),
503
+ requirement_group_id: z.number(),
455
504
  requirement_group: documentRequirementGroup.optional(),
456
- requirementGroup: documentRequirementGroup.optional(),
505
+ requirementGroup: documentRequirementGroup.optional(), // Frontend compatibility
457
506
  created_at: z.string(),
458
507
  updated_at: z.string(),
459
508
  });
@@ -574,11 +623,21 @@ export const flightLogSchema = z.object({
574
623
  etdZ: z.string(),
575
624
  etaZ: z.string(),
576
625
  duration_minutes: z.number(),
577
- crew: z.array(z.any()).nullable().optional(),
578
- attendants: z.array(z.any()).nullable().optional(),
626
+ crew_assignments: z
627
+ .array(
628
+ z.object({
629
+ id: z.number().optional(),
630
+ membership_id: z.number(),
631
+ role: z.string(),
632
+ is_pic: z.boolean().optional(),
633
+ membership: z.any().optional(),
634
+ }),
635
+ )
636
+ .optional(),
579
637
  total_landings: z.number().nullable().optional(),
580
638
  full_stop_landings: z.number().nullable().optional(),
581
639
  touch_and_gos: z.number().default(0),
640
+ low_approaches: z.number().default(0),
582
641
  flight_rule: z.string().nullable().optional(),
583
642
  flight_time_type: z.string().nullable().optional(),
584
643
  dep_airport_id: z.number().nullable().optional(),
@@ -632,6 +691,7 @@ export const invoiceSchema = z.object({
632
691
  recipient_zip: z.string().nullable().optional(),
633
692
  recipient_state: z.string().nullable().optional(),
634
693
  recipient_country: z.string().nullable().optional(),
694
+ recipient_vat_id: z.string().nullable().optional(),
635
695
  issuer_name: z.string().nullable().optional(),
636
696
  issuer_address_street_1: z.string().nullable().optional(),
637
697
  issuer_address_street_2: z.string().nullable().optional(),
@@ -727,6 +787,21 @@ export const courseSchema = z.object({
727
787
  .optional(),
728
788
  });
729
789
 
790
+ /**
791
+ * Materialized, admin-only metrics for an enrollment — recomputed server-side
792
+ * (see m-crit-api course_enrollment_metrics). `flags` is an extensible bag of
793
+ * computed booleans (e.g. `has_solo`).
794
+ */
795
+ export const courseEnrollmentMetricsSchema = z.object({
796
+ last_flight_at: z.string().nullable(),
797
+ next_flight_at: z.string().nullable(),
798
+ total_flight_minutes: z.number().default(0),
799
+ flags: z
800
+ .record(z.string(), z.union([z.boolean(), z.number(), z.string()]))
801
+ .default({}),
802
+ calculated_at: z.string().nullable(),
803
+ });
804
+
730
805
  export const courseEnrollmentSchema = z.object({
731
806
  type: z.literal("course_enrollment").optional(),
732
807
  id: z.number(),
@@ -738,7 +813,11 @@ export const courseEnrollmentSchema = z.object({
738
813
  enrollment_date: z.string(),
739
814
  completion_date: z.string().nullable().optional(),
740
815
  progress_percentage: z.number().default(0),
816
+ milestone_count: z.number().optional(),
741
817
  comments: z.string().nullable().optional(),
818
+ initial_payment_generated: z.boolean().optional(),
819
+ initial_payment_removable: z.boolean().optional(),
820
+ metrics: courseEnrollmentMetricsSchema.optional(),
742
821
  created_at: z.string(),
743
822
  updated_at: z.string(),
744
823
  course: courseSchema.optional(),
@@ -792,6 +871,7 @@ export const addressSchema = z.object({
792
871
  state: z.string().nullable().optional(),
793
872
  country: z.string().nullable().optional(),
794
873
  additional_info: z.string().nullable().optional(),
874
+ vat_id: z.string().nullable().optional(),
795
875
  created_at: z.string(),
796
876
  updated_at: z.string(),
797
877
  });
@@ -877,21 +957,26 @@ export const settingSchema = z.object({
877
957
  export const postSchema = z.object({
878
958
  type: z.literal("post"),
879
959
  id: z.number(),
880
- postable_type: z.string(),
881
- postable_id: z.number(),
960
+ company_id: z.number(),
961
+ postable_type: z.string().nullable().optional(),
962
+ postable_id: z.number().nullable().optional(),
882
963
  author_id: z.number(),
883
964
  author: userSchema.optional(),
884
- title: z.string(),
965
+ title: z.string().nullable().optional(),
885
966
  content: z.string(),
886
- published: z.boolean().default(false),
887
- published_at: z.string().nullable().optional(),
967
+ sticky: z.boolean().default(false),
968
+ public: z.boolean().default(false),
969
+ media: mediaCollection.optional(),
888
970
  created_at: z.string(),
889
971
  updated_at: z.string(),
890
972
  can: z
891
973
  .object({
974
+ view: zNullableBool,
892
975
  update: zNullableBool,
893
976
  delete: zNullableBool,
894
- publish: zNullableBool,
977
+ setFlags: zNullableBool,
978
+ restore: zNullableBool,
979
+ forceDelete: zNullableBool,
895
980
  })
896
981
  .optional(),
897
982
  });
@@ -906,7 +991,6 @@ export const commentSchema = z.object({
906
991
  body: z.string(),
907
992
  author_id: z.number().optional(),
908
993
  author: userSchema.optional(),
909
- resolved_at: z.string().optional().nullable(),
910
994
  created_at: z.string(),
911
995
  updated_at: z.string().optional(),
912
996
  children: z.lazy((): z.ZodTypeAny => commentSchema.array()).optional(),
@@ -915,7 +999,6 @@ export const commentSchema = z.object({
915
999
  view: z.boolean().optional(),
916
1000
  update: z.boolean().optional().nullable(),
917
1001
  delete: z.boolean().optional().nullable(),
918
- resolve: z.boolean().optional(),
919
1002
  reply: z.boolean().optional(),
920
1003
  viewComments: z.boolean().optional(),
921
1004
  createComments: z.boolean().optional(),
@@ -923,6 +1006,45 @@ export const commentSchema = z.object({
923
1006
  .optional(),
924
1007
  });
925
1008
 
1009
+ // Airplane issue (aviation defect log) — matches backend AirplaneIssueResource
1010
+ export const airplaneIssueSeverityEnum = z.enum([
1011
+ "minor",
1012
+ "major",
1013
+ "grounding",
1014
+ ]);
1015
+ export const airplaneIssueStatusEnum = z.enum(["open", "deferred", "resolved"]);
1016
+
1017
+ export const airplaneIssueSchema = z.object({
1018
+ type: z.literal("airplaneIssue"),
1019
+ id: z.number(),
1020
+ airplane_id: z.number(),
1021
+ title: z.string().nullable().optional(),
1022
+ body: z.string(),
1023
+ severity: airplaneIssueSeverityEnum,
1024
+ ata_chapter: z.string().nullable().optional(),
1025
+ status: airplaneIssueStatusEnum,
1026
+ reporter: userSchema.optional(),
1027
+ resolver: userSchema.optional(),
1028
+ deferred_at: z.string().nullable().optional(),
1029
+ deferred_until: z.string().nullable().optional(),
1030
+ deferral_notes: z.string().nullable().optional(),
1031
+ resolved_at: z.string().nullable().optional(),
1032
+ resolution_notes: z.string().nullable().optional(),
1033
+ attachments: z.array(mediaSchema).optional(),
1034
+ created_at: z.string(),
1035
+ updated_at: z.string().optional(),
1036
+ can: z
1037
+ .object({
1038
+ view: z.boolean().nullable().optional(),
1039
+ update: z.boolean().nullable().optional(),
1040
+ resolve: z.boolean().nullable().optional(),
1041
+ defer: z.boolean().nullable().optional(),
1042
+ reopen: z.boolean().nullable().optional(),
1043
+ delete: z.boolean().nullable().optional(),
1044
+ })
1045
+ .optional(),
1046
+ });
1047
+
926
1048
  export const specialFlightSchema = z.object({
927
1049
  type: z.literal("specialFlight"),
928
1050
  id: z.number(),
@@ -99,6 +99,18 @@ export type Course = z.infer<typeof ModelSchemas.courseSchema>;
99
99
  export type CourseEnrollment = z.infer<
100
100
  typeof ModelSchemas.courseEnrollmentSchema
101
101
  >;
102
+ export type CourseEnrollmentMetrics = z.infer<
103
+ typeof ModelSchemas.courseEnrollmentMetricsSchema
104
+ >;
105
+
106
+ // Airplane issue (aviation defect log) Types
107
+ export type AirplaneIssue = z.infer<typeof ModelSchemas.airplaneIssueSchema>;
108
+ export type AirplaneIssueSeverity = z.infer<
109
+ typeof ModelSchemas.airplaneIssueSeverityEnum
110
+ >;
111
+ export type AirplaneIssueStatus = z.infer<
112
+ typeof ModelSchemas.airplaneIssueStatusEnum
113
+ >;
102
114
 
103
115
  // Communication and Support Types
104
116
  export type Event = z.infer<typeof ModelSchemas.eventSchema>;