@adaptware/eagles-db 0.5.36 → 0.5.39
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.
- package/client/edge.js +1 -2
- package/client/index.js +6 -7
- package/client/wasm.js +1 -2
- package/package.json +1 -1
- package/prisma/schema/department.prisma +3 -2
- package/prisma/schema/jobDescription.prisma +1 -0
- package/prisma/schema/licensing/aiCostLedger.prisma +34 -0
- package/prisma/schema/licensing/assignmentHistory.prisma +19 -0
- package/prisma/schema/licensing/licensePackageCatalog.prisma +62 -0
- package/prisma/schema/licensing/licensingEnums.prisma +80 -0
- package/prisma/schema/licensing/licensingLedger.prisma +32 -0
- package/prisma/schema/licensing/purchasedLicense.prisma +74 -0
- package/prisma/schema/licensing/purchasedTopUp.prisma +39 -0
- package/prisma/schema/migrations/20260519120000_add_analytics_schema/migration.sql +84 -0
- package/prisma/schema/migrations/20260625120000_add_interviewer_analytics/migration.sql +26 -0
- package/prisma/schema/migrations/20260629120000_add_user_lifecycle_activity_events/migration.sql +13 -0
- package/prisma/schema/migrations/20260629140000_drop_organisation_org_code/migration.sql +2 -0
- package/prisma/schema/migrations/20260629160000_employee_codes_dual_interviewer_analytics/migration.sql +87 -0
- package/prisma/schema/migrations/20260630120000_add_application_sources/migration.sql +38 -0
- package/prisma/schema/migrations/20260701120000_add_source_effectiveness_analytics/migration.sql +40 -0
- package/prisma/schema/migrations/20260702120000_add_analytics_daily_tables/migration.sql +232 -0
- package/prisma/schema/migrations/20260716120000_evaluation_category_four_values/migration.sql +204 -0
- package/prisma/schema/migrations/20260716130000_application_withdrawn_analytics/migration.sql +31 -0
- package/prisma/schema/migrations/20260804120000_contact_us_optional_website_subject/migration.sql +3 -0
- package/prisma/schema/migrations/20260810120000_add_licensing_schema/migration.sql +237 -0
- package/prisma/schema/migrations/20260814153000_add_licensing_ledger/migration.sql +236 -0
- package/prisma/schema/migrations/20260828120000_license_package_orgs_cost_price_ai_cost_ledger/migration.sql +74 -0
- package/prisma/schema/migrations/20260831120000_ai_cost_ledger_purchase_reason/migration.sql +2 -0
- package/prisma/schema/migrations/20260831140000_ai_cost_ledger_nullable_hiring_unit/migration.sql +3 -0
- package/prisma/schema/organisation.prisma +6 -0
- package/prisma/schema/schema.prisma +1 -1
package/client/edge.js
CHANGED
|
@@ -2816,7 +2816,7 @@ const config = {
|
|
|
2816
2816
|
},
|
|
2817
2817
|
"relativeEnvPaths": {
|
|
2818
2818
|
"rootEnvPath": null,
|
|
2819
|
-
"schemaEnvPath": "
|
|
2819
|
+
"schemaEnvPath": "../../eagles-backend/.env"
|
|
2820
2820
|
},
|
|
2821
2821
|
"relativePath": "../prisma/schema",
|
|
2822
2822
|
"clientVersion": "6.19.3",
|
|
@@ -2825,7 +2825,6 @@ const config = {
|
|
|
2825
2825
|
"db"
|
|
2826
2826
|
],
|
|
2827
2827
|
"activeProvider": "postgresql",
|
|
2828
|
-
"postinstall": false,
|
|
2829
2828
|
"inlineDatasources": {
|
|
2830
2829
|
"db": {
|
|
2831
2830
|
"url": {
|
package/client/index.js
CHANGED
|
@@ -2817,7 +2817,7 @@ const config = {
|
|
|
2817
2817
|
},
|
|
2818
2818
|
"relativeEnvPaths": {
|
|
2819
2819
|
"rootEnvPath": null,
|
|
2820
|
-
"schemaEnvPath": "
|
|
2820
|
+
"schemaEnvPath": "../../eagles-backend/.env"
|
|
2821
2821
|
},
|
|
2822
2822
|
"relativePath": "../prisma/schema",
|
|
2823
2823
|
"clientVersion": "6.19.3",
|
|
@@ -2826,7 +2826,6 @@ const config = {
|
|
|
2826
2826
|
"db"
|
|
2827
2827
|
],
|
|
2828
2828
|
"activeProvider": "postgresql",
|
|
2829
|
-
"postinstall": false,
|
|
2830
2829
|
"inlineDatasources": {
|
|
2831
2830
|
"db": {
|
|
2832
2831
|
"url": {
|
|
@@ -2845,8 +2844,8 @@ const fs = require('fs')
|
|
|
2845
2844
|
config.dirname = __dirname
|
|
2846
2845
|
if (!fs.existsSync(path.join(__dirname, 'schema.prisma'))) {
|
|
2847
2846
|
const alternativePaths = [
|
|
2848
|
-
"client",
|
|
2849
|
-
"",
|
|
2847
|
+
"../eagles-db/client",
|
|
2848
|
+
"eagles-db/client",
|
|
2850
2849
|
]
|
|
2851
2850
|
|
|
2852
2851
|
const alternativePath = alternativePaths.find((altPath) => {
|
|
@@ -2876,11 +2875,11 @@ Object.assign(exports, Prisma)
|
|
|
2876
2875
|
|
|
2877
2876
|
// file annotations for bundling tools to include these files
|
|
2878
2877
|
path.join(__dirname, "libquery_engine-darwin-arm64.dylib.node");
|
|
2879
|
-
path.join(process.cwd(), "client/libquery_engine-darwin-arm64.dylib.node")
|
|
2878
|
+
path.join(process.cwd(), "../eagles-db/client/libquery_engine-darwin-arm64.dylib.node")
|
|
2880
2879
|
|
|
2881
2880
|
// file annotations for bundling tools to include these files
|
|
2882
2881
|
path.join(__dirname, "libquery_engine-linux-arm64-openssl-1.1.x.so.node");
|
|
2883
|
-
path.join(process.cwd(), "client/libquery_engine-linux-arm64-openssl-1.1.x.so.node")
|
|
2882
|
+
path.join(process.cwd(), "../eagles-db/client/libquery_engine-linux-arm64-openssl-1.1.x.so.node")
|
|
2884
2883
|
// file annotations for bundling tools to include these files
|
|
2885
2884
|
path.join(__dirname, "schema.prisma");
|
|
2886
|
-
path.join(process.cwd(), "client/schema.prisma")
|
|
2885
|
+
path.join(process.cwd(), "../eagles-db/client/schema.prisma")
|
package/client/wasm.js
CHANGED
|
@@ -2816,7 +2816,7 @@ const config = {
|
|
|
2816
2816
|
},
|
|
2817
2817
|
"relativeEnvPaths": {
|
|
2818
2818
|
"rootEnvPath": null,
|
|
2819
|
-
"schemaEnvPath": "
|
|
2819
|
+
"schemaEnvPath": "../../eagles-backend/.env"
|
|
2820
2820
|
},
|
|
2821
2821
|
"relativePath": "../prisma/schema",
|
|
2822
2822
|
"clientVersion": "6.19.3",
|
|
@@ -2825,7 +2825,6 @@ const config = {
|
|
|
2825
2825
|
"db"
|
|
2826
2826
|
],
|
|
2827
2827
|
"activeProvider": "postgresql",
|
|
2828
|
-
"postinstall": false,
|
|
2829
2828
|
"inlineDatasources": {
|
|
2830
2829
|
"db": {
|
|
2831
2830
|
"url": {
|
package/package.json
CHANGED
|
@@ -38,8 +38,9 @@ model Department {
|
|
|
38
38
|
hiring_plan_lines HiringPlanLine[]
|
|
39
39
|
employees Employee[]
|
|
40
40
|
job_descriptions JobDescription[]
|
|
41
|
-
job_profiles
|
|
42
|
-
sections
|
|
41
|
+
job_profiles JobProfile[]
|
|
42
|
+
sections HiringPlanSection[]
|
|
43
|
+
assigned_hiring_units PurchasedHiringUnit[]
|
|
43
44
|
|
|
44
45
|
@@unique([organisation_id, name])
|
|
45
46
|
@@index([organisation_id])
|
|
@@ -72,6 +72,7 @@ model JobDescription {
|
|
|
72
72
|
hiring_plan_line HiringPlanLine? @relation("PlanLineRequisitions", fields: [hiring_plan_line_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
|
|
73
73
|
/// Plan lines that use this JD as the role template/reference.
|
|
74
74
|
referenced_by_plan_lines HiringPlanLine[] @relation("PlanLineTemplateJd")
|
|
75
|
+
linked_hiring_units PurchasedHiringUnit[]
|
|
75
76
|
|
|
76
77
|
@@index([organisation_id])
|
|
77
78
|
@@index([hiring_manager_id])
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// Append-only book of AI workflow cost (org pool, optionally a hiring unit).
|
|
2
|
+
/// Covers every workflow (including license-included names). Amount is always USD.
|
|
3
|
+
/// total_cost(unit) = SUM(DEBIT amount) - SUM(CREDIT amount) for that unit.
|
|
4
|
+
/// CREDIT / PURCHASE is full package internal cost (USD) per hiring unit.
|
|
5
|
+
/// DEBIT / USAGE is every workflow's Orion totalCost (USD), nothing excluded.
|
|
6
|
+
model AiCostLedgerEntry {
|
|
7
|
+
id String @id @default(uuid())
|
|
8
|
+
organisation_id String
|
|
9
|
+
purchased_hiring_unit_id String?
|
|
10
|
+
workflow_name String
|
|
11
|
+
direction LicensingLedgerDirection
|
|
12
|
+
/// Always non-negative. USD.
|
|
13
|
+
amount Decimal @db.Decimal(20, 4)
|
|
14
|
+
reason AiCostLedgerReason
|
|
15
|
+
occurred_at DateTime @default(now())
|
|
16
|
+
source_type String?
|
|
17
|
+
source_id String?
|
|
18
|
+
description String?
|
|
19
|
+
idempotency_key String @unique
|
|
20
|
+
created_at DateTime @default(now())
|
|
21
|
+
updated_at DateTime @default(now()) @updatedAt
|
|
22
|
+
created_by String
|
|
23
|
+
updated_by String
|
|
24
|
+
is_active Boolean @default(true)
|
|
25
|
+
|
|
26
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
27
|
+
purchased_hiring_unit PurchasedHiringUnit? @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
28
|
+
|
|
29
|
+
@@index([purchased_hiring_unit_id, occurred_at], map: "ai_cost_ledger_unit_occurred_idx")
|
|
30
|
+
@@index([purchased_hiring_unit_id, workflow_name, occurred_at], map: "ai_cost_ledger_unit_workflow_occurred_idx")
|
|
31
|
+
@@index([organisation_id, occurred_at], map: "ai_cost_ledger_org_occurred_idx")
|
|
32
|
+
@@map("ai_cost_ledger")
|
|
33
|
+
@@schema("licensing")
|
|
34
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// Immutable assignment history for Hiring Unit department/job changes.
|
|
2
|
+
model PurchasedHiringUnitAssignmentEvent {
|
|
3
|
+
id String @id @default(uuid())
|
|
4
|
+
purchased_hiring_unit_id String
|
|
5
|
+
event_kind PurchasedHiringUnitAssignmentEventKind
|
|
6
|
+
previous_department_id String?
|
|
7
|
+
new_department_id String?
|
|
8
|
+
previous_job_description_id String?
|
|
9
|
+
new_job_description_id String?
|
|
10
|
+
effective_at DateTime @default(now())
|
|
11
|
+
created_by String
|
|
12
|
+
|
|
13
|
+
purchased_hiring_unit PurchasedHiringUnit @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
14
|
+
|
|
15
|
+
@@index([purchased_hiring_unit_id], map: "purchased_hu_assignment_events_unit_id_idx")
|
|
16
|
+
@@index([purchased_hiring_unit_id, effective_at], map: "purchased_hu_assignment_events_unit_effective_idx")
|
|
17
|
+
@@map("purchased_hiring_unit_assignment_events")
|
|
18
|
+
@@schema("licensing")
|
|
19
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/// Product catalogue: one wide row per (code, version) with fixed per-hiring-unit entitlements.
|
|
2
|
+
/// See eagles-db/docs/eagles-db/licensing-catalog.md for column → usage metric_key mapping at purchase.
|
|
3
|
+
model LicensePackage {
|
|
4
|
+
id String @id @default(uuid())
|
|
5
|
+
code String
|
|
6
|
+
version Int
|
|
7
|
+
name String
|
|
8
|
+
description String?
|
|
9
|
+
price Decimal @db.Decimal(18, 2)
|
|
10
|
+
/// Internal cost of the package. Same currency as `currency`. Not for org-facing catalogue APIs.
|
|
11
|
+
cost_price Decimal @default(0) @db.Decimal(18, 2)
|
|
12
|
+
currency String @default("INR")
|
|
13
|
+
status LicensePackageStatus @default(DRAFT)
|
|
14
|
+
/// Number of PurchasedHiringUnit rows created per package purchase.
|
|
15
|
+
units_per_purchase Int
|
|
16
|
+
|
|
17
|
+
/// Per-hiring-unit entitlements. null = not included; 0 = explicitly zero.
|
|
18
|
+
interview_ai_assisted_hours Decimal? @db.Decimal(20, 4)
|
|
19
|
+
interview_full_ai_hours Decimal? @db.Decimal(20, 4)
|
|
20
|
+
interview_non_ai_hours Decimal? @db.Decimal(20, 4)
|
|
21
|
+
assignment_count Decimal? @db.Decimal(20, 4)
|
|
22
|
+
test_count Decimal? @db.Decimal(20, 4)
|
|
23
|
+
resume_count Decimal? @db.Decimal(20, 4)
|
|
24
|
+
credits Decimal? @db.Decimal(20, 4)
|
|
25
|
+
|
|
26
|
+
created_at DateTime @default(now())
|
|
27
|
+
updated_at DateTime @updatedAt
|
|
28
|
+
created_by String
|
|
29
|
+
updated_by String
|
|
30
|
+
is_active Boolean @default(true)
|
|
31
|
+
|
|
32
|
+
purchased_license_packages PurchasedLicensePackage[]
|
|
33
|
+
organisations LicensePackageOrganisation[]
|
|
34
|
+
|
|
35
|
+
@@unique([code, version])
|
|
36
|
+
@@index([code])
|
|
37
|
+
@@index([status])
|
|
38
|
+
@@map("license_packages")
|
|
39
|
+
@@schema("licensing")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Many-to-many: which organisations may see this catalogue package.
|
|
43
|
+
/// Zero rows = visible to nobody except platform list (enforced later in eagles-backend).
|
|
44
|
+
model LicensePackageOrganisation {
|
|
45
|
+
id String @id @default(uuid())
|
|
46
|
+
license_package_id String
|
|
47
|
+
organisation_id String
|
|
48
|
+
|
|
49
|
+
created_at DateTime @default(now())
|
|
50
|
+
updated_at DateTime @updatedAt
|
|
51
|
+
created_by String
|
|
52
|
+
updated_by String
|
|
53
|
+
is_active Boolean @default(true)
|
|
54
|
+
|
|
55
|
+
license_package LicensePackage @relation(fields: [license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
56
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
57
|
+
|
|
58
|
+
@@unique([license_package_id, organisation_id], map: "license_package_orgs_pkg_org_key")
|
|
59
|
+
@@index([organisation_id])
|
|
60
|
+
@@map("license_package_organisations")
|
|
61
|
+
@@schema("licensing")
|
|
62
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
enum LicensePackageStatus {
|
|
2
|
+
DRAFT
|
|
3
|
+
ACTIVE
|
|
4
|
+
ARCHIVED
|
|
5
|
+
|
|
6
|
+
@@schema("licensing")
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
enum PurchasedLicensePackageStatus {
|
|
10
|
+
ACTIVE
|
|
11
|
+
EXPIRED
|
|
12
|
+
CANCELLED
|
|
13
|
+
|
|
14
|
+
@@schema("licensing")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum PurchasedHiringUnitStatus {
|
|
18
|
+
AVAILABLE
|
|
19
|
+
ASSIGNED
|
|
20
|
+
ACTIVE
|
|
21
|
+
EXPIRED
|
|
22
|
+
|
|
23
|
+
@@schema("licensing")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
enum PurchasedTopUpStatus {
|
|
27
|
+
ACTIVE
|
|
28
|
+
DEPLETED
|
|
29
|
+
CANCELLED
|
|
30
|
+
|
|
31
|
+
@@schema("licensing")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
enum PurchasedHiringUnitAssignmentEventKind {
|
|
35
|
+
DEPARTMENT_ASSIGNED
|
|
36
|
+
DEPARTMENT_UNASSIGNED
|
|
37
|
+
JOB_LINKED
|
|
38
|
+
JOB_UNLINKED
|
|
39
|
+
|
|
40
|
+
@@schema("licensing")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
enum LicensingLedgerEntitlementType {
|
|
44
|
+
INTERVIEW_AI_ASSISTED_HOURS
|
|
45
|
+
INTERVIEW_FULL_AI_HOURS
|
|
46
|
+
INTERVIEW_NON_AI_HOURS
|
|
47
|
+
ASSIGNMENT_COUNT
|
|
48
|
+
TEST_COUNT
|
|
49
|
+
RESUME_COUNT
|
|
50
|
+
CREDITS
|
|
51
|
+
|
|
52
|
+
@@schema("licensing")
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
enum LicensingLedgerDirection {
|
|
56
|
+
CREDIT
|
|
57
|
+
DEBIT
|
|
58
|
+
|
|
59
|
+
@@schema("licensing")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
enum LicensingLedgerReason {
|
|
63
|
+
PURCHASE
|
|
64
|
+
TOP_UP
|
|
65
|
+
USAGE
|
|
66
|
+
ADJUSTMENT
|
|
67
|
+
REFUND
|
|
68
|
+
EXPIRY
|
|
69
|
+
|
|
70
|
+
@@schema("licensing")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
enum AiCostLedgerReason {
|
|
74
|
+
PURCHASE
|
|
75
|
+
USAGE
|
|
76
|
+
ADJUSTMENT
|
|
77
|
+
REFUND
|
|
78
|
+
|
|
79
|
+
@@schema("licensing")
|
|
80
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// Append-only book of hiring-unit entitlement movements.
|
|
2
|
+
/// remaining(unit, type) = SUM(CREDIT amount) - SUM(DEBIT amount).
|
|
3
|
+
/// See eagles-db/docs/eagles-db/licensing-hiring-unit.md.
|
|
4
|
+
model LicensingLedgerEntry {
|
|
5
|
+
id String @id @default(uuid())
|
|
6
|
+
organisation_id String
|
|
7
|
+
/// Null for org-level rows (e.g. unallocated top-ups later).
|
|
8
|
+
purchased_hiring_unit_id String?
|
|
9
|
+
entitlement_type LicensingLedgerEntitlementType
|
|
10
|
+
direction LicensingLedgerDirection
|
|
11
|
+
/// Always non-negative. CREDIT of 0 means the stem is included at zero.
|
|
12
|
+
amount Decimal @db.Decimal(20, 4)
|
|
13
|
+
reason LicensingLedgerReason
|
|
14
|
+
occurred_at DateTime @default(now())
|
|
15
|
+
source_type String?
|
|
16
|
+
source_id String?
|
|
17
|
+
description String?
|
|
18
|
+
idempotency_key String @unique
|
|
19
|
+
created_at DateTime @default(now())
|
|
20
|
+
updated_at DateTime @default(now()) @updatedAt
|
|
21
|
+
created_by String
|
|
22
|
+
updated_by String
|
|
23
|
+
is_active Boolean @default(true)
|
|
24
|
+
|
|
25
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
26
|
+
purchased_hiring_unit PurchasedHiringUnit? @relation(fields: [purchased_hiring_unit_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
27
|
+
|
|
28
|
+
@@index([purchased_hiring_unit_id, entitlement_type, occurred_at], map: "licensing_ledger_unit_type_occurred_idx")
|
|
29
|
+
@@index([organisation_id, entitlement_type, occurred_at], map: "licensing_ledger_org_type_occurred_idx")
|
|
30
|
+
@@map("licensing_ledger")
|
|
31
|
+
@@schema("licensing")
|
|
32
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/// Historical package purchase by an organisation (independent per transaction).
|
|
2
|
+
model PurchasedLicensePackage {
|
|
3
|
+
id String @id @default(uuid())
|
|
4
|
+
organisation_id String
|
|
5
|
+
license_package_id String
|
|
6
|
+
/// Snapshot of catalogue identity at purchase time.
|
|
7
|
+
package_code String
|
|
8
|
+
package_version Int
|
|
9
|
+
package_name String
|
|
10
|
+
price Decimal @db.Decimal(18, 2)
|
|
11
|
+
currency String @default("INR")
|
|
12
|
+
units_per_purchase Int
|
|
13
|
+
/// How many package instances were bought in this transaction.
|
|
14
|
+
package_quantity Int @default(1)
|
|
15
|
+
purchased_at DateTime @default(now())
|
|
16
|
+
status PurchasedLicensePackageStatus @default(ACTIVE)
|
|
17
|
+
created_at DateTime @default(now())
|
|
18
|
+
updated_at DateTime @updatedAt
|
|
19
|
+
created_by String
|
|
20
|
+
updated_by String
|
|
21
|
+
is_active Boolean @default(true)
|
|
22
|
+
|
|
23
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
24
|
+
license_package LicensePackage @relation(fields: [license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
25
|
+
hiring_units PurchasedHiringUnit[]
|
|
26
|
+
|
|
27
|
+
@@index([organisation_id])
|
|
28
|
+
@@index([organisation_id, status])
|
|
29
|
+
@@index([organisation_id, purchased_at])
|
|
30
|
+
@@map("purchased_license_packages")
|
|
31
|
+
@@schema("licensing")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Runtime hiring unit identity and allocation. Entitlement balances live on
|
|
35
|
+
/// `licensing.licensing_ledger` (Prisma model `LicensingLedgerEntry`).
|
|
36
|
+
/// See eagles-db/docs/eagles-db/licensing-hiring-unit.md.
|
|
37
|
+
model PurchasedHiringUnit {
|
|
38
|
+
id String @id @default(uuid())
|
|
39
|
+
organisation_id String
|
|
40
|
+
purchased_license_package_id String
|
|
41
|
+
status PurchasedHiringUnitStatus @default(AVAILABLE)
|
|
42
|
+
/// Current department allocation (licensing allocation, not hiring manager).
|
|
43
|
+
department_id String?
|
|
44
|
+
/// Set once when department_id is first assigned; not cleared on reassignment.
|
|
45
|
+
first_assigned_at DateTime?
|
|
46
|
+
/// Optional unit expiry.
|
|
47
|
+
expiry_at DateTime?
|
|
48
|
+
/// Optional job association (distinct from JobDescription.hiring_manager_id).
|
|
49
|
+
job_description_id String?
|
|
50
|
+
|
|
51
|
+
created_at DateTime @default(now())
|
|
52
|
+
updated_at DateTime @updatedAt
|
|
53
|
+
created_by String
|
|
54
|
+
updated_by String
|
|
55
|
+
is_active Boolean @default(true)
|
|
56
|
+
|
|
57
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
58
|
+
purchased_license_package PurchasedLicensePackage @relation(fields: [purchased_license_package_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
59
|
+
department Department? @relation(fields: [department_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
|
|
60
|
+
job_description JobDescription? @relation(fields: [job_description_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
|
|
61
|
+
assignment_events PurchasedHiringUnitAssignmentEvent[]
|
|
62
|
+
ledger_entries LicensingLedgerEntry[]
|
|
63
|
+
ai_cost_ledger_entries AiCostLedgerEntry[]
|
|
64
|
+
|
|
65
|
+
@@index([organisation_id])
|
|
66
|
+
@@index([purchased_license_package_id])
|
|
67
|
+
@@index([department_id])
|
|
68
|
+
@@index([job_description_id])
|
|
69
|
+
@@index([organisation_id, status])
|
|
70
|
+
@@index([organisation_id, department_id])
|
|
71
|
+
@@index([organisation_id, job_description_id])
|
|
72
|
+
@@map("purchased_hiring_units")
|
|
73
|
+
@@schema("licensing")
|
|
74
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/// Wide top-up purchase: org-level per-metric pool (purchased / remaining) before allocation to hiring units.
|
|
2
|
+
model PurchasedTopUp {
|
|
3
|
+
id String @id @default(uuid())
|
|
4
|
+
organisation_id String
|
|
5
|
+
purchased_at DateTime @default(now())
|
|
6
|
+
status PurchasedTopUpStatus @default(ACTIVE)
|
|
7
|
+
total_price Decimal? @db.Decimal(18, 2)
|
|
8
|
+
currency String? @default("INR")
|
|
9
|
+
description String?
|
|
10
|
+
|
|
11
|
+
interview_ai_assisted_hours_purchased Decimal? @db.Decimal(20, 4)
|
|
12
|
+
interview_full_ai_hours_purchased Decimal? @db.Decimal(20, 4)
|
|
13
|
+
interview_non_ai_hours_purchased Decimal? @db.Decimal(20, 4)
|
|
14
|
+
assignment_count_purchased Decimal? @db.Decimal(20, 4)
|
|
15
|
+
test_count_purchased Decimal? @db.Decimal(20, 4)
|
|
16
|
+
resume_count_purchased Decimal? @db.Decimal(20, 4)
|
|
17
|
+
credits_purchased Decimal? @db.Decimal(20, 4)
|
|
18
|
+
|
|
19
|
+
interview_ai_assisted_hours_remaining Decimal? @db.Decimal(20, 4)
|
|
20
|
+
interview_full_ai_hours_remaining Decimal? @db.Decimal(20, 4)
|
|
21
|
+
interview_non_ai_hours_remaining Decimal? @db.Decimal(20, 4)
|
|
22
|
+
assignment_count_remaining Decimal? @db.Decimal(20, 4)
|
|
23
|
+
test_count_remaining Decimal? @db.Decimal(20, 4)
|
|
24
|
+
resume_count_remaining Decimal? @db.Decimal(20, 4)
|
|
25
|
+
credits_remaining Decimal? @db.Decimal(20, 4)
|
|
26
|
+
|
|
27
|
+
created_at DateTime @default(now())
|
|
28
|
+
updated_at DateTime @updatedAt
|
|
29
|
+
created_by String
|
|
30
|
+
updated_by String
|
|
31
|
+
is_active Boolean @default(true)
|
|
32
|
+
|
|
33
|
+
organisation Organisation @relation(fields: [organisation_id], references: [id], onDelete: Restrict, onUpdate: Cascade)
|
|
34
|
+
|
|
35
|
+
@@index([organisation_id])
|
|
36
|
+
@@index([organisation_id, status])
|
|
37
|
+
@@map("purchased_top_ups")
|
|
38
|
+
@@schema("licensing")
|
|
39
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
-- CreateSchema
|
|
2
|
+
CREATE SCHEMA IF NOT EXISTS "analytics";
|
|
3
|
+
|
|
4
|
+
-- CreateEnum
|
|
5
|
+
CREATE TYPE "analytics"."RoundResult" AS ENUM ('PASSED', 'FAILED');
|
|
6
|
+
|
|
7
|
+
-- CreateTable
|
|
8
|
+
CREATE TABLE "analytics"."round_analytics" (
|
|
9
|
+
"id" TEXT NOT NULL,
|
|
10
|
+
"organisation_id" TEXT NOT NULL,
|
|
11
|
+
"application_id" TEXT NOT NULL,
|
|
12
|
+
"candidate_id" TEXT NOT NULL,
|
|
13
|
+
"job_description_id" TEXT NOT NULL,
|
|
14
|
+
"evaluation_plan_id" TEXT NOT NULL,
|
|
15
|
+
"round_id" TEXT NOT NULL,
|
|
16
|
+
"round_name" TEXT,
|
|
17
|
+
"evaluation_category" "EvaluationCategory",
|
|
18
|
+
"round_type" "RoundType",
|
|
19
|
+
"assigned_at" TIMESTAMP(3),
|
|
20
|
+
"interview_created_at" TIMESTAMP(3),
|
|
21
|
+
"interview_scheduled_at" TIMESTAMP(3),
|
|
22
|
+
"interview_started_at" TIMESTAMP(3),
|
|
23
|
+
"interview_completed_at" TIMESTAMP(3),
|
|
24
|
+
"interview_evaluated_at" TIMESTAMP(3),
|
|
25
|
+
"round_completed_at" TIMESTAMP(3),
|
|
26
|
+
"round_result" "analytics"."RoundResult",
|
|
27
|
+
"round_result_at" TIMESTAMP(3),
|
|
28
|
+
"scheduling_duration_minutes" INTEGER,
|
|
29
|
+
"interview_duration_minutes" INTEGER,
|
|
30
|
+
"feedback_duration_minutes" INTEGER,
|
|
31
|
+
"decision_duration_minutes" INTEGER,
|
|
32
|
+
"total_round_duration_minutes" INTEGER,
|
|
33
|
+
"is_custom" BOOLEAN NOT NULL DEFAULT false,
|
|
34
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
35
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
36
|
+
|
|
37
|
+
CONSTRAINT "round_analytics_pkey" PRIMARY KEY ("id")
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
-- CreateTable
|
|
41
|
+
CREATE TABLE "analytics"."job_round_analytics" (
|
|
42
|
+
"id" TEXT NOT NULL,
|
|
43
|
+
"organisation_id" TEXT NOT NULL,
|
|
44
|
+
"job_description_id" TEXT NOT NULL,
|
|
45
|
+
"evaluation_plan_id" TEXT NOT NULL,
|
|
46
|
+
"round_name" TEXT NOT NULL,
|
|
47
|
+
"evaluation_category" "EvaluationCategory",
|
|
48
|
+
"is_custom" BOOLEAN NOT NULL DEFAULT false,
|
|
49
|
+
"assigned_count" INTEGER NOT NULL DEFAULT 0,
|
|
50
|
+
"completed_count" INTEGER NOT NULL DEFAULT 0,
|
|
51
|
+
"passed_count" INTEGER NOT NULL DEFAULT 0,
|
|
52
|
+
"failed_count" INTEGER NOT NULL DEFAULT 0,
|
|
53
|
+
"withdrawn_count" INTEGER NOT NULL DEFAULT 0,
|
|
54
|
+
"no_show_count" INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
"total_completion_minutes" BIGINT NOT NULL DEFAULT 0,
|
|
56
|
+
"avg_completion_minutes" DOUBLE PRECISION,
|
|
57
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
58
|
+
|
|
59
|
+
CONSTRAINT "job_round_analytics_pkey" PRIMARY KEY ("id")
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
-- CreateIndex
|
|
63
|
+
CREATE UNIQUE INDEX "round_analytics_round_id_key" ON "analytics"."round_analytics"("round_id");
|
|
64
|
+
|
|
65
|
+
-- CreateIndex
|
|
66
|
+
CREATE INDEX "round_analytics_organisation_id_idx" ON "analytics"."round_analytics"("organisation_id");
|
|
67
|
+
|
|
68
|
+
-- CreateIndex
|
|
69
|
+
CREATE INDEX "round_analytics_job_description_id_idx" ON "analytics"."round_analytics"("job_description_id");
|
|
70
|
+
|
|
71
|
+
-- CreateIndex
|
|
72
|
+
CREATE INDEX "round_analytics_application_id_idx" ON "analytics"."round_analytics"("application_id");
|
|
73
|
+
|
|
74
|
+
-- CreateIndex
|
|
75
|
+
CREATE INDEX "round_analytics_candidate_id_idx" ON "analytics"."round_analytics"("candidate_id");
|
|
76
|
+
|
|
77
|
+
-- CreateIndex
|
|
78
|
+
CREATE INDEX "round_analytics_evaluation_category_idx" ON "analytics"."round_analytics"("evaluation_category");
|
|
79
|
+
|
|
80
|
+
-- CreateIndex
|
|
81
|
+
CREATE INDEX "round_analytics_round_result_idx" ON "analytics"."round_analytics"("round_result");
|
|
82
|
+
|
|
83
|
+
-- CreateIndex
|
|
84
|
+
CREATE UNIQUE INDEX "job_round_analytics_job_description_id_evaluation_plan_id_key" ON "analytics"."job_round_analytics"("job_description_id", "evaluation_plan_id");
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "analytics"."interviewer_analytics" (
|
|
3
|
+
"id" TEXT NOT NULL,
|
|
4
|
+
"organisation_id" TEXT NOT NULL,
|
|
5
|
+
"user_id" TEXT NOT NULL,
|
|
6
|
+
"name" TEXT,
|
|
7
|
+
"employee_id" TEXT,
|
|
8
|
+
"interview_count" INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
"accepted_count" INTEGER NOT NULL DEFAULT 0,
|
|
10
|
+
"rejected_count" INTEGER NOT NULL DEFAULT 0,
|
|
11
|
+
"unsure_count" INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
"ai_disagreement_count" INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
"ai_disagreement_percent" DOUBLE PRECISION,
|
|
14
|
+
"avg_difficulty" DOUBLE PRECISION,
|
|
15
|
+
"avg_supportiveness" DOUBLE PRECISION,
|
|
16
|
+
"avg_topics_coverage_percent" DOUBLE PRECISION,
|
|
17
|
+
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
18
|
+
|
|
19
|
+
CONSTRAINT "interviewer_analytics_pkey" PRIMARY KEY ("id")
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- CreateIndex
|
|
23
|
+
CREATE UNIQUE INDEX "interviewer_analytics_organisation_id_user_id_key" ON "analytics"."interviewer_analytics"("organisation_id", "user_id");
|
|
24
|
+
|
|
25
|
+
-- CreateIndex
|
|
26
|
+
CREATE INDEX "interviewer_analytics_organisation_id_idx" ON "analytics"."interviewer_analytics"("organisation_id");
|
package/prisma/schema/migrations/20260629120000_add_user_lifecycle_activity_events/migration.sql
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- AlterEnum
|
|
2
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_INVITED';
|
|
3
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_INVITATION_RESENT';
|
|
4
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_CREATED';
|
|
5
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_INVITATION_ACCEPTED';
|
|
6
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_INVITATION_EXPIRED';
|
|
7
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_DEACTIVATED';
|
|
8
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_REACTIVATED';
|
|
9
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_ROLE_CHANGED';
|
|
10
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'USER_PROFILE_COMPLETED';
|
|
11
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'CANDIDATE_REGISTERED';
|
|
12
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'CANDIDATE_CREATED';
|
|
13
|
+
ALTER TYPE "public"."ActivityEventType" ADD VALUE 'CANDIDATE_PROFILE_COMPLETED';
|