vr-models 1.0.1 → 1.0.2
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/dist/models/device.models.d.ts +28 -3
- package/dist/models/device.models.js +91 -48
- package/dist/models/devicePaymentPlan.models.d.ts +41 -4
- package/dist/models/devicePaymentPlan.models.js +159 -91
- package/dist/models/eventLog.models.d.ts +34 -7
- package/dist/models/eventLog.models.js +40 -0
- package/dist/models/idempotencyRecord.models.d.ts +27 -2
- package/dist/models/idempotencyRecord.models.js +27 -0
- package/dist/models/payment.models.d.ts +46 -7
- package/dist/models/payment.models.js +77 -2
- package/dist/models/pricing.models.d.ts +30 -5
- package/dist/models/pricing.models.js +29 -1
- package/dist/models/product.models.d.ts +31 -4
- package/dist/models/product.models.js +53 -2
- package/dist/models/securityClearance.models.d.ts +30 -5
- package/dist/models/securityClearance.models.js +91 -48
- package/dist/models/transaction.models.d.ts +30 -4
- package/dist/models/transaction.models.js +60 -3
- package/dist/models/user.models.d.ts +51 -3
- package/dist/models/user.models.js +195 -115
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.IdempotencyRecord = void 0;
|
|
4
4
|
const vr_migrations_1 = require("vr-migrations");
|
|
5
5
|
class IdempotencyRecord extends vr_migrations_1.Model {
|
|
6
|
+
// Static initialization method
|
|
6
7
|
static initialize(sequelize) {
|
|
7
8
|
this.init({
|
|
8
9
|
id: {
|
|
@@ -58,5 +59,31 @@ class IdempotencyRecord extends vr_migrations_1.Model {
|
|
|
58
59
|
},
|
|
59
60
|
});
|
|
60
61
|
}
|
|
62
|
+
// Static association method
|
|
63
|
+
static associate(models) {
|
|
64
|
+
// This model doesn't have foreign key associations
|
|
65
|
+
}
|
|
66
|
+
// Custom instance methods
|
|
67
|
+
static async invalidate(key) {
|
|
68
|
+
const result = await this.destroy({
|
|
69
|
+
where: { key },
|
|
70
|
+
});
|
|
71
|
+
return result > 0;
|
|
72
|
+
}
|
|
73
|
+
isValid() {
|
|
74
|
+
return new Date() < this.expiresAt;
|
|
75
|
+
}
|
|
76
|
+
isExpired() {
|
|
77
|
+
return !this.isValid();
|
|
78
|
+
}
|
|
79
|
+
getResponse() {
|
|
80
|
+
if (!this.responseStatusCode || !this.responseBody) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
statusCode: this.responseStatusCode,
|
|
85
|
+
body: this.responseBody,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
61
88
|
}
|
|
62
89
|
exports.IdempotencyRecord = IdempotencyRecord;
|
|
@@ -1,7 +1,37 @@
|
|
|
1
1
|
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
|
+
import type { User } from "./user.models";
|
|
3
|
+
import type { DevicePaymentPlan } from "./devicePaymentPlan.models";
|
|
4
|
+
import type { Transaction } from "./transaction.models";
|
|
5
|
+
import type { IdempotencyRecord } from "./idempotencyRecord.models";
|
|
2
6
|
export type PaymentProvider = "mtn_momo" | "airtel_money";
|
|
3
7
|
export type PaymentStatus = "pending" | "succeeded" | "failed";
|
|
4
|
-
export
|
|
8
|
+
export interface PaymentAttributes {
|
|
9
|
+
id: string;
|
|
10
|
+
userId: string;
|
|
11
|
+
devicePaymentPlanId: string;
|
|
12
|
+
transactionId: string | null;
|
|
13
|
+
idempotencyKeyId: string | null;
|
|
14
|
+
amount: number;
|
|
15
|
+
provider: PaymentProvider;
|
|
16
|
+
providerReference: string | null;
|
|
17
|
+
status: PaymentStatus;
|
|
18
|
+
metadata: Record<string, any>;
|
|
19
|
+
createdAt: Date;
|
|
20
|
+
updatedAt: Date;
|
|
21
|
+
user?: User;
|
|
22
|
+
devicePaymentPlan?: DevicePaymentPlan;
|
|
23
|
+
transaction?: Transaction;
|
|
24
|
+
idempotencyKey?: IdempotencyRecord;
|
|
25
|
+
}
|
|
26
|
+
export interface PaymentCreationAttributes extends Omit<PaymentAttributes, "id" | "createdAt" | "updatedAt" | "status" | "providerReference" | "metadata" | "transactionId" | "idempotencyKeyId"> {
|
|
27
|
+
id?: string;
|
|
28
|
+
status?: PaymentStatus;
|
|
29
|
+
providerReference?: string | null;
|
|
30
|
+
metadata?: Record<string, any>;
|
|
31
|
+
transactionId?: string | null;
|
|
32
|
+
idempotencyKeyId?: string | null;
|
|
33
|
+
}
|
|
34
|
+
export declare class Payment extends Model<InferAttributes<Payment>, InferCreationAttributes<Payment>> implements PaymentAttributes {
|
|
5
35
|
id: CreationOptional<string>;
|
|
6
36
|
userId: string;
|
|
7
37
|
devicePaymentPlanId: string;
|
|
@@ -10,15 +40,24 @@ export declare class Payment extends Model<InferAttributes<Payment>, InferCreati
|
|
|
10
40
|
amount: number;
|
|
11
41
|
provider: PaymentProvider;
|
|
12
42
|
providerReference: CreationOptional<string | null>;
|
|
13
|
-
status: PaymentStatus
|
|
14
|
-
metadata: Record<string, any
|
|
43
|
+
status: CreationOptional<PaymentStatus>;
|
|
44
|
+
metadata: CreationOptional<Record<string, any>>;
|
|
15
45
|
readonly createdAt: CreationOptional<Date>;
|
|
16
46
|
readonly updatedAt: CreationOptional<Date>;
|
|
17
|
-
user?: NonAttribute<
|
|
18
|
-
devicePaymentPlan?: NonAttribute<
|
|
19
|
-
transaction?: NonAttribute<
|
|
20
|
-
idempotencyKey?: NonAttribute<
|
|
47
|
+
user?: NonAttribute<User>;
|
|
48
|
+
devicePaymentPlan?: NonAttribute<DevicePaymentPlan>;
|
|
49
|
+
transaction?: NonAttribute<Transaction>;
|
|
50
|
+
idempotencyKey?: NonAttribute<IdempotencyRecord>;
|
|
21
51
|
static initialize(sequelize: any): void;
|
|
22
52
|
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
53
|
+
markAsSucceeded(providerReference: string, metadata?: Record<string, any>): Promise<void>;
|
|
54
|
+
markAsFailed(reason: string, metadata?: Record<string, any>): Promise<void>;
|
|
55
|
+
process(transactionId: string, idempotencyKeyId?: string): Promise<void>;
|
|
56
|
+
isSuccessful(): boolean;
|
|
57
|
+
isPending(): boolean;
|
|
58
|
+
isFailed(): boolean;
|
|
59
|
+
getProviderDisplayName(): string;
|
|
60
|
+
static getUserPayments(userId: string, limit?: number): Promise<Payment[]>;
|
|
61
|
+
static getPaymentPlanPayments(devicePaymentPlanId: string): Promise<Payment[]>;
|
|
23
62
|
}
|
|
24
63
|
export type PaymentModel = typeof Payment;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Payment = void 0;
|
|
4
4
|
const vr_migrations_1 = require("vr-migrations");
|
|
5
5
|
class Payment extends vr_migrations_1.Model {
|
|
6
|
+
// Static initialization method
|
|
6
7
|
static initialize(sequelize) {
|
|
7
8
|
this.init({
|
|
8
9
|
id: {
|
|
@@ -29,7 +30,11 @@ class Payment extends vr_migrations_1.Model {
|
|
|
29
30
|
allowNull: false,
|
|
30
31
|
defaultValue: "pending",
|
|
31
32
|
},
|
|
32
|
-
metadata: {
|
|
33
|
+
metadata: {
|
|
34
|
+
type: vr_migrations_1.DataTypes.JSONB,
|
|
35
|
+
allowNull: false,
|
|
36
|
+
defaultValue: {},
|
|
37
|
+
},
|
|
33
38
|
createdAt: { type: vr_migrations_1.DataTypes.DATE, defaultValue: vr_migrations_1.DataTypes.NOW },
|
|
34
39
|
updatedAt: { type: vr_migrations_1.DataTypes.DATE, defaultValue: vr_migrations_1.DataTypes.NOW },
|
|
35
40
|
}, {
|
|
@@ -45,19 +50,89 @@ class Payment extends vr_migrations_1.Model {
|
|
|
45
50
|
},
|
|
46
51
|
});
|
|
47
52
|
}
|
|
53
|
+
// Static association method
|
|
48
54
|
static associate(models) {
|
|
49
|
-
this.belongsTo(models.User, {
|
|
55
|
+
this.belongsTo(models.User, {
|
|
56
|
+
foreignKey: "userId",
|
|
57
|
+
as: "user",
|
|
58
|
+
onDelete: "RESTRICT",
|
|
59
|
+
onUpdate: "CASCADE",
|
|
60
|
+
});
|
|
50
61
|
this.belongsTo(models.DevicePaymentPlan, {
|
|
51
62
|
foreignKey: "devicePaymentPlanId",
|
|
52
63
|
as: "devicePaymentPlan",
|
|
64
|
+
onDelete: "RESTRICT",
|
|
65
|
+
onUpdate: "CASCADE",
|
|
53
66
|
});
|
|
54
67
|
this.belongsTo(models.Transaction, {
|
|
55
68
|
foreignKey: "transactionId",
|
|
56
69
|
as: "transaction",
|
|
70
|
+
onDelete: "SET NULL",
|
|
71
|
+
onUpdate: "CASCADE",
|
|
57
72
|
});
|
|
58
73
|
this.belongsTo(models.IdempotencyRecord, {
|
|
59
74
|
foreignKey: "idempotencyKeyId",
|
|
60
75
|
as: "idempotencyKey",
|
|
76
|
+
onDelete: "SET NULL",
|
|
77
|
+
onUpdate: "CASCADE",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Custom instance methods
|
|
81
|
+
async markAsSucceeded(providerReference, metadata) {
|
|
82
|
+
this.status = "succeeded";
|
|
83
|
+
this.providerReference = providerReference;
|
|
84
|
+
if (metadata) {
|
|
85
|
+
this.metadata = { ...this.metadata, ...metadata };
|
|
86
|
+
}
|
|
87
|
+
await this.save();
|
|
88
|
+
}
|
|
89
|
+
async markAsFailed(reason, metadata) {
|
|
90
|
+
this.status = "failed";
|
|
91
|
+
const failureMetadata = {
|
|
92
|
+
failureReason: reason,
|
|
93
|
+
failedAt: new Date().toISOString(),
|
|
94
|
+
...metadata,
|
|
95
|
+
};
|
|
96
|
+
this.metadata = { ...this.metadata, ...failureMetadata };
|
|
97
|
+
await this.save();
|
|
98
|
+
}
|
|
99
|
+
async process(transactionId, idempotencyKeyId) {
|
|
100
|
+
this.transactionId = transactionId;
|
|
101
|
+
if (idempotencyKeyId) {
|
|
102
|
+
this.idempotencyKeyId = idempotencyKeyId;
|
|
103
|
+
}
|
|
104
|
+
await this.save();
|
|
105
|
+
}
|
|
106
|
+
isSuccessful() {
|
|
107
|
+
return this.status === "succeeded";
|
|
108
|
+
}
|
|
109
|
+
isPending() {
|
|
110
|
+
return this.status === "pending";
|
|
111
|
+
}
|
|
112
|
+
isFailed() {
|
|
113
|
+
return this.status === "failed";
|
|
114
|
+
}
|
|
115
|
+
getProviderDisplayName() {
|
|
116
|
+
switch (this.provider) {
|
|
117
|
+
case "mtn_momo":
|
|
118
|
+
return "MTN Mobile Money";
|
|
119
|
+
case "airtel_money":
|
|
120
|
+
return "Airtel Money";
|
|
121
|
+
default:
|
|
122
|
+
return this.provider;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
static async getUserPayments(userId, limit = 50) {
|
|
126
|
+
return await this.findAll({
|
|
127
|
+
where: { userId },
|
|
128
|
+
order: [["createdAt", "DESC"]],
|
|
129
|
+
limit,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
static async getPaymentPlanPayments(devicePaymentPlanId) {
|
|
133
|
+
return await this.findAll({
|
|
134
|
+
where: { devicePaymentPlanId },
|
|
135
|
+
order: [["createdAt", "ASC"]],
|
|
61
136
|
});
|
|
62
137
|
}
|
|
63
138
|
}
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { Product } from "./product.models";
|
|
3
|
+
export interface PricingAttributes {
|
|
4
|
+
id: string;
|
|
4
5
|
productId: string;
|
|
5
6
|
name: string;
|
|
6
7
|
upfrontPrice: number;
|
|
7
8
|
downPayment: number;
|
|
8
|
-
installmentAmount
|
|
9
|
-
installmentIntervalDays
|
|
9
|
+
installmentAmount: number | null;
|
|
10
|
+
installmentIntervalDays: number | null;
|
|
11
|
+
totalAmount: number;
|
|
12
|
+
isActive: boolean;
|
|
13
|
+
createdAt: Date;
|
|
14
|
+
updatedAt: Date;
|
|
15
|
+
product?: Product;
|
|
16
|
+
}
|
|
17
|
+
export interface PricingCreationAttributes extends Omit<PricingAttributes, "id" | "createdAt" | "updatedAt" | "isActive" | "downPayment"> {
|
|
18
|
+
id?: string;
|
|
19
|
+
isActive?: boolean;
|
|
20
|
+
downPayment?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class Pricing extends Model<InferAttributes<Pricing>, InferCreationAttributes<Pricing>> implements PricingAttributes {
|
|
23
|
+
id: CreationOptional<string>;
|
|
24
|
+
productId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
upfrontPrice: number;
|
|
27
|
+
downPayment: CreationOptional<number>;
|
|
28
|
+
installmentAmount: CreationOptional<number | null>;
|
|
29
|
+
installmentIntervalDays: CreationOptional<number | null>;
|
|
10
30
|
totalAmount: number;
|
|
11
31
|
isActive: CreationOptional<boolean>;
|
|
12
32
|
readonly createdAt: CreationOptional<Date>;
|
|
13
33
|
readonly updatedAt: CreationOptional<Date>;
|
|
14
|
-
product?: NonAttribute<
|
|
34
|
+
product?: NonAttribute<Product>;
|
|
15
35
|
static initialize(sequelize: any): void;
|
|
16
36
|
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
37
|
+
activate(): Promise<void>;
|
|
38
|
+
deactivate(): Promise<void>;
|
|
39
|
+
isInstallmentPlan(): boolean;
|
|
40
|
+
getInstallmentCount(): number | null;
|
|
41
|
+
calculateRemainingAmount(paidAmount: number): number;
|
|
17
42
|
}
|
|
18
43
|
export type PricingModel = typeof Pricing;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Pricing = void 0;
|
|
4
4
|
const vr_migrations_1 = require("vr-migrations");
|
|
5
5
|
class Pricing extends vr_migrations_1.Model {
|
|
6
|
+
// Static initialization method
|
|
6
7
|
static initialize(sequelize) {
|
|
7
8
|
this.init({
|
|
8
9
|
id: {
|
|
@@ -35,8 +36,35 @@ class Pricing extends vr_migrations_1.Model {
|
|
|
35
36
|
timestamps: true,
|
|
36
37
|
});
|
|
37
38
|
}
|
|
39
|
+
// Static association method
|
|
38
40
|
static associate(models) {
|
|
39
|
-
this.belongsTo(models.Product, {
|
|
41
|
+
this.belongsTo(models.Product, {
|
|
42
|
+
foreignKey: "productId",
|
|
43
|
+
as: "product",
|
|
44
|
+
onDelete: "CASCADE",
|
|
45
|
+
onUpdate: "CASCADE",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Custom instance methods
|
|
49
|
+
async activate() {
|
|
50
|
+
this.isActive = true;
|
|
51
|
+
await this.save();
|
|
52
|
+
}
|
|
53
|
+
async deactivate() {
|
|
54
|
+
this.isActive = false;
|
|
55
|
+
await this.save();
|
|
56
|
+
}
|
|
57
|
+
isInstallmentPlan() {
|
|
58
|
+
return !!(this.installmentAmount && this.installmentIntervalDays);
|
|
59
|
+
}
|
|
60
|
+
getInstallmentCount() {
|
|
61
|
+
if (!this.isInstallmentPlan())
|
|
62
|
+
return null;
|
|
63
|
+
const remainingAmount = this.totalAmount - this.downPayment;
|
|
64
|
+
return Math.ceil(remainingAmount / (this.installmentAmount || 1));
|
|
65
|
+
}
|
|
66
|
+
calculateRemainingAmount(paidAmount) {
|
|
67
|
+
return Math.max(0, this.totalAmount - paidAmount);
|
|
40
68
|
}
|
|
41
69
|
}
|
|
42
70
|
exports.Pricing = Pricing;
|
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
|
-
|
|
2
|
+
import type { Pricing } from "./pricing.models";
|
|
3
|
+
import type { Device } from "./device.models";
|
|
4
|
+
export interface ProductAttributes {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string | null;
|
|
8
|
+
stock: number;
|
|
9
|
+
isActive: boolean;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
updatedAt: Date;
|
|
12
|
+
pricings?: Pricing[];
|
|
13
|
+
devices?: Device[];
|
|
14
|
+
}
|
|
15
|
+
export interface ProductCreationAttributes extends Omit<ProductAttributes, "id" | "createdAt" | "updatedAt" | "stock" | "isActive" | "description"> {
|
|
16
|
+
id?: string;
|
|
17
|
+
description?: string | null;
|
|
18
|
+
stock?: number;
|
|
19
|
+
isActive?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare class Product extends Model<InferAttributes<Product>, InferCreationAttributes<Product>> implements ProductAttributes {
|
|
3
22
|
id: CreationOptional<string>;
|
|
4
23
|
name: string;
|
|
5
|
-
description: string
|
|
24
|
+
description: CreationOptional<string | null>;
|
|
6
25
|
stock: CreationOptional<number>;
|
|
7
26
|
isActive: CreationOptional<boolean>;
|
|
8
27
|
readonly createdAt: CreationOptional<Date>;
|
|
9
28
|
readonly updatedAt: CreationOptional<Date>;
|
|
10
|
-
pricings?: NonAttribute<
|
|
11
|
-
devices?: NonAttribute<
|
|
29
|
+
pricings?: NonAttribute<Pricing[]>;
|
|
30
|
+
devices?: NonAttribute<Device[]>;
|
|
12
31
|
static initialize(sequelize: any): void;
|
|
13
32
|
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
33
|
+
activate(): Promise<void>;
|
|
34
|
+
deactivate(): Promise<void>;
|
|
35
|
+
incrementStock(amount?: number): Promise<void>;
|
|
36
|
+
decrementStock(amount?: number): Promise<void>;
|
|
37
|
+
isInStock(): boolean;
|
|
38
|
+
getActivePricings(): Pricing[];
|
|
39
|
+
getDefaultPricing(): Pricing | null;
|
|
40
|
+
static findAvailableProducts(): Promise<Product[]>;
|
|
14
41
|
}
|
|
15
42
|
export type ProductModel = typeof Product;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Product = void 0;
|
|
4
4
|
const vr_migrations_1 = require("vr-migrations");
|
|
5
5
|
class Product extends vr_migrations_1.Model {
|
|
6
|
+
// Static initialization method
|
|
6
7
|
static initialize(sequelize) {
|
|
7
8
|
this.init({
|
|
8
9
|
id: {
|
|
@@ -27,9 +28,59 @@ class Product extends vr_migrations_1.Model {
|
|
|
27
28
|
timestamps: true,
|
|
28
29
|
});
|
|
29
30
|
}
|
|
31
|
+
// Static association method
|
|
30
32
|
static associate(models) {
|
|
31
|
-
this.hasMany(models.Pricing, {
|
|
32
|
-
|
|
33
|
+
this.hasMany(models.Pricing, {
|
|
34
|
+
foreignKey: "productId",
|
|
35
|
+
as: "pricings",
|
|
36
|
+
onDelete: "CASCADE",
|
|
37
|
+
onUpdate: "CASCADE",
|
|
38
|
+
});
|
|
39
|
+
this.hasMany(models.Device, {
|
|
40
|
+
foreignKey: "productId",
|
|
41
|
+
as: "devices",
|
|
42
|
+
onDelete: "RESTRICT",
|
|
43
|
+
onUpdate: "CASCADE",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// Custom instance methods
|
|
47
|
+
async activate() {
|
|
48
|
+
this.isActive = true;
|
|
49
|
+
await this.save();
|
|
50
|
+
}
|
|
51
|
+
async deactivate() {
|
|
52
|
+
this.isActive = false;
|
|
53
|
+
await this.save();
|
|
54
|
+
}
|
|
55
|
+
async incrementStock(amount = 1) {
|
|
56
|
+
this.stock += amount;
|
|
57
|
+
await this.save();
|
|
58
|
+
}
|
|
59
|
+
async decrementStock(amount = 1) {
|
|
60
|
+
if (this.stock < amount) {
|
|
61
|
+
throw new Error(`Insufficient stock. Available: ${this.stock}, Requested: ${amount}`);
|
|
62
|
+
}
|
|
63
|
+
this.stock -= amount;
|
|
64
|
+
await this.save();
|
|
65
|
+
}
|
|
66
|
+
isInStock() {
|
|
67
|
+
return this.stock > 0;
|
|
68
|
+
}
|
|
69
|
+
getActivePricings() {
|
|
70
|
+
if (!this.pricings)
|
|
71
|
+
return [];
|
|
72
|
+
return this.pricings.filter((pricing) => pricing.isActive);
|
|
73
|
+
}
|
|
74
|
+
getDefaultPricing() {
|
|
75
|
+
if (!this.pricings)
|
|
76
|
+
return null;
|
|
77
|
+
return this.pricings.find((pricing) => pricing.isActive) || null;
|
|
78
|
+
}
|
|
79
|
+
static async findAvailableProducts() {
|
|
80
|
+
return await this.findAll({
|
|
81
|
+
where: { isActive: true },
|
|
82
|
+
include: ["pricings"],
|
|
83
|
+
});
|
|
33
84
|
}
|
|
34
85
|
}
|
|
35
86
|
exports.Product = Product;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute } from "vr-migrations";
|
|
1
|
+
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
2
|
import type { User } from "./user.models";
|
|
3
3
|
export declare const USER_ROLES: readonly ["RIDER", "PASSENGER", "ADMIN", "AGENT", "SUPER_ADMIN"];
|
|
4
4
|
export type UserRole = (typeof USER_ROLES)[number];
|
|
@@ -30,17 +30,42 @@ export declare enum Permission {
|
|
|
30
30
|
MANAGE_SECURITY_CLEARANCE = "MANAGE_SECURITY_CLEARANCE",
|
|
31
31
|
OVERRIDE_DEVICE_LOCK = "OVERRIDE_DEVICE_LOCK"
|
|
32
32
|
}
|
|
33
|
-
export
|
|
34
|
-
id:
|
|
33
|
+
export interface SecurityClearanceAttributes {
|
|
34
|
+
id: string;
|
|
35
35
|
role: UserRole;
|
|
36
|
-
description:
|
|
36
|
+
description: string | null;
|
|
37
37
|
level: number;
|
|
38
38
|
permissions: Permission[];
|
|
39
39
|
isDefault: boolean;
|
|
40
|
+
createdAt: Date;
|
|
41
|
+
updatedAt: Date;
|
|
42
|
+
users?: User[];
|
|
43
|
+
}
|
|
44
|
+
export interface SecurityClearanceCreationAttributes extends Omit<SecurityClearanceAttributes, "id" | "createdAt" | "updatedAt" | "permissions" | "isDefault" | "description"> {
|
|
45
|
+
id?: string;
|
|
46
|
+
permissions?: Permission[];
|
|
47
|
+
isDefault?: boolean;
|
|
48
|
+
description?: string | null;
|
|
49
|
+
}
|
|
50
|
+
export declare class SecurityClearance extends Model<InferAttributes<SecurityClearance>, InferCreationAttributes<SecurityClearance>> implements SecurityClearanceAttributes {
|
|
51
|
+
id: CreationOptional<string>;
|
|
52
|
+
role: UserRole;
|
|
53
|
+
description: CreationOptional<string | null>;
|
|
54
|
+
level: number;
|
|
55
|
+
permissions: CreationOptional<Permission[]>;
|
|
56
|
+
isDefault: CreationOptional<boolean>;
|
|
40
57
|
createdAt: CreationOptional<Date>;
|
|
41
58
|
updatedAt: CreationOptional<Date>;
|
|
42
59
|
users?: NonAttribute<User[]>;
|
|
60
|
+
static initialize(sequelize: any): void;
|
|
61
|
+
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
43
62
|
hasPermission(permission: Permission): boolean;
|
|
63
|
+
addPermission(permission: Permission): Promise<void>;
|
|
64
|
+
removePermission(permission: Permission): Promise<void>;
|
|
65
|
+
setAsDefault(): Promise<void>;
|
|
66
|
+
removeAsDefault(): Promise<void>;
|
|
67
|
+
getRoleDisplayName(): string;
|
|
68
|
+
static getDefaultClearance(): Promise<SecurityClearance | null>;
|
|
69
|
+
static findByRole(role: UserRole): Promise<SecurityClearance | null>;
|
|
44
70
|
}
|
|
45
|
-
export declare const initSecurityClearanceModel: (sequelize: any) => void;
|
|
46
71
|
export type SecurityClearanceModel = typeof SecurityClearance;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
// src/models/securityClearance.models.ts
|
|
3
|
+
exports.SecurityClearance = exports.Permission = exports.USER_ROLES = void 0;
|
|
5
4
|
const vr_migrations_1 = require("vr-migrations");
|
|
5
|
+
// Constants
|
|
6
6
|
exports.USER_ROLES = [
|
|
7
7
|
"RIDER",
|
|
8
8
|
"PASSENGER",
|
|
@@ -40,54 +40,97 @@ var Permission;
|
|
|
40
40
|
Permission["OVERRIDE_DEVICE_LOCK"] = "OVERRIDE_DEVICE_LOCK";
|
|
41
41
|
})(Permission || (exports.Permission = Permission = {}));
|
|
42
42
|
class SecurityClearance extends vr_migrations_1.Model {
|
|
43
|
+
// Static initialization method
|
|
44
|
+
static initialize(sequelize) {
|
|
45
|
+
this.init({
|
|
46
|
+
id: {
|
|
47
|
+
type: vr_migrations_1.DataTypes.UUID,
|
|
48
|
+
defaultValue: vr_migrations_1.DataTypes.UUIDV4,
|
|
49
|
+
primaryKey: true,
|
|
50
|
+
},
|
|
51
|
+
role: {
|
|
52
|
+
type: vr_migrations_1.DataTypes.ENUM(...exports.USER_ROLES),
|
|
53
|
+
allowNull: false,
|
|
54
|
+
unique: true,
|
|
55
|
+
},
|
|
56
|
+
description: {
|
|
57
|
+
type: vr_migrations_1.DataTypes.TEXT,
|
|
58
|
+
allowNull: true,
|
|
59
|
+
},
|
|
60
|
+
level: {
|
|
61
|
+
type: vr_migrations_1.DataTypes.INTEGER,
|
|
62
|
+
allowNull: false,
|
|
63
|
+
},
|
|
64
|
+
permissions: {
|
|
65
|
+
type: vr_migrations_1.DataTypes.ARRAY(vr_migrations_1.DataTypes.STRING),
|
|
66
|
+
allowNull: false,
|
|
67
|
+
defaultValue: [],
|
|
68
|
+
},
|
|
69
|
+
isDefault: {
|
|
70
|
+
type: vr_migrations_1.DataTypes.BOOLEAN,
|
|
71
|
+
defaultValue: false,
|
|
72
|
+
},
|
|
73
|
+
createdAt: {
|
|
74
|
+
type: vr_migrations_1.DataTypes.DATE,
|
|
75
|
+
defaultValue: vr_migrations_1.DataTypes.NOW,
|
|
76
|
+
},
|
|
77
|
+
updatedAt: {
|
|
78
|
+
type: vr_migrations_1.DataTypes.DATE,
|
|
79
|
+
defaultValue: vr_migrations_1.DataTypes.NOW,
|
|
80
|
+
},
|
|
81
|
+
}, {
|
|
82
|
+
sequelize,
|
|
83
|
+
modelName: "SecurityClearance",
|
|
84
|
+
tableName: "security_clearances",
|
|
85
|
+
timestamps: true,
|
|
86
|
+
freezeTableName: true,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Static association method
|
|
90
|
+
static associate(models) {
|
|
91
|
+
this.hasMany(models.User, {
|
|
92
|
+
foreignKey: "securityClearanceId",
|
|
93
|
+
as: "users",
|
|
94
|
+
onDelete: "RESTRICT",
|
|
95
|
+
onUpdate: "CASCADE",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Custom instance methods
|
|
43
99
|
hasPermission(permission) {
|
|
44
100
|
return this.permissions.includes(permission);
|
|
45
101
|
}
|
|
102
|
+
async addPermission(permission) {
|
|
103
|
+
if (!this.hasPermission(permission)) {
|
|
104
|
+
this.permissions = [...this.permissions, permission];
|
|
105
|
+
await this.save();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async removePermission(permission) {
|
|
109
|
+
this.permissions = this.permissions.filter((p) => p !== permission);
|
|
110
|
+
await this.save();
|
|
111
|
+
}
|
|
112
|
+
async setAsDefault() {
|
|
113
|
+
// First, unset any existing default
|
|
114
|
+
await SecurityClearance.update({ isDefault: false }, { where: { isDefault: true } });
|
|
115
|
+
// Then set this as default
|
|
116
|
+
this.isDefault = true;
|
|
117
|
+
await this.save();
|
|
118
|
+
}
|
|
119
|
+
async removeAsDefault() {
|
|
120
|
+
this.isDefault = false;
|
|
121
|
+
await this.save();
|
|
122
|
+
}
|
|
123
|
+
getRoleDisplayName() {
|
|
124
|
+
return this.role
|
|
125
|
+
.split("_")
|
|
126
|
+
.map((word) => word.charAt(0) + word.slice(1).toLowerCase())
|
|
127
|
+
.join(" ");
|
|
128
|
+
}
|
|
129
|
+
static async getDefaultClearance() {
|
|
130
|
+
return await this.findOne({ where: { isDefault: true } });
|
|
131
|
+
}
|
|
132
|
+
static async findByRole(role) {
|
|
133
|
+
return await this.findOne({ where: { role } });
|
|
134
|
+
}
|
|
46
135
|
}
|
|
47
136
|
exports.SecurityClearance = SecurityClearance;
|
|
48
|
-
const initSecurityClearanceModel = (sequelize) => {
|
|
49
|
-
SecurityClearance.init({
|
|
50
|
-
id: {
|
|
51
|
-
type: vr_migrations_1.DataTypes.UUID,
|
|
52
|
-
defaultValue: vr_migrations_1.DataTypes.UUIDV4,
|
|
53
|
-
primaryKey: true,
|
|
54
|
-
},
|
|
55
|
-
role: {
|
|
56
|
-
type: vr_migrations_1.DataTypes.ENUM(...exports.USER_ROLES),
|
|
57
|
-
allowNull: false,
|
|
58
|
-
unique: true,
|
|
59
|
-
},
|
|
60
|
-
description: {
|
|
61
|
-
type: vr_migrations_1.DataTypes.TEXT,
|
|
62
|
-
allowNull: true,
|
|
63
|
-
},
|
|
64
|
-
level: {
|
|
65
|
-
type: vr_migrations_1.DataTypes.INTEGER,
|
|
66
|
-
allowNull: false,
|
|
67
|
-
},
|
|
68
|
-
permissions: {
|
|
69
|
-
type: vr_migrations_1.DataTypes.ARRAY(vr_migrations_1.DataTypes.STRING),
|
|
70
|
-
allowNull: false,
|
|
71
|
-
defaultValue: [],
|
|
72
|
-
},
|
|
73
|
-
isDefault: {
|
|
74
|
-
type: vr_migrations_1.DataTypes.BOOLEAN,
|
|
75
|
-
defaultValue: false,
|
|
76
|
-
},
|
|
77
|
-
createdAt: {
|
|
78
|
-
type: vr_migrations_1.DataTypes.DATE,
|
|
79
|
-
defaultValue: vr_migrations_1.DataTypes.NOW,
|
|
80
|
-
},
|
|
81
|
-
updatedAt: {
|
|
82
|
-
type: vr_migrations_1.DataTypes.DATE,
|
|
83
|
-
defaultValue: vr_migrations_1.DataTypes.NOW,
|
|
84
|
-
},
|
|
85
|
-
}, {
|
|
86
|
-
sequelize,
|
|
87
|
-
modelName: "SecurityClearance",
|
|
88
|
-
tableName: "security_clearances",
|
|
89
|
-
timestamps: true,
|
|
90
|
-
freezeTableName: true,
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
exports.initSecurityClearanceModel = initSecurityClearanceModel;
|