vr-models 1.0.56 → 1.0.58
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/contact.models.d.ts +71 -0
- package/dist/models/{phoneContact.models.js → contact.models.js} +93 -29
- package/dist/models/devicePaymentPlan.models.d.ts +3 -0
- package/dist/models/devicePaymentPlan.models.js +7 -0
- package/dist/models/index.d.ts +3 -3
- package/dist/models/index.js +2 -2
- package/dist/models/payment.models.d.ts +37 -18
- package/dist/models/payment.models.js +158 -44
- package/dist/models/paymentEventLog.models.d.ts +69 -0
- package/dist/models/paymentEventLog.models.js +204 -0
- package/dist/models/types.d.ts +2 -2
- package/dist/models/user.models.d.ts +13 -12
- package/dist/models/user.models.js +36 -26
- package/package.json +1 -1
- package/dist/models/phoneContact.models.d.ts +0 -71
- package/dist/models/transaction.models.d.ts +0 -44
- package/dist/models/transaction.models.js +0 -97
|
@@ -5,8 +5,11 @@ exports.User = exports.GENDER_OPTIONS = void 0;
|
|
|
5
5
|
const vr_migrations_1 = require("vr-migrations");
|
|
6
6
|
// ==================== GENDER OPTIONS ====================
|
|
7
7
|
exports.GENDER_OPTIONS = ["male", "female"];
|
|
8
|
+
// ==================== USER MODEL ====================
|
|
8
9
|
class User extends vr_migrations_1.Model {
|
|
9
|
-
//
|
|
10
|
+
// ===========================================================================
|
|
11
|
+
// INITIALIZATION
|
|
12
|
+
// ===========================================================================
|
|
10
13
|
static initialize(sequelize) {
|
|
11
14
|
this.init({
|
|
12
15
|
id: {
|
|
@@ -27,11 +30,6 @@ class User extends vr_migrations_1.Model {
|
|
|
27
30
|
allowNull: true,
|
|
28
31
|
unique: true,
|
|
29
32
|
},
|
|
30
|
-
email: {
|
|
31
|
-
type: vr_migrations_1.DataTypes.STRING(100),
|
|
32
|
-
allowNull: true,
|
|
33
|
-
unique: true,
|
|
34
|
-
},
|
|
35
33
|
password: {
|
|
36
34
|
type: vr_migrations_1.DataTypes.STRING,
|
|
37
35
|
allowNull: true,
|
|
@@ -73,7 +71,7 @@ class User extends vr_migrations_1.Model {
|
|
|
73
71
|
max: new Date().getFullYear(),
|
|
74
72
|
},
|
|
75
73
|
},
|
|
76
|
-
|
|
74
|
+
primaryContactId: {
|
|
77
75
|
type: vr_migrations_1.DataTypes.UUID,
|
|
78
76
|
allowNull: true,
|
|
79
77
|
},
|
|
@@ -125,7 +123,9 @@ class User extends vr_migrations_1.Model {
|
|
|
125
123
|
freezeTableName: true,
|
|
126
124
|
});
|
|
127
125
|
}
|
|
128
|
-
//
|
|
126
|
+
// ===========================================================================
|
|
127
|
+
// ASSOCIATIONS
|
|
128
|
+
// ===========================================================================
|
|
129
129
|
static associate(models) {
|
|
130
130
|
this.belongsTo(models.SecurityClearance, {
|
|
131
131
|
foreignKey: "securityClearanceId",
|
|
@@ -133,15 +133,16 @@ class User extends vr_migrations_1.Model {
|
|
|
133
133
|
onDelete: "RESTRICT",
|
|
134
134
|
onUpdate: "CASCADE",
|
|
135
135
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
// NEW: Contact associations (renamed from PhoneContact)
|
|
137
|
+
this.belongsTo(models.Contact, {
|
|
138
|
+
foreignKey: "primaryContactId",
|
|
139
|
+
as: "primaryContact",
|
|
139
140
|
onDelete: "SET NULL",
|
|
140
141
|
onUpdate: "CASCADE",
|
|
141
142
|
});
|
|
142
|
-
this.hasMany(models.
|
|
143
|
+
this.hasMany(models.Contact, {
|
|
143
144
|
foreignKey: "userId",
|
|
144
|
-
as: "
|
|
145
|
+
as: "contacts",
|
|
145
146
|
onDelete: "SET NULL",
|
|
146
147
|
onUpdate: "CASCADE",
|
|
147
148
|
});
|
|
@@ -170,7 +171,9 @@ class User extends vr_migrations_1.Model {
|
|
|
170
171
|
onUpdate: "CASCADE",
|
|
171
172
|
});
|
|
172
173
|
}
|
|
173
|
-
//
|
|
174
|
+
// ===========================================================================
|
|
175
|
+
// CUSTOM INSTANCE METHODS
|
|
176
|
+
// ===========================================================================
|
|
174
177
|
async softDelete(deletedBy, reason) {
|
|
175
178
|
this.deletion = {
|
|
176
179
|
deleted: true,
|
|
@@ -195,18 +198,25 @@ class User extends vr_migrations_1.Model {
|
|
|
195
198
|
this.deactivatedAt = null;
|
|
196
199
|
await this.save();
|
|
197
200
|
}
|
|
198
|
-
// Helper to
|
|
199
|
-
async
|
|
200
|
-
|
|
201
|
-
.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
201
|
+
// Helper to get primary verified contact
|
|
202
|
+
async getPrimaryVerifiedContact() {
|
|
203
|
+
if (this.primaryContactId) {
|
|
204
|
+
const ContactModel = this.constructor.sequelize.models.Contact;
|
|
205
|
+
return await ContactModel.findOne({
|
|
206
|
+
where: {
|
|
207
|
+
id: this.primaryContactId,
|
|
208
|
+
isVerified: true,
|
|
209
|
+
isActive: true,
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
// Helper to check if user has a verified contact of a specific type
|
|
216
|
+
async hasVerifiedContactType(type) {
|
|
217
|
+
if (!this.contacts)
|
|
218
|
+
return false;
|
|
219
|
+
return this.contacts.some((contact) => contact.type === type && contact.isVerified && contact.isActive);
|
|
210
220
|
}
|
|
211
221
|
// Helper to get full birth date as Date object
|
|
212
222
|
getBirthDate() {
|
package/package.json
CHANGED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
|
-
import type { User } from "./user.models";
|
|
3
|
-
export interface PhoneContactAttributes {
|
|
4
|
-
id: string;
|
|
5
|
-
phoneNumber: string;
|
|
6
|
-
userId: string | null;
|
|
7
|
-
isVerified: boolean;
|
|
8
|
-
verifiedAt: Date | null;
|
|
9
|
-
isPrimary: boolean;
|
|
10
|
-
isActive: boolean;
|
|
11
|
-
otp: string | null;
|
|
12
|
-
otpExpiresAt: Date | null;
|
|
13
|
-
metadata: {
|
|
14
|
-
lastOtpSentAt?: Date;
|
|
15
|
-
otpAttempts?: number;
|
|
16
|
-
lastFailedAttemptAt?: Date;
|
|
17
|
-
isLocked?: boolean;
|
|
18
|
-
lockedUntil: Date | null;
|
|
19
|
-
carrier?: string;
|
|
20
|
-
countryCode?: string;
|
|
21
|
-
deactivatedAt?: Date | null;
|
|
22
|
-
deactivationReason?: string;
|
|
23
|
-
};
|
|
24
|
-
createdAt: Date;
|
|
25
|
-
updatedAt: Date;
|
|
26
|
-
user?: NonAttribute<User>;
|
|
27
|
-
}
|
|
28
|
-
export interface PhoneContactCreationAttributes extends Omit<PhoneContactAttributes, "id" | "createdAt" | "updatedAt" | "metadata"> {
|
|
29
|
-
id?: string;
|
|
30
|
-
metadata?: Record<string, any>;
|
|
31
|
-
}
|
|
32
|
-
export declare class PhoneContact extends Model<InferAttributes<PhoneContact>, InferCreationAttributes<PhoneContact>> implements PhoneContactAttributes {
|
|
33
|
-
id: CreationOptional<string>;
|
|
34
|
-
phoneNumber: string;
|
|
35
|
-
userId: CreationOptional<string | null>;
|
|
36
|
-
isVerified: CreationOptional<boolean>;
|
|
37
|
-
verifiedAt: CreationOptional<Date | null>;
|
|
38
|
-
isPrimary: CreationOptional<boolean>;
|
|
39
|
-
isActive: CreationOptional<boolean>;
|
|
40
|
-
otp: CreationOptional<string | null>;
|
|
41
|
-
otpExpiresAt: CreationOptional<Date | null>;
|
|
42
|
-
metadata: CreationOptional<{
|
|
43
|
-
lastOtpSentAt?: Date;
|
|
44
|
-
otpAttempts?: number;
|
|
45
|
-
lastFailedAttemptAt?: Date;
|
|
46
|
-
isLocked?: boolean;
|
|
47
|
-
lockedUntil: Date | null;
|
|
48
|
-
carrier?: string;
|
|
49
|
-
countryCode?: string;
|
|
50
|
-
deactivatedAt?: Date | null;
|
|
51
|
-
deactivationReason?: string;
|
|
52
|
-
}>;
|
|
53
|
-
readonly createdAt: CreationOptional<Date>;
|
|
54
|
-
readonly updatedAt: CreationOptional<Date>;
|
|
55
|
-
user?: NonAttribute<User>;
|
|
56
|
-
static initialize(sequelize: any): void;
|
|
57
|
-
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
58
|
-
deactivate(reason?: string): Promise<void>;
|
|
59
|
-
reactivate(): Promise<void>;
|
|
60
|
-
isLocked(): boolean;
|
|
61
|
-
getRemainingLockTime(): number | null;
|
|
62
|
-
isExpired(): boolean;
|
|
63
|
-
getRemainingOTPTime(): number | null;
|
|
64
|
-
static findByPhoneNumber(phoneNumber: string): Promise<PhoneContact | null>;
|
|
65
|
-
static findVerifiedByPhoneNumber(phoneNumber: string): Promise<PhoneContact | null>;
|
|
66
|
-
static getUserPrimaryPhone(userId: string): Promise<PhoneContact | null>;
|
|
67
|
-
static getUserPhones(userId: string): Promise<PhoneContact[]>;
|
|
68
|
-
static isPhoneNumberAvailable(phoneNumber: string): Promise<boolean>;
|
|
69
|
-
static cleanupExpiredOTPs(): Promise<void>;
|
|
70
|
-
}
|
|
71
|
-
export type PhoneContactModel = typeof PhoneContact;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Model, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ModelStatic } from "vr-migrations";
|
|
2
|
-
import type { Payment } from "./payment.models";
|
|
3
|
-
import type { User } from "./user.models";
|
|
4
|
-
export type TransactionStatus = "succeeded" | "failed";
|
|
5
|
-
export interface TransactionAttributes {
|
|
6
|
-
id: string;
|
|
7
|
-
userId: string;
|
|
8
|
-
paymentId: string;
|
|
9
|
-
amount: number;
|
|
10
|
-
status: TransactionStatus;
|
|
11
|
-
providerReference: string;
|
|
12
|
-
metadata: Record<string, any>;
|
|
13
|
-
createdAt: Date;
|
|
14
|
-
updatedAt: Date;
|
|
15
|
-
payment?: Payment;
|
|
16
|
-
user?: User;
|
|
17
|
-
}
|
|
18
|
-
export interface TransactionCreationAttributes extends Omit<TransactionAttributes, "id" | "createdAt" | "updatedAt" | "metadata"> {
|
|
19
|
-
id?: string;
|
|
20
|
-
metadata?: Record<string, any>;
|
|
21
|
-
}
|
|
22
|
-
export declare class Transaction extends Model<InferAttributes<Transaction>, InferCreationAttributes<Transaction>> implements TransactionAttributes {
|
|
23
|
-
id: CreationOptional<string>;
|
|
24
|
-
userId: string;
|
|
25
|
-
paymentId: string;
|
|
26
|
-
amount: number;
|
|
27
|
-
status: TransactionStatus;
|
|
28
|
-
providerReference: string;
|
|
29
|
-
metadata: CreationOptional<Record<string, any>>;
|
|
30
|
-
readonly createdAt: CreationOptional<Date>;
|
|
31
|
-
readonly updatedAt: CreationOptional<Date>;
|
|
32
|
-
payment?: NonAttribute<Payment>;
|
|
33
|
-
user?: NonAttribute<User>;
|
|
34
|
-
static initialize(sequelize: any): void;
|
|
35
|
-
static associate(models: Record<string, ModelStatic<Model>>): void;
|
|
36
|
-
markAsSucceeded(metadata?: Record<string, any>): Promise<void>;
|
|
37
|
-
markAsFailed(reason: string, metadata?: Record<string, any>): Promise<void>;
|
|
38
|
-
isSuccessful(): boolean;
|
|
39
|
-
isFailed(): boolean;
|
|
40
|
-
getFormattedAmount(): string;
|
|
41
|
-
static getUserTransactions(userId: string, limit?: number): Promise<Transaction[]>;
|
|
42
|
-
static getPaymentTransactions(paymentId: string): Promise<Transaction[]>;
|
|
43
|
-
}
|
|
44
|
-
export type TransactionModel = typeof Transaction;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Transaction = void 0;
|
|
4
|
-
const vr_migrations_1 = require("vr-migrations");
|
|
5
|
-
class Transaction extends vr_migrations_1.Model {
|
|
6
|
-
// Static initialization method
|
|
7
|
-
static initialize(sequelize) {
|
|
8
|
-
this.init({
|
|
9
|
-
id: {
|
|
10
|
-
type: vr_migrations_1.DataTypes.UUID,
|
|
11
|
-
defaultValue: vr_migrations_1.DataTypes.UUIDV4,
|
|
12
|
-
primaryKey: true,
|
|
13
|
-
},
|
|
14
|
-
userId: { type: vr_migrations_1.DataTypes.UUID, allowNull: false },
|
|
15
|
-
paymentId: { type: vr_migrations_1.DataTypes.UUID, allowNull: false },
|
|
16
|
-
amount: {
|
|
17
|
-
type: vr_migrations_1.DataTypes.FLOAT,
|
|
18
|
-
allowNull: false,
|
|
19
|
-
validate: { min: 1 },
|
|
20
|
-
},
|
|
21
|
-
status: {
|
|
22
|
-
type: vr_migrations_1.DataTypes.ENUM("succeeded", "failed"),
|
|
23
|
-
allowNull: false,
|
|
24
|
-
},
|
|
25
|
-
providerReference: { type: vr_migrations_1.DataTypes.STRING, allowNull: false },
|
|
26
|
-
metadata: {
|
|
27
|
-
type: vr_migrations_1.DataTypes.JSONB,
|
|
28
|
-
allowNull: false,
|
|
29
|
-
defaultValue: {},
|
|
30
|
-
},
|
|
31
|
-
createdAt: { type: vr_migrations_1.DataTypes.DATE, defaultValue: vr_migrations_1.DataTypes.NOW },
|
|
32
|
-
updatedAt: { type: vr_migrations_1.DataTypes.DATE, defaultValue: vr_migrations_1.DataTypes.NOW },
|
|
33
|
-
}, {
|
|
34
|
-
sequelize,
|
|
35
|
-
tableName: "transactions",
|
|
36
|
-
modelName: "Transaction",
|
|
37
|
-
timestamps: true,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
// Static association method
|
|
41
|
-
static associate(models) {
|
|
42
|
-
this.belongsTo(models.Payment, {
|
|
43
|
-
foreignKey: "paymentId",
|
|
44
|
-
as: "payment",
|
|
45
|
-
onDelete: "SET NULL", // ← This is SET NULL, not CASCADE
|
|
46
|
-
onUpdate: "CASCADE",
|
|
47
|
-
});
|
|
48
|
-
this.belongsTo(models.User, {
|
|
49
|
-
foreignKey: "userId",
|
|
50
|
-
as: "user",
|
|
51
|
-
onDelete: "RESTRICT",
|
|
52
|
-
onUpdate: "CASCADE",
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
// Custom instance methods
|
|
56
|
-
async markAsSucceeded(metadata) {
|
|
57
|
-
this.status = "succeeded";
|
|
58
|
-
if (metadata) {
|
|
59
|
-
this.metadata = { ...this.metadata, ...metadata };
|
|
60
|
-
}
|
|
61
|
-
await this.save();
|
|
62
|
-
}
|
|
63
|
-
async markAsFailed(reason, metadata) {
|
|
64
|
-
this.status = "failed";
|
|
65
|
-
const failureMetadata = {
|
|
66
|
-
failureReason: reason,
|
|
67
|
-
failedAt: new Date().toISOString(),
|
|
68
|
-
...metadata,
|
|
69
|
-
};
|
|
70
|
-
this.metadata = { ...this.metadata, ...failureMetadata };
|
|
71
|
-
await this.save();
|
|
72
|
-
}
|
|
73
|
-
isSuccessful() {
|
|
74
|
-
return this.status === "succeeded";
|
|
75
|
-
}
|
|
76
|
-
isFailed() {
|
|
77
|
-
return this.status === "failed";
|
|
78
|
-
}
|
|
79
|
-
getFormattedAmount() {
|
|
80
|
-
return `RWF ${this.amount.toLocaleString()}`;
|
|
81
|
-
}
|
|
82
|
-
static async getUserTransactions(userId, limit = 50) {
|
|
83
|
-
return await this.findAll({
|
|
84
|
-
where: { userId },
|
|
85
|
-
order: [["createdAt", "DESC"]],
|
|
86
|
-
limit,
|
|
87
|
-
include: ["payment"],
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
static async getPaymentTransactions(paymentId) {
|
|
91
|
-
return await this.findAll({
|
|
92
|
-
where: { paymentId },
|
|
93
|
-
order: [["createdAt", "DESC"]],
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
exports.Transaction = Transaction;
|