@adaptware/eagles-db 0.5.39 → 0.5.41

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 (63) hide show
  1. package/client/edge.js +243 -11
  2. package/client/index-browser.js +236 -5
  3. package/client/index.d.ts +107488 -86871
  4. package/client/index.js +248 -16
  5. package/client/package.json +1 -1
  6. package/client/schema.prisma +491 -118
  7. package/client/wasm.js +243 -11
  8. package/package.json +1 -1
  9. package/prisma/schema/applications.prisma +29 -34
  10. package/prisma/schema/assessmentLibrary.prisma +2 -0
  11. package/prisma/schema/document.prisma +0 -1
  12. package/prisma/schema/evaluationPlan.prisma +9 -0
  13. package/prisma/schema/migrations/20260522120000_ongoing_evaluation_record_kind/migration.sql +25 -0
  14. package/prisma/schema/migrations/20260523120000_replace_record_kind_with_is_committed/migration.sql +24 -0
  15. package/prisma/schema/migrations/20260528120000_drop_job_description_recommendation_config/migration.sql +2 -0
  16. package/prisma/schema/migrations/20260710120000_add_resume_rendered_export_fields/migration.sql +9 -0
  17. package/prisma/schema/migrations/20260714120000_add_job_description_display_html_document/migration.sql +8 -0
  18. package/prisma/schema/migrations/20260716120000_add_offer_letters/migration.sql +183 -0
  19. package/prisma/schema/migrations/20260716140000_offer_schema_refinements/migration.sql +13 -0
  20. package/prisma/schema/migrations/20260716160000_offer_schema_hardening/migration.sql +95 -0
  21. package/prisma/schema/migrations/20260716180000_offer_letter_template_config/migration.sql +2 -0
  22. package/prisma/schema/migrations/20260716190000_add_evaluation_focus_areas/migration.sql +6 -0
  23. package/prisma/schema/migrations/20260717120000_offer_workflow_approval/migration.sql +30 -0
  24. package/prisma/schema/migrations/20260720120000_offer_letter_template_is_draft/migration.sql +5 -0
  25. package/prisma/schema/migrations/20260720140000_offer_status_split/migration.sql +51 -0
  26. package/prisma/schema/migrations/20260720140001_offer_status_split_backfill/migration.sql +37 -0
  27. package/prisma/schema/migrations/20260722120000_offer_draft_edited_html/migration.sql +13 -0
  28. package/prisma/schema/migrations/20260723150000_offer_withdraw_actor_no_show_reason/migration.sql +10 -0
  29. package/prisma/schema/migrations/20260724120000_open_job_offer_accepted_declined_counts/migration.sql +7 -0
  30. package/prisma/schema/migrations/20260811120000_add_integration_provider_razorpay/migration.sql +6 -0
  31. package/prisma/schema/migrations/20260812120000_add_billing_transactions/migration.sql +49 -0
  32. package/prisma/schema/migrations/20260812130000_drop_billing_transaction_gst_snapshots/migration.sql +3 -0
  33. package/prisma/schema/migrations/20260812180000_billing_transaction_invoice_number/migration.sql +5 -0
  34. package/prisma/schema/migrations/20260813120000_payment_webhooks_gst_refunds/migration.sql +79 -0
  35. package/prisma/schema/migrations/20260813140000_platform_gst_profiles/migration.sql +49 -0
  36. package/prisma/schema/migrations/20260813150000_rename_gst_profiles/migration.sql +53 -0
  37. package/prisma/schema/migrations/20260813160000_remove_gst_billing/migration.sql +16 -0
  38. package/prisma/schema/migrations/20260813170000_billing_licensing_unrecoverable/migration.sql +2 -0
  39. package/prisma/schema/migrations/20260813180000_billing_transaction_payment_method/migration.sql +2 -0
  40. package/prisma/schema/migrations/20260814090000_billing_transaction_purchaser_email/migration.sql +2 -0
  41. package/prisma/schema/migrations/20260816100000_billing_product_organisations/migration.sql +35 -0
  42. package/prisma/schema/migrations/20260816120000_merge_billing_product_organisations/migration.sql +25 -0
  43. package/prisma/schema/migrations/20260817120000_billing_payment_mismatch/migration.sql +7 -0
  44. package/prisma/schema/migrations/20260819120000_billing_product_prices/migration.sql +62 -0
  45. package/prisma/schema/migrations/20260819140000_billing_exchange_rates/migration.sql +25 -0
  46. package/prisma/schema/migrations/20260820120000_billing_transaction_failure_category/migration.sql +31 -0
  47. package/prisma/schema/migrations/20260820130000_backfill_billing_transaction_failure_details/migration.sql +23 -0
  48. package/prisma/schema/migrations/20260820140000_drop_billing_product_price_overrides/migration.sql +2 -0
  49. package/prisma/schema/migrations/20260821120000_drop_billing_product_and_mock_licensing/migration.sql +38 -0
  50. package/prisma/schema/migrations/20260824120000_billing_transaction_purchase_display_name/migration.sql +2 -0
  51. package/prisma/schema/migrations/20260831120000_user_communication_email/migration.sql +6 -0
  52. package/prisma/schema/migrations/20260901143000_assessment_question_bank_state/migration.sql +15 -0
  53. package/prisma/schema/migrations/20260902120000_question_category_two_values/migration.sql +16 -0
  54. package/prisma/schema/migrations/20260902143000_question_bank_item_key/migration.sql +17 -0
  55. package/prisma/schema/migrations/20260903120000_split_round_type_assessment/migration.sql +9 -0
  56. package/prisma/schema/migrations/20260904110000_restore_round_type_assessment_enum/migration.sql +5 -0
  57. package/prisma/schema/migrations/20260904120000_revert_wrong_split_assessment_round_types/migration.sql +42 -0
  58. package/prisma/schema/questions.prisma +13 -0
  59. package/prisma/.DS_Store +0 -0
  60. package/prisma/schema/.DS_Store +0 -0
  61. package/prisma/schema/migrations/.DS_Store +0 -0
  62. package/prisma/schema/migrations/20260826160000_add_application_fit_check_report_document/.DS_Store +0 -0
  63. package/prisma/schema/migrations/20260826160000_add_application_fit_check_report_document/migration.sql +0 -13
@@ -414,53 +414,49 @@ enum ApplicationOfferSubstatus {
414
414
 
415
415
  model Application {
416
416
  /// Primary key
417
- id String @id @default(uuid())
417
+ id String @id @default(uuid())
418
418
  /// Foreign keys
419
- organisation_id String
420
- candidate_id String
421
- resume_id String
422
- job_description_id String
423
- evaluation_plan_id String?
424
- recruiter_id String?
425
- source_id String?
419
+ organisation_id String
420
+ candidate_id String
421
+ resume_id String
422
+ job_description_id String
423
+ evaluation_plan_id String?
424
+ recruiter_id String?
425
+ source_id String?
426
426
  /// Data fields
427
- fit_check_score Float?
428
- applied_at DateTime @default(now())
429
- round_no Int @default(0)
430
- is_jaf_completed Boolean @default(false)
431
- proceed_to_next_round Boolean? @default(false)
432
- evaluationComment String?
427
+ fit_check_score Float?
428
+ applied_at DateTime @default(now())
429
+ round_no Int @default(0)
430
+ is_jaf_completed Boolean @default(false)
431
+ proceed_to_next_round Boolean? @default(false)
432
+ evaluationComment String?
433
433
  /// Candidate flag (orthogonal to ApplicationStatus). Latest actor/comment only.
434
- is_flagged Boolean @default(false)
435
- flag_comment String?
436
- flagged_at DateTime?
437
- flagged_by String?
438
- unflag_comment String?
439
- unflagged_at DateTime?
440
- unflagged_by String?
441
- fit_check_status FitCheckStatus?
442
- status ApplicationStatus @default(PENDING)
434
+ is_flagged Boolean @default(false)
435
+ flag_comment String?
436
+ flagged_at DateTime?
437
+ flagged_by String?
438
+ unflag_comment String?
439
+ unflagged_at DateTime?
440
+ unflagged_by String?
441
+ fit_check_status FitCheckStatus?
442
+ status ApplicationStatus @default(PENDING)
443
443
  /// Fine-grained offer-stage state. Meaningful only when status = OFFER (or was OFFER for a terminal-substatus that flipped to REJECTED / JOINED).
444
- offer_substatus ApplicationOfferSubstatus?
444
+ offer_substatus ApplicationOfferSubstatus?
445
445
  /// Audit fields
446
- created_at DateTime @default(now())
447
- updated_at DateTime @updatedAt
448
- created_by String
449
- updated_by String
450
- is_active Boolean @default(true)
451
- fit_check_report_document_id String? @unique
452
- fit_check_report_updated_flag Boolean @default(false)
453
- fit_check_report_data Json? @default("{}")
454
-
446
+ created_at DateTime @default(now())
447
+ updated_at DateTime @updatedAt
448
+ created_by String
449
+ updated_by String
450
+ is_active Boolean @default(true)
455
451
  /// Relations
456
- evaluation_plan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id])
457
- candidate User @relation(fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
458
- organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
459
- resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
460
- job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
452
+ evaluation_plan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id])
453
+ candidate User @relation(fields: [candidate_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
454
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
455
+ resume Resume @relation(fields: [resume_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
456
+ job_description JobDescription @relation(fields: [job_description_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
461
457
  fit_check FitCheck?
462
- recruiter User? @relation("ApplicationRecruiter", fields: [recruiter_id], references: [id])
463
- source Source? @relation(fields: [source_id], references: [id], onDelete: SetNull)
458
+ recruiter User? @relation("ApplicationRecruiter", fields: [recruiter_id], references: [id])
459
+ source Source? @relation(fields: [source_id], references: [id], onDelete: SetNull)
464
460
  interviews Interview[]
465
461
  assignments Assignment[]
466
462
  ongoing_evaluations OngoingEvaluation[]
@@ -470,7 +466,6 @@ model Application {
470
466
  communication_messages CommunicationMessage[]
471
467
  job_application_responses JobApplicationResponse[]
472
468
  offer Offer?
473
- fit_check_report_document Document? @relation("ApplicationFitCheckReportDocument", fields: [fit_check_report_document_id], references: [id], onDelete: SetNull)
474
469
 
475
470
  @@unique([candidate_id, job_description_id]) // Ensures candidate applies only once per job
476
471
  @@index([candidate_id])
@@ -557,6 +552,8 @@ model AssessmentLibrary {
557
552
  created_by String
558
553
  updated_by String
559
554
  is_active Boolean @default(true)
555
+ /// Frozen question plan, batch cursor, and bank-generation status (JSON).
556
+ generation_state Json?
560
557
  organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
561
558
  questions Question[] // One assessment → many questions
562
559
  assessments Assessment[]
@@ -1284,24 +1281,25 @@ enum HiringPlanSectionStatus {
1284
1281
  /// Replaces the free-text `business_unit` string on HiringPlanLine / Employee.
1285
1282
  /// Headship lives on DepartmentMember.is_head (at most one per dept, enforced in service).
1286
1283
  model Department {
1287
- id String @id @default(uuid())
1288
- organisation_id String
1289
- name String
1290
- code String?
1284
+ id String @id @default(uuid())
1285
+ organisation_id String
1286
+ name String
1287
+ code String?
1291
1288
  /// Global display order across departments within the org (drag-reorder in plan grid).
1292
- sort_order Int @default(0)
1293
- created_at DateTime @default(now())
1294
- updated_at DateTime @updatedAt
1295
- created_by String
1296
- updated_by String
1297
- is_active Boolean @default(true)
1298
- organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
1299
- members DepartmentMember[]
1300
- hiring_plan_lines HiringPlanLine[]
1301
- employees Employee[]
1302
- job_descriptions JobDescription[]
1303
- job_profiles JobProfile[]
1304
- sections HiringPlanSection[]
1289
+ sort_order Int @default(0)
1290
+ created_at DateTime @default(now())
1291
+ updated_at DateTime @updatedAt
1292
+ created_by String
1293
+ updated_by String
1294
+ is_active Boolean @default(true)
1295
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Cascade, onUpdate: Cascade)
1296
+ members DepartmentMember[]
1297
+ hiring_plan_lines HiringPlanLine[]
1298
+ employees Employee[]
1299
+ job_descriptions JobDescription[]
1300
+ job_profiles JobProfile[]
1301
+ sections HiringPlanSection[]
1302
+ assigned_hiring_units PurchasedHiringUnit[]
1305
1303
 
1306
1304
  @@unique([organisation_id, name])
1307
1305
  @@index([organisation_id])
@@ -1405,7 +1403,6 @@ model Document {
1405
1403
  offer_letters OfferLetter[] @relation("OfferLetterPdf")
1406
1404
  offer_letter_template_snapshots OfferLetter[] @relation("OfferLetterTemplateSnapshot")
1407
1405
  offer_draft_edited_html Offer[] @relation("OfferDraftEditedHtml")
1408
- application_fit_check_report Application? @relation("ApplicationFitCheckReportDocument")
1409
1406
 
1410
1407
  // Indexes
1411
1408
  @@index([candidate_id])
@@ -1448,8 +1445,17 @@ model EvaluationCriteria {
1448
1445
  @@schema("public")
1449
1446
  }
1450
1447
 
1448
+ /// MCQ / interview round classification on EvaluationPlan and analytics.
1449
+ /// ASSESSMENT is the legacy value kept for backward compatibility — do not drop it.
1450
+ /// GENERAL_APTITUDE_ASSESSMENT and DOMAIN_KNOWLEDGE_ASSESSMENT are explicit split
1451
+ /// types for new aptitude vs domain-knowledge MCQ rounds only.
1451
1452
  enum RoundType {
1453
+ /// Legacy MCQ round type; existing plans and analytics may still use this.
1452
1454
  ASSESSMENT
1455
+ /// New explicit general-aptitude MCQ round.
1456
+ GENERAL_APTITUDE_ASSESSMENT
1457
+ /// New explicit domain-knowledge MCQ round.
1458
+ DOMAIN_KNOWLEDGE_ASSESSMENT
1453
1459
  INTERVIEW
1454
1460
  ASSIGNMENT
1455
1461
  SCREENING
@@ -2539,6 +2545,7 @@ model JobDescription {
2539
2545
  hiring_plan_line HiringPlanLine? @relation("PlanLineRequisitions", fields: [hiring_plan_line_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
2540
2546
  /// Plan lines that use this JD as the role template/reference.
2541
2547
  referenced_by_plan_lines HiringPlanLine[] @relation("PlanLineTemplateJd")
2548
+ linked_hiring_units PurchasedHiringUnit[]
2542
2549
 
2543
2550
  @@index([organisation_id])
2544
2551
  @@index([hiring_manager_id])
@@ -2730,6 +2737,353 @@ model JobRoundAnalyticsDaily {
2730
2737
  @@schema("analytics")
2731
2738
  }
2732
2739
 
2740
+ /// Append-only book of AI workflow cost (org pool, optionally a hiring unit).
2741
+ /// Covers every workflow (including license-included names). Amount is always USD.
2742
+ /// total_cost(unit) = SUM(DEBIT amount) - SUM(CREDIT amount) for that unit.
2743
+ /// CREDIT / PURCHASE is full package internal cost (USD) per hiring unit.
2744
+ /// DEBIT / USAGE is every workflow's Orion totalCost (USD), nothing excluded.
2745
+ model AiCostLedgerEntry {
2746
+ id String @id @default(uuid())
2747
+ organisation_id String
2748
+ purchased_hiring_unit_id String?
2749
+ workflow_name String
2750
+ direction LicensingLedgerDirection
2751
+ /// Always non-negative. USD.
2752
+ amount Decimal @db.Decimal(20, 4)
2753
+ reason AiCostLedgerReason
2754
+ occurred_at DateTime @default(now())
2755
+ source_type String?
2756
+ source_id String?
2757
+ description String?
2758
+ idempotency_key String @unique
2759
+ created_at DateTime @default(now())
2760
+ updated_at DateTime @default(now()) @updatedAt
2761
+ created_by String
2762
+ updated_by String
2763
+ is_active Boolean @default(true)
2764
+
2765
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2766
+ purchased_hiring_unit PurchasedHiringUnit? @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2767
+
2768
+ @@index([purchased_hiring_unit_id, occurred_at], map: "ai_cost_ledger_unit_occurred_idx")
2769
+ @@index([purchased_hiring_unit_id, workflow_name, occurred_at], map: "ai_cost_ledger_unit_workflow_occurred_idx")
2770
+ @@index([organisation_id, occurred_at], map: "ai_cost_ledger_org_occurred_idx")
2771
+ @@map("ai_cost_ledger")
2772
+ @@schema("licensing")
2773
+ }
2774
+
2775
+ /// Immutable assignment history for Hiring Unit department/job changes.
2776
+ model PurchasedHiringUnitAssignmentEvent {
2777
+ id String @id @default(uuid())
2778
+ purchased_hiring_unit_id String
2779
+ event_kind PurchasedHiringUnitAssignmentEventKind
2780
+ previous_department_id String?
2781
+ new_department_id String?
2782
+ previous_job_description_id String?
2783
+ new_job_description_id String?
2784
+ effective_at DateTime @default(now())
2785
+ created_by String
2786
+
2787
+ purchased_hiring_unit PurchasedHiringUnit @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2788
+
2789
+ @@index([purchased_hiring_unit_id], map: "purchased_hu_assignment_events_unit_id_idx")
2790
+ @@index([purchased_hiring_unit_id, effective_at], map: "purchased_hu_assignment_events_unit_effective_idx")
2791
+ @@map("purchased_hiring_unit_assignment_events")
2792
+ @@schema("licensing")
2793
+ }
2794
+
2795
+ /// Product catalogue: one wide row per (code, version) with fixed per-hiring-unit entitlements.
2796
+ /// See eagles-db/docs/eagles-db/licensing-catalog.md for column → usage metric_key mapping at purchase.
2797
+ model LicensePackage {
2798
+ id String @id @default(uuid())
2799
+ code String
2800
+ version Int
2801
+ name String
2802
+ description String?
2803
+ price Decimal @db.Decimal(18, 2)
2804
+ /// Internal cost of the package. Same currency as `currency`. Not for org-facing catalogue APIs.
2805
+ cost_price Decimal @default(0) @db.Decimal(18, 2)
2806
+ currency String @default("INR")
2807
+ status LicensePackageStatus @default(DRAFT)
2808
+ /// Number of PurchasedHiringUnit rows created per package purchase.
2809
+ units_per_purchase Int
2810
+
2811
+ /// Per-hiring-unit entitlements. null = not included; 0 = explicitly zero.
2812
+ interview_ai_assisted_hours Decimal? @db.Decimal(20, 4)
2813
+ interview_full_ai_hours Decimal? @db.Decimal(20, 4)
2814
+ interview_non_ai_hours Decimal? @db.Decimal(20, 4)
2815
+ assignment_count Decimal? @db.Decimal(20, 4)
2816
+ test_count Decimal? @db.Decimal(20, 4)
2817
+ resume_count Decimal? @db.Decimal(20, 4)
2818
+ credits Decimal? @db.Decimal(20, 4)
2819
+
2820
+ created_at DateTime @default(now())
2821
+ updated_at DateTime @updatedAt
2822
+ created_by String
2823
+ updated_by String
2824
+ is_active Boolean @default(true)
2825
+
2826
+ purchased_license_packages PurchasedLicensePackage[]
2827
+ organisations LicensePackageOrganisation[]
2828
+
2829
+ @@unique([code, version])
2830
+ @@index([code])
2831
+ @@index([status])
2832
+ @@map("license_packages")
2833
+ @@schema("licensing")
2834
+ }
2835
+
2836
+ /// Many-to-many: which organisations may see this catalogue package.
2837
+ /// Zero rows = visible to nobody except platform list (enforced later in eagles-backend).
2838
+ model LicensePackageOrganisation {
2839
+ id String @id @default(uuid())
2840
+ license_package_id String
2841
+ organisation_id String
2842
+
2843
+ created_at DateTime @default(now())
2844
+ updated_at DateTime @updatedAt
2845
+ created_by String
2846
+ updated_by String
2847
+ is_active Boolean @default(true)
2848
+
2849
+ license_package LicensePackage @relation(fields: [license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2850
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2851
+
2852
+ @@unique([license_package_id, organisation_id], map: "license_package_orgs_pkg_org_key")
2853
+ @@index([organisation_id])
2854
+ @@map("license_package_organisations")
2855
+ @@schema("licensing")
2856
+ }
2857
+
2858
+ enum LicensePackageStatus {
2859
+ DRAFT
2860
+ ACTIVE
2861
+ ARCHIVED
2862
+
2863
+ @@schema("licensing")
2864
+ }
2865
+
2866
+ enum PurchasedLicensePackageStatus {
2867
+ ACTIVE
2868
+ EXPIRED
2869
+ CANCELLED
2870
+
2871
+ @@schema("licensing")
2872
+ }
2873
+
2874
+ enum PurchasedHiringUnitStatus {
2875
+ AVAILABLE
2876
+ ASSIGNED
2877
+ ACTIVE
2878
+ EXPIRED
2879
+
2880
+ @@schema("licensing")
2881
+ }
2882
+
2883
+ enum PurchasedTopUpStatus {
2884
+ ACTIVE
2885
+ DEPLETED
2886
+ CANCELLED
2887
+
2888
+ @@schema("licensing")
2889
+ }
2890
+
2891
+ enum PurchasedHiringUnitAssignmentEventKind {
2892
+ DEPARTMENT_ASSIGNED
2893
+ DEPARTMENT_UNASSIGNED
2894
+ JOB_LINKED
2895
+ JOB_UNLINKED
2896
+
2897
+ @@schema("licensing")
2898
+ }
2899
+
2900
+ enum LicensingLedgerEntitlementType {
2901
+ INTERVIEW_AI_ASSISTED_HOURS
2902
+ INTERVIEW_FULL_AI_HOURS
2903
+ INTERVIEW_NON_AI_HOURS
2904
+ ASSIGNMENT_COUNT
2905
+ TEST_COUNT
2906
+ RESUME_COUNT
2907
+ CREDITS
2908
+
2909
+ @@schema("licensing")
2910
+ }
2911
+
2912
+ enum LicensingLedgerDirection {
2913
+ CREDIT
2914
+ DEBIT
2915
+
2916
+ @@schema("licensing")
2917
+ }
2918
+
2919
+ enum LicensingLedgerReason {
2920
+ PURCHASE
2921
+ TOP_UP
2922
+ USAGE
2923
+ ADJUSTMENT
2924
+ REFUND
2925
+ EXPIRY
2926
+
2927
+ @@schema("licensing")
2928
+ }
2929
+
2930
+ enum AiCostLedgerReason {
2931
+ PURCHASE
2932
+ USAGE
2933
+ ADJUSTMENT
2934
+ REFUND
2935
+
2936
+ @@schema("licensing")
2937
+ }
2938
+
2939
+ /// Append-only book of hiring-unit entitlement movements.
2940
+ /// remaining(unit, type) = SUM(CREDIT amount) - SUM(DEBIT amount).
2941
+ /// See eagles-db/docs/eagles-db/licensing-hiring-unit.md.
2942
+ model LicensingLedgerEntry {
2943
+ id String @id @default(uuid())
2944
+ organisation_id String
2945
+ /// Null for org-level rows (e.g. unallocated top-ups later).
2946
+ purchased_hiring_unit_id String?
2947
+ entitlement_type LicensingLedgerEntitlementType
2948
+ direction LicensingLedgerDirection
2949
+ /// Always non-negative. CREDIT of 0 means the stem is included at zero.
2950
+ amount Decimal @db.Decimal(20, 4)
2951
+ reason LicensingLedgerReason
2952
+ occurred_at DateTime @default(now())
2953
+ source_type String?
2954
+ source_id String?
2955
+ description String?
2956
+ idempotency_key String @unique
2957
+ created_at DateTime @default(now())
2958
+ updated_at DateTime @default(now()) @updatedAt
2959
+ created_by String
2960
+ updated_by String
2961
+ is_active Boolean @default(true)
2962
+
2963
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2964
+ purchased_hiring_unit PurchasedHiringUnit? @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2965
+
2966
+ @@index([purchased_hiring_unit_id, entitlement_type, occurred_at], map: "licensing_ledger_unit_type_occurred_idx")
2967
+ @@index([organisation_id, entitlement_type, occurred_at], map: "licensing_ledger_org_type_occurred_idx")
2968
+ @@map("licensing_ledger")
2969
+ @@schema("licensing")
2970
+ }
2971
+
2972
+ /// Historical package purchase by an organisation (independent per transaction).
2973
+ model PurchasedLicensePackage {
2974
+ id String @id @default(uuid())
2975
+ organisation_id String
2976
+ license_package_id String
2977
+ /// Snapshot of catalogue identity at purchase time.
2978
+ package_code String
2979
+ package_version Int
2980
+ package_name String
2981
+ price Decimal @db.Decimal(18, 2)
2982
+ currency String @default("INR")
2983
+ units_per_purchase Int
2984
+ /// How many package instances were bought in this transaction.
2985
+ package_quantity Int @default(1)
2986
+ purchased_at DateTime @default(now())
2987
+ status PurchasedLicensePackageStatus @default(ACTIVE)
2988
+ created_at DateTime @default(now())
2989
+ updated_at DateTime @updatedAt
2990
+ created_by String
2991
+ updated_by String
2992
+ is_active Boolean @default(true)
2993
+
2994
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2995
+ license_package LicensePackage @relation(fields: [license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
2996
+ hiring_units PurchasedHiringUnit[]
2997
+
2998
+ @@index([organisation_id])
2999
+ @@index([organisation_id, status])
3000
+ @@index([organisation_id, purchased_at])
3001
+ @@map("purchased_license_packages")
3002
+ @@schema("licensing")
3003
+ }
3004
+
3005
+ /// Runtime hiring unit identity and allocation. Entitlement balances live on
3006
+ /// `licensing.licensing_ledger` (Prisma model `LicensingLedgerEntry`).
3007
+ /// See eagles-db/docs/eagles-db/licensing-hiring-unit.md.
3008
+ model PurchasedHiringUnit {
3009
+ id String @id @default(uuid())
3010
+ organisation_id String
3011
+ purchased_license_package_id String
3012
+ status PurchasedHiringUnitStatus @default(AVAILABLE)
3013
+ /// Current department allocation (licensing allocation, not hiring manager).
3014
+ department_id String?
3015
+ /// Set once when department_id is first assigned; not cleared on reassignment.
3016
+ first_assigned_at DateTime?
3017
+ /// Optional unit expiry.
3018
+ expiry_at DateTime?
3019
+ /// Optional job association (distinct from JobDescription.hiring_manager_id).
3020
+ job_description_id String?
3021
+
3022
+ created_at DateTime @default(now())
3023
+ updated_at DateTime @updatedAt
3024
+ created_by String
3025
+ updated_by String
3026
+ is_active Boolean @default(true)
3027
+
3028
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
3029
+ purchased_license_package PurchasedLicensePackage @relation(fields: [purchased_license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
3030
+ department Department? @relation(fields: [department_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
3031
+ job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
3032
+ assignment_events PurchasedHiringUnitAssignmentEvent[]
3033
+ ledger_entries LicensingLedgerEntry[]
3034
+ ai_cost_ledger_entries AiCostLedgerEntry[]
3035
+
3036
+ @@index([organisation_id])
3037
+ @@index([purchased_license_package_id])
3038
+ @@index([department_id])
3039
+ @@index([job_description_id])
3040
+ @@index([organisation_id, status])
3041
+ @@index([organisation_id, department_id])
3042
+ @@index([organisation_id, job_description_id])
3043
+ @@map("purchased_hiring_units")
3044
+ @@schema("licensing")
3045
+ }
3046
+
3047
+ /// Wide top-up purchase: org-level per-metric pool (purchased / remaining) before allocation to hiring units.
3048
+ model PurchasedTopUp {
3049
+ id String @id @default(uuid())
3050
+ organisation_id String
3051
+ purchased_at DateTime @default(now())
3052
+ status PurchasedTopUpStatus @default(ACTIVE)
3053
+ total_price Decimal? @db.Decimal(18, 2)
3054
+ currency String? @default("INR")
3055
+ description String?
3056
+
3057
+ interview_ai_assisted_hours_purchased Decimal? @db.Decimal(20, 4)
3058
+ interview_full_ai_hours_purchased Decimal? @db.Decimal(20, 4)
3059
+ interview_non_ai_hours_purchased Decimal? @db.Decimal(20, 4)
3060
+ assignment_count_purchased Decimal? @db.Decimal(20, 4)
3061
+ test_count_purchased Decimal? @db.Decimal(20, 4)
3062
+ resume_count_purchased Decimal? @db.Decimal(20, 4)
3063
+ credits_purchased Decimal? @db.Decimal(20, 4)
3064
+
3065
+ interview_ai_assisted_hours_remaining Decimal? @db.Decimal(20, 4)
3066
+ interview_full_ai_hours_remaining Decimal? @db.Decimal(20, 4)
3067
+ interview_non_ai_hours_remaining Decimal? @db.Decimal(20, 4)
3068
+ assignment_count_remaining Decimal? @db.Decimal(20, 4)
3069
+ test_count_remaining Decimal? @db.Decimal(20, 4)
3070
+ resume_count_remaining Decimal? @db.Decimal(20, 4)
3071
+ credits_remaining Decimal? @db.Decimal(20, 4)
3072
+
3073
+ created_at DateTime @default(now())
3074
+ updated_at DateTime @updatedAt
3075
+ created_by String
3076
+ updated_by String
3077
+ is_active Boolean @default(true)
3078
+
3079
+ organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
3080
+
3081
+ @@index([organisation_id])
3082
+ @@index([organisation_id, status])
3083
+ @@map("purchased_top_ups")
3084
+ @@schema("licensing")
3085
+ }
3086
+
2733
3087
  model LiveAnalysis {
2734
3088
  id String @id @default(uuid())
2735
3089
  //foreign keys
@@ -3152,65 +3506,71 @@ enum OrganisationSize {
3152
3506
  }
3153
3507
 
3154
3508
  model Organisation {
3155
- id String @id @default(uuid())
3156
- name String @unique
3157
- industry String
3158
- about String
3159
- website String
3160
- size OrganisationSize @default(ONE_TO_TEN)
3161
- phone String
3162
- address String
3163
- company_values Json[]
3164
- allowed_email_domains String[]
3165
- send_email Boolean @default(true)
3166
- interviewers User[]
3167
- created_at DateTime @default(now())
3168
- updated_at DateTime @updatedAt
3169
- created_by String
3170
- updated_by String
3171
- is_active Boolean @default(true)
3172
- alias String? @unique
3173
- logo String?
3174
- job_sequence Int @default(1)
3175
- employee_sequence Int @default(1)
3176
- applications Application[]
3177
- user_roles UserRole[]
3178
- job_descriptions JobDescription[]
3179
- job_profiles JobProfile[]
3180
- assessment_library AssessmentLibrary[]
3181
- assignment_library AssignmentLibrary[]
3182
- interviews Interview[]
3183
- assignments Assignment[]
3184
- fit_check FitCheck[] // one-to-many link
3185
- resumes Resume[] // one-to-many link
3186
- approvals Approval[] // one-to-many link
3187
- suggestions Suggestion[]
3188
- ongoing_evaluations OngoingEvaluation[] // optional one-to-many
3189
- actions Action[]
3190
- integration_credentials IntegrationCredential[]
3191
- zoho_sync_mappings ZohoSyncMapping[]
3192
- assessments Assessment[]
3193
- timezone String @default("Asia/Kolkata")
3509
+ id String @id @default(uuid())
3510
+ name String @unique
3511
+ industry String
3512
+ about String
3513
+ website String
3514
+ size OrganisationSize @default(ONE_TO_TEN)
3515
+ phone String
3516
+ address String
3517
+ company_values Json[]
3518
+ allowed_email_domains String[]
3519
+ send_email Boolean @default(true)
3520
+ interviewers User[]
3521
+ created_at DateTime @default(now())
3522
+ updated_at DateTime @updatedAt
3523
+ created_by String
3524
+ updated_by String
3525
+ is_active Boolean @default(true)
3526
+ alias String? @unique
3527
+ logo String?
3528
+ job_sequence Int @default(1)
3529
+ employee_sequence Int @default(1)
3530
+ applications Application[]
3531
+ user_roles UserRole[]
3532
+ job_descriptions JobDescription[]
3533
+ job_profiles JobProfile[]
3534
+ assessment_library AssessmentLibrary[]
3535
+ assignment_library AssignmentLibrary[]
3536
+ interviews Interview[]
3537
+ assignments Assignment[]
3538
+ fit_check FitCheck[] // one-to-many link
3539
+ resumes Resume[] // one-to-many link
3540
+ approvals Approval[] // one-to-many link
3541
+ suggestions Suggestion[]
3542
+ ongoing_evaluations OngoingEvaluation[] // optional one-to-many
3543
+ actions Action[]
3544
+ integration_credentials IntegrationCredential[]
3545
+ zoho_sync_mappings ZohoSyncMapping[]
3546
+ assessments Assessment[]
3547
+ timezone String @default("Asia/Kolkata")
3194
3548
  /// ISO 3166-1 alpha-2 (e.g. IN).
3195
- country_code String @default("IN")
3196
- organisation_configs OrganisationConfig[]
3197
- activity_events ActivityEvent[]
3198
- usage_ledger_entries UsageLedgerEntry[]
3199
- usage_aggregates UsageAggregate[]
3200
- channel_provider_configs ChannelProviderConfig[]
3201
- conversations Conversation[]
3202
- communication_messages CommunicationMessage[]
3203
- job_application_fields JobApplicationField[]
3204
- documents Document[]
3205
- job_application_templates JobApplicationTemplate[]
3206
- offer_letter_templates OfferLetterTemplate[]
3207
- offers Offer[]
3208
- sources Source[]
3209
- evaluation_criteria EvaluationCriteria[]
3210
- departments Department[]
3211
- hiring_plans HiringPlan[]
3212
- employees Employee[]
3213
- competency_dictionaries CompetencyDictionary[]
3549
+ country_code String @default("IN")
3550
+ organisation_configs OrganisationConfig[]
3551
+ activity_events ActivityEvent[]
3552
+ usage_ledger_entries UsageLedgerEntry[]
3553
+ usage_aggregates UsageAggregate[]
3554
+ channel_provider_configs ChannelProviderConfig[]
3555
+ conversations Conversation[]
3556
+ communication_messages CommunicationMessage[]
3557
+ job_application_fields JobApplicationField[]
3558
+ documents Document[]
3559
+ job_application_templates JobApplicationTemplate[]
3560
+ offer_letter_templates OfferLetterTemplate[]
3561
+ offers Offer[]
3562
+ sources Source[]
3563
+ evaluation_criteria EvaluationCriteria[]
3564
+ departments Department[]
3565
+ hiring_plans HiringPlan[]
3566
+ employees Employee[]
3567
+ competency_dictionaries CompetencyDictionary[]
3568
+ purchased_license_packages PurchasedLicensePackage[]
3569
+ purchased_hiring_units PurchasedHiringUnit[]
3570
+ purchased_top_ups PurchasedTopUp[]
3571
+ licensing_ledger_entries LicensingLedgerEntry[]
3572
+ license_package_organisations LicensePackageOrganisation[]
3573
+ ai_cost_ledger_entries AiCostLedgerEntry[]
3214
3574
 
3215
3575
  @@index([name])
3216
3576
  @@schema("public")
@@ -3367,12 +3727,24 @@ enum Difficulty {
3367
3727
  @@schema("public")
3368
3728
  }
3369
3729
 
3730
+ enum QuestionCategory {
3731
+ /// Aptitude, logical reasoning, numerical, verbal — non-domain general tests.
3732
+ GENERAL_APTITUDE
3733
+ /// Role/domain/technical knowledge (skills from JD and competencies).
3734
+ DOMAIN_KNOWLEDGE
3735
+
3736
+ @@schema("public")
3737
+ }
3738
+
3370
3739
  model Question {
3371
3740
  id String @id @default(uuid())
3372
3741
  assessment_library_id String?
3373
3742
  evaluation_plan_id String?
3374
3743
  candidate_id String?
3375
3744
  skill String?
3745
+ category QuestionCategory?
3746
+ /// Stable idempotency key for reusable bank rows: `{generationSeed}:{planSlot}`.
3747
+ bank_item_key String?
3376
3748
  question String
3377
3749
  answer String
3378
3750
  options String[] // For MCQ's
@@ -3389,6 +3761,7 @@ model Question {
3389
3761
  evaluationPlan EvaluationPlan? @relation(fields: [evaluation_plan_id], references: [id], onDelete: SetNull)
3390
3762
  candidateResponse CandidateQuestionResponse[]
3391
3763
 
3764
+ @@unique([assessment_library_id, bank_item_key])
3392
3765
  @@schema("public")
3393
3766
  }
3394
3767
 
@@ -3675,7 +4048,7 @@ datasource db {
3675
4048
  provider = "postgresql"
3676
4049
  url = env("DATABASE_URL")
3677
4050
 
3678
- schemas = ["public", "analytics", "usage"]
4051
+ schemas = ["public", "analytics", "usage", "licensing"]
3679
4052
  }
3680
4053
 
3681
4054
  enum SourceCategory {