@valentine-efagene/qshelter-common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OpenApiHelper.ts +121 -0
- package/decorator/permission.decorator.ts +4 -0
- package/decorator/tenant.decorator.ts +16 -0
- package/dist/entities/BaseEntity.d.ts +11 -0
- package/dist/entities/BaseEntity.js +54 -0
- package/dist/entities/BaseEntity.js.map +1 -0
- package/dist/entities/TenantAwareEntity.d.ts +10 -0
- package/dist/entities/TenantAwareEntity.js +52 -0
- package/dist/entities/TenantAwareEntity.js.map +1 -0
- package/dist/entities/TenantAwareRepository.d.ts +13 -0
- package/dist/entities/TenantAwareRepository.js +65 -0
- package/dist/entities/TenantAwareRepository.js.map +1 -0
- package/dist/entities/amenity.entity.d.ts +4 -0
- package/dist/entities/amenity.entity.js +27 -0
- package/dist/entities/amenity.entity.js.map +1 -0
- package/dist/entities/common.entity.d.ts +17 -0
- package/dist/entities/common.entity.js +63 -0
- package/dist/entities/common.entity.js.map +1 -0
- package/dist/entities/common.pure.entity.d.ts +11 -0
- package/dist/entities/common.pure.entity.js +51 -0
- package/dist/entities/common.pure.entity.js.map +1 -0
- package/dist/entities/index.d.ts +27 -0
- package/dist/entities/index.js +44 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/mortgage-document.entity.d.ts +14 -0
- package/dist/entities/mortgage-document.entity.js +58 -0
- package/dist/entities/mortgage-document.entity.js.map +1 -0
- package/dist/entities/mortgage-downpayment-installment.entity.d.ts +19 -0
- package/dist/entities/mortgage-downpayment-installment.entity.js +63 -0
- package/dist/entities/mortgage-downpayment-installment.entity.js.map +1 -0
- package/dist/entities/mortgage-downpayment-payment.entity.d.ts +28 -0
- package/dist/entities/mortgage-downpayment-payment.entity.js +84 -0
- package/dist/entities/mortgage-downpayment-payment.entity.js.map +1 -0
- package/dist/entities/mortgage-downpayment.entity.d.ts +22 -0
- package/dist/entities/mortgage-downpayment.entity.js +66 -0
- package/dist/entities/mortgage-downpayment.entity.js.map +1 -0
- package/dist/entities/mortgage-step.entity.d.ts +12 -0
- package/dist/entities/mortgage-step.entity.js +52 -0
- package/dist/entities/mortgage-step.entity.js.map +1 -0
- package/dist/entities/mortgage-type.entity.d.ts +10 -0
- package/dist/entities/mortgage-type.entity.js +46 -0
- package/dist/entities/mortgage-type.entity.js.map +1 -0
- package/dist/entities/mortgage.entity.d.ts +37 -0
- package/dist/entities/mortgage.entity.js +124 -0
- package/dist/entities/mortgage.entity.js.map +1 -0
- package/dist/entities/password_reset_tokens.entity.d.ts +7 -0
- package/dist/entities/password_reset_tokens.entity.js +43 -0
- package/dist/entities/password_reset_tokens.entity.js.map +1 -0
- package/dist/entities/permission.entity.d.ts +6 -0
- package/dist/entities/permission.entity.js +30 -0
- package/dist/entities/permission.entity.js.map +1 -0
- package/dist/entities/property-document.entity.d.ts +6 -0
- package/dist/entities/property-document.entity.js +34 -0
- package/dist/entities/property-document.entity.js.map +1 -0
- package/dist/entities/property-media.entity.d.ts +6 -0
- package/dist/entities/property-media.entity.js +36 -0
- package/dist/entities/property-media.entity.js.map +1 -0
- package/dist/entities/property.entity.d.ts +36 -0
- package/dist/entities/property.entity.js +182 -0
- package/dist/entities/property.entity.js.map +1 -0
- package/dist/entities/refresh_token.entity.d.ts +7 -0
- package/dist/entities/refresh_token.entity.js +35 -0
- package/dist/entities/refresh_token.entity.js.map +1 -0
- package/dist/entities/role.entity.d.ts +8 -0
- package/dist/entities/role.entity.js +39 -0
- package/dist/entities/role.entity.js.map +1 -0
- package/dist/entities/settings.entity.d.ts +17 -0
- package/dist/entities/settings.entity.js +79 -0
- package/dist/entities/settings.entity.js.map +1 -0
- package/dist/entities/social.entity.d.ts +8 -0
- package/dist/entities/social.entity.js +46 -0
- package/dist/entities/social.entity.js.map +1 -0
- package/dist/entities/tenant.entity.d.ts +29 -0
- package/dist/entities/tenant.entity.js +82 -0
- package/dist/entities/tenant.entity.js.map +1 -0
- package/dist/entities/transaction.entity.d.ts +17 -0
- package/dist/entities/transaction.entity.js +84 -0
- package/dist/entities/transaction.entity.js.map +1 -0
- package/dist/entities/user.entity.d.ts +26 -0
- package/dist/entities/user.entity.js +103 -0
- package/dist/entities/user.entity.js.map +1 -0
- package/dist/entities/user_suspensions.entity.d.ts +7 -0
- package/dist/entities/user_suspensions.entity.js +42 -0
- package/dist/entities/user_suspensions.entity.js.map +1 -0
- package/dist/entities/wallet.entity.d.ts +17 -0
- package/dist/entities/wallet.entity.js +79 -0
- package/dist/entities/wallet.entity.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/pagination/index.d.ts +2 -0
- package/dist/pagination/index.js +19 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/pagination/pagination.helper.d.ts +7 -0
- package/dist/pagination/pagination.helper.js +40 -0
- package/dist/pagination/pagination.helper.js.map +1 -0
- package/dist/pagination/pagination.types.d.ts +19 -0
- package/dist/pagination/pagination.types.js +3 -0
- package/dist/pagination/pagination.types.js.map +1 -0
- package/dist/standard-response.d.ts +7 -0
- package/dist/standard-response.js +27 -0
- package/dist/standard-response.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/common.type.d.ts +26 -0
- package/dist/types/common.type.js +26 -0
- package/dist/types/common.type.js.map +1 -0
- package/dist/types/mortgage-fsm.types.d.ts +180 -0
- package/dist/types/mortgage-fsm.types.js +130 -0
- package/dist/types/mortgage-fsm.types.js.map +1 -0
- package/dist/types/policy.types.d.ts +18 -0
- package/dist/types/policy.types.js +3 -0
- package/dist/types/policy.types.js.map +1 -0
- package/dist/types/property.type.d.ts +9 -0
- package/dist/types/property.type.js +15 -0
- package/dist/types/property.type.js.map +1 -0
- package/dist/types/social.enums.d.ts +15 -0
- package/dist/types/social.enums.js +22 -0
- package/dist/types/social.enums.js.map +1 -0
- package/dist/types/tenant.enums.d.ts +13 -0
- package/dist/types/tenant.enums.js +19 -0
- package/dist/types/tenant.enums.js.map +1 -0
- package/dist/types/transaction.type.d.ts +8 -0
- package/dist/types/transaction.type.js +14 -0
- package/dist/types/transaction.type.js.map +1 -0
- package/dist/types/user.enums.d.ts +10 -0
- package/dist/types/user.enums.js +16 -0
- package/dist/types/user.enums.js.map +1 -0
- package/entities/BaseEntity.ts +34 -0
- package/entities/TenantAwareEntity.ts +34 -0
- package/entities/TenantAwareRepository.ts +100 -0
- package/entities/amenity.entity.ts +10 -0
- package/entities/common.entity.ts +46 -0
- package/entities/common.pure.entity.ts +36 -0
- package/entities/index.ts +27 -0
- package/entities/mortgage-document.entity.ts +37 -0
- package/entities/mortgage-downpayment-installment.entity.ts +40 -0
- package/entities/mortgage-downpayment-payment.entity.ts +61 -0
- package/entities/mortgage-downpayment.entity.ts +43 -0
- package/entities/mortgage-step.entity.ts +33 -0
- package/entities/mortgage-type.entity.ts +31 -0
- package/entities/mortgage.entity.ts +89 -0
- package/entities/password_reset_tokens.entity.ts +25 -0
- package/entities/permission.entity.ts +12 -0
- package/entities/property-document.entity.ts +21 -0
- package/entities/property-media.entity.ts +23 -0
- package/entities/property.entity.ts +147 -0
- package/entities/refresh_token.entity.ts +16 -0
- package/entities/role.entity.ts +20 -0
- package/entities/settings.entity.ts +56 -0
- package/entities/social.entity.ts +27 -0
- package/entities/tenant.entity.ts +65 -0
- package/entities/transaction.entity.ts +56 -0
- package/entities/user.entity.ts +89 -0
- package/entities/user_suspensions.entity.ts +24 -0
- package/entities/wallet.entity.ts +54 -0
- package/guard/permission.guard.ts +42 -0
- package/guard/swagger-auth.guard.ts +9 -0
- package/helpers/ArrayHelper.ts +1 -0
- package/helpers/ConstantHelper.ts +101 -0
- package/helpers/CustomNamingStrategy.ts +27 -0
- package/helpers/DateHelper.ts +21 -0
- package/helpers/EmailHelper.ts +38 -0
- package/helpers/FileSystemHelper.ts +101 -0
- package/index.ts +9 -0
- package/middleware/TenantMiddleware.ts +52 -0
- package/package.json +46 -0
- package/pagination/index.ts +2 -0
- package/pagination/pagination.helper.ts +57 -0
- package/pagination/pagination.types.ts +21 -0
- package/standard-response.ts +16 -0
- package/tsconfig.json +33 -0
- package/types/common.type.ts +32 -0
- package/types/mortgage-fsm.types.ts +279 -0
- package/types/policy.types.ts +21 -0
- package/types/property.type.ts +10 -0
- package/types/social.enums.ts +17 -0
- package/types/tenant.enums.ts +14 -0
- package/types/transaction.type.ts +9 -0
- package/types/user.enums.ts +11 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, OneToOne } from 'typeorm';
|
|
2
|
+
import { PropertyDocument } from './property-document.entity';
|
|
3
|
+
import { PropertyMedia } from './property-media.entity';
|
|
4
|
+
import { User } from './user.entity';
|
|
5
|
+
import { Amenity } from './amenity.entity';
|
|
6
|
+
import { AbstractBaseReviewableEntity } from './common.entity';
|
|
7
|
+
import { Mortgage } from './mortgage.entity';
|
|
8
|
+
import { PropertyStatus, PropertyType } from '../types/property.type';
|
|
9
|
+
import { Currency, PropertyCategory } from '../types/social.enums';
|
|
10
|
+
|
|
11
|
+
@Entity({ name: 'property' })
|
|
12
|
+
export class Property extends AbstractBaseReviewableEntity {
|
|
13
|
+
@ManyToOne(() => User, {
|
|
14
|
+
//eager: true,
|
|
15
|
+
onDelete: 'CASCADE',
|
|
16
|
+
onUpdate: 'CASCADE',
|
|
17
|
+
})
|
|
18
|
+
@JoinColumn({ name: 'user_id' })
|
|
19
|
+
user: User;
|
|
20
|
+
|
|
21
|
+
@Column({ nullable: true })
|
|
22
|
+
userId: number;
|
|
23
|
+
|
|
24
|
+
@OneToMany(
|
|
25
|
+
() => PropertyDocument,
|
|
26
|
+
(propertyDocument) => propertyDocument.property,
|
|
27
|
+
)
|
|
28
|
+
documents: PropertyDocument[];
|
|
29
|
+
|
|
30
|
+
@ManyToMany(() => Amenity)
|
|
31
|
+
@JoinTable()
|
|
32
|
+
amenities: Amenity[]
|
|
33
|
+
|
|
34
|
+
@OneToMany(
|
|
35
|
+
() => PropertyMedia,
|
|
36
|
+
(propertyDocument) => propertyDocument.property,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
media: PropertyMedia[];
|
|
40
|
+
|
|
41
|
+
@OneToMany(() => Mortgage, (mortgage) => mortgage.property)
|
|
42
|
+
mortgages: Mortgage[];
|
|
43
|
+
@OneToOne(() => PropertyMedia, {
|
|
44
|
+
onDelete: 'SET NULL', // prevents FK errors if image is deleted
|
|
45
|
+
onUpdate: 'CASCADE'
|
|
46
|
+
})
|
|
47
|
+
@JoinColumn({ name: 'display_image_id' })
|
|
48
|
+
displayImage: PropertyMedia;
|
|
49
|
+
|
|
50
|
+
@Column({
|
|
51
|
+
nullable: true
|
|
52
|
+
})
|
|
53
|
+
displayImageId: number
|
|
54
|
+
|
|
55
|
+
@Column({ nullable: true })
|
|
56
|
+
title: string;
|
|
57
|
+
|
|
58
|
+
@Column({
|
|
59
|
+
nullable: true,
|
|
60
|
+
type: 'enum',
|
|
61
|
+
enum: PropertyCategory,
|
|
62
|
+
})
|
|
63
|
+
category: PropertyCategory;
|
|
64
|
+
|
|
65
|
+
@Column({
|
|
66
|
+
nullable: true,
|
|
67
|
+
type: 'enum',
|
|
68
|
+
enum: PropertyType
|
|
69
|
+
})
|
|
70
|
+
propertyType: string;
|
|
71
|
+
|
|
72
|
+
@Column({ nullable: true })
|
|
73
|
+
country: string;
|
|
74
|
+
|
|
75
|
+
@Column({
|
|
76
|
+
nullable: true,
|
|
77
|
+
type: 'enum',
|
|
78
|
+
enum: Currency,
|
|
79
|
+
})
|
|
80
|
+
currency: Currency;
|
|
81
|
+
|
|
82
|
+
@Column({ nullable: true })
|
|
83
|
+
city: string;
|
|
84
|
+
|
|
85
|
+
@Column({ nullable: true })
|
|
86
|
+
district: string;
|
|
87
|
+
|
|
88
|
+
@Column({ nullable: true })
|
|
89
|
+
zipCode: string;
|
|
90
|
+
|
|
91
|
+
@Column({ nullable: true })
|
|
92
|
+
streetAddress: string;
|
|
93
|
+
|
|
94
|
+
@Column({ nullable: false })
|
|
95
|
+
nBedrooms: string
|
|
96
|
+
|
|
97
|
+
@Column({ nullable: false })
|
|
98
|
+
nBathrooms: string
|
|
99
|
+
|
|
100
|
+
@Column({ nullable: false })
|
|
101
|
+
nParkingSpots: string
|
|
102
|
+
|
|
103
|
+
@Column({
|
|
104
|
+
type: 'double precision',
|
|
105
|
+
scale: 2,
|
|
106
|
+
precision: 20,
|
|
107
|
+
nullable: true,
|
|
108
|
+
})
|
|
109
|
+
price: number
|
|
110
|
+
|
|
111
|
+
@Column({
|
|
112
|
+
type: 'double precision',
|
|
113
|
+
scale: 2,
|
|
114
|
+
precision: 20,
|
|
115
|
+
nullable: true,
|
|
116
|
+
})
|
|
117
|
+
longitude: number
|
|
118
|
+
|
|
119
|
+
@Column({
|
|
120
|
+
type: 'double precision',
|
|
121
|
+
scale: 2,
|
|
122
|
+
precision: 20,
|
|
123
|
+
nullable: true,
|
|
124
|
+
})
|
|
125
|
+
latitude: number
|
|
126
|
+
|
|
127
|
+
@Column({
|
|
128
|
+
type: 'double precision',
|
|
129
|
+
scale: 2,
|
|
130
|
+
precision: 20,
|
|
131
|
+
nullable: true,
|
|
132
|
+
})
|
|
133
|
+
area: number
|
|
134
|
+
|
|
135
|
+
@Column({
|
|
136
|
+
type: 'text',
|
|
137
|
+
nullable: true
|
|
138
|
+
})
|
|
139
|
+
description: string
|
|
140
|
+
|
|
141
|
+
@Column({
|
|
142
|
+
type: 'enum',
|
|
143
|
+
enum: PropertyStatus,
|
|
144
|
+
default: PropertyStatus.PENDING,
|
|
145
|
+
})
|
|
146
|
+
status: PropertyStatus;
|
|
147
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
|
|
2
|
+
import { BaseEntity } from './BaseEntity';
|
|
3
|
+
import { User } from './user.entity';
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'refresh_tokens' })
|
|
6
|
+
export class RefreshToken extends BaseEntity {
|
|
7
|
+
@ManyToOne(() => User, (user) => user.refreshTokens)
|
|
8
|
+
@JoinColumn({ name: 'user_id' })
|
|
9
|
+
user: User;
|
|
10
|
+
|
|
11
|
+
@Column({ nullable: true })
|
|
12
|
+
userId: number;
|
|
13
|
+
|
|
14
|
+
@Column({ nullable: false, type: 'text' })
|
|
15
|
+
token: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Column, Entity, JoinTable, ManyToMany } from 'typeorm';
|
|
2
|
+
import { Permission } from './permission.entity';
|
|
3
|
+
import { User } from './user.entity';
|
|
4
|
+
import { BaseEntity } from './BaseEntity';
|
|
5
|
+
|
|
6
|
+
@Entity({ name: 'roles' })
|
|
7
|
+
export class Role extends BaseEntity {
|
|
8
|
+
@Column({ nullable: true })
|
|
9
|
+
name: string;
|
|
10
|
+
|
|
11
|
+
@ManyToMany(() => Permission, (permission) => permission.roles, {
|
|
12
|
+
onDelete: 'CASCADE',
|
|
13
|
+
eager: true
|
|
14
|
+
})
|
|
15
|
+
@JoinTable()
|
|
16
|
+
permissions: Permission[]
|
|
17
|
+
|
|
18
|
+
@ManyToMany(() => User, (user) => user.roles)
|
|
19
|
+
users: User[]
|
|
20
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
|
2
|
+
import { PropertyMedia } from './property-media.entity';
|
|
3
|
+
import { User } from './user.entity';
|
|
4
|
+
import { AbstractBaseReviewableEntity } from './common.entity';
|
|
5
|
+
import { Status } from '../types/common.type';
|
|
6
|
+
|
|
7
|
+
@Entity({ name: 'settings' })
|
|
8
|
+
export class Settings extends AbstractBaseReviewableEntity {
|
|
9
|
+
@ManyToOne(() => User, {
|
|
10
|
+
//eager: true,
|
|
11
|
+
onDelete: 'CASCADE',
|
|
12
|
+
onUpdate: 'CASCADE',
|
|
13
|
+
})
|
|
14
|
+
@JoinColumn({ name: 'created_by' })
|
|
15
|
+
creator: User;
|
|
16
|
+
|
|
17
|
+
@Column({ nullable: true })
|
|
18
|
+
createdBy: number;
|
|
19
|
+
|
|
20
|
+
@OneToMany(
|
|
21
|
+
() => PropertyMedia,
|
|
22
|
+
(PropertyMedia) => PropertyMedia.property,
|
|
23
|
+
)
|
|
24
|
+
media: PropertyMedia[];
|
|
25
|
+
|
|
26
|
+
@Column({ nullable: true })
|
|
27
|
+
title: string;
|
|
28
|
+
|
|
29
|
+
@Column()
|
|
30
|
+
location: string;
|
|
31
|
+
|
|
32
|
+
@Column()
|
|
33
|
+
startTime: Date;
|
|
34
|
+
|
|
35
|
+
@Column()
|
|
36
|
+
endTime: Date;
|
|
37
|
+
|
|
38
|
+
@Column({ default: true })
|
|
39
|
+
isPrivate: boolean;
|
|
40
|
+
|
|
41
|
+
@Column({ nullable: true })
|
|
42
|
+
qrOfflineCode: string;
|
|
43
|
+
|
|
44
|
+
@Column({
|
|
45
|
+
type: 'text',
|
|
46
|
+
nullable: true
|
|
47
|
+
})
|
|
48
|
+
description: string
|
|
49
|
+
|
|
50
|
+
@Column({
|
|
51
|
+
type: 'enum',
|
|
52
|
+
enum: Status,
|
|
53
|
+
default: Status.PENDING,
|
|
54
|
+
})
|
|
55
|
+
status: Status;
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
|
|
2
|
+
import { User } from './user.entity';
|
|
3
|
+
import { AbstractBaseReviewableEntity } from './common.entity';
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'social' })
|
|
6
|
+
export class Social extends AbstractBaseReviewableEntity {
|
|
7
|
+
@ManyToOne(() => User, {
|
|
8
|
+
//eager: true,
|
|
9
|
+
onDelete: 'CASCADE',
|
|
10
|
+
onUpdate: 'CASCADE',
|
|
11
|
+
})
|
|
12
|
+
@JoinColumn({ name: 'user_id' })
|
|
13
|
+
user: User;
|
|
14
|
+
|
|
15
|
+
@Column({ nullable: true })
|
|
16
|
+
userId: number;
|
|
17
|
+
|
|
18
|
+
@Column({
|
|
19
|
+
nullable: true,
|
|
20
|
+
})
|
|
21
|
+
brand: string;
|
|
22
|
+
|
|
23
|
+
@Column({
|
|
24
|
+
nullable: true,
|
|
25
|
+
})
|
|
26
|
+
link: string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Entity, Column, Index, Unique } from 'typeorm';
|
|
2
|
+
import { BaseEntity } from './BaseEntity';
|
|
3
|
+
import { TenantStatus, TenantPlan } from '../types/tenant.enums';
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'tenants' })
|
|
6
|
+
@Unique(['subdomain'])
|
|
7
|
+
@Unique(['domain'])
|
|
8
|
+
export class Tenant extends BaseEntity {
|
|
9
|
+
@Column({ length: 255 })
|
|
10
|
+
name: string;
|
|
11
|
+
|
|
12
|
+
@Column({ length: 100, unique: true })
|
|
13
|
+
@Index()
|
|
14
|
+
subdomain: string; // e.g., 'acme' for acme.yourdomain.com
|
|
15
|
+
|
|
16
|
+
@Column({ length: 255, nullable: true, unique: true })
|
|
17
|
+
domain: string; // Optional custom domain: e.g., 'realestate.acme.com'
|
|
18
|
+
|
|
19
|
+
@Column({ type: 'varchar', default: TenantStatus.ACTIVE })
|
|
20
|
+
status: TenantStatus;
|
|
21
|
+
|
|
22
|
+
@Column({ type: 'varchar', default: TenantPlan.FREE })
|
|
23
|
+
plan: TenantPlan;
|
|
24
|
+
|
|
25
|
+
@Column({ type: 'json', nullable: true })
|
|
26
|
+
config: {
|
|
27
|
+
maxUsers?: number;
|
|
28
|
+
maxProperties?: number;
|
|
29
|
+
features?: string[];
|
|
30
|
+
customBranding?: {
|
|
31
|
+
logo?: string;
|
|
32
|
+
primaryColor?: string;
|
|
33
|
+
secondaryColor?: string;
|
|
34
|
+
};
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
@Column({ type: 'json', nullable: true })
|
|
39
|
+
metadata: any; // Additional tenant-specific metadata
|
|
40
|
+
|
|
41
|
+
@Column({ type: 'timestamp', nullable: true })
|
|
42
|
+
trialEndsAt: Date;
|
|
43
|
+
|
|
44
|
+
@Column({ type: 'timestamp', nullable: true })
|
|
45
|
+
subscriptionEndsAt: Date;
|
|
46
|
+
|
|
47
|
+
// Contact information
|
|
48
|
+
@Column({ length: 255, nullable: true })
|
|
49
|
+
contactEmail: string;
|
|
50
|
+
|
|
51
|
+
@Column({ length: 50, nullable: true })
|
|
52
|
+
contactPhone: string;
|
|
53
|
+
|
|
54
|
+
// Database strategy (for future use if migrating to separate databases per tenant)
|
|
55
|
+
@Column({ type: 'varchar', default: 'shared' })
|
|
56
|
+
databaseStrategy: 'shared' | 'isolated';
|
|
57
|
+
|
|
58
|
+
@Column({ length: 255, nullable: true })
|
|
59
|
+
databaseHost: string;
|
|
60
|
+
|
|
61
|
+
@Column({ length: 100, nullable: true })
|
|
62
|
+
databaseName: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default Tenant;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
|
2
|
+
import { Provider, TransactionType } from '../types/transaction.type';
|
|
3
|
+
import { Wallet } from './wallet.entity';
|
|
4
|
+
import { User } from './user.entity';
|
|
5
|
+
|
|
6
|
+
@Entity({ name: 'prod_transactions' })
|
|
7
|
+
export class Transaction {
|
|
8
|
+
@PrimaryGeneratedColumn()
|
|
9
|
+
id: number;
|
|
10
|
+
|
|
11
|
+
@Column({
|
|
12
|
+
type: 'enum',
|
|
13
|
+
enum: TransactionType
|
|
14
|
+
})
|
|
15
|
+
type: TransactionType
|
|
16
|
+
|
|
17
|
+
@ManyToOne(() => Wallet, wallet => wallet.transactions, {
|
|
18
|
+
onDelete: 'CASCADE',
|
|
19
|
+
onUpdate: 'CASCADE',
|
|
20
|
+
})
|
|
21
|
+
@JoinColumn({ name: 'wallet_id' })
|
|
22
|
+
wallet: Wallet;
|
|
23
|
+
|
|
24
|
+
@Column()
|
|
25
|
+
walletId: number
|
|
26
|
+
|
|
27
|
+
@ManyToOne(() => User, (user) => user.transactions)
|
|
28
|
+
@JoinColumn({ name: 'user_id' })
|
|
29
|
+
user: User;
|
|
30
|
+
|
|
31
|
+
@Column()
|
|
32
|
+
userId: number
|
|
33
|
+
|
|
34
|
+
@Column({
|
|
35
|
+
type: 'enum',
|
|
36
|
+
enum: Provider
|
|
37
|
+
})
|
|
38
|
+
provider: Provider
|
|
39
|
+
|
|
40
|
+
@Column()
|
|
41
|
+
ref: string
|
|
42
|
+
|
|
43
|
+
@Column({
|
|
44
|
+
type: 'text'
|
|
45
|
+
})
|
|
46
|
+
metadata: string
|
|
47
|
+
|
|
48
|
+
@Column({ type: 'decimal', precision: 65, scale: 2, nullable: true })
|
|
49
|
+
amount: number;
|
|
50
|
+
|
|
51
|
+
@CreateDateColumn()
|
|
52
|
+
createdAt: Date;
|
|
53
|
+
|
|
54
|
+
@UpdateDateColumn()
|
|
55
|
+
updatedAt: Date;
|
|
56
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Column, Entity, JoinTable, ManyToMany, OneToMany } from 'typeorm';
|
|
2
|
+
import { TenantAwareBaseEntity } from './BaseEntity';
|
|
3
|
+
import { UserStatus } from '../types/user.enums';
|
|
4
|
+
import { Role } from './role.entity';
|
|
5
|
+
import { RefreshToken } from './refresh_token.entity';
|
|
6
|
+
import { Property } from './property.entity';
|
|
7
|
+
import { Transaction } from './transaction.entity';
|
|
8
|
+
import { Wallet } from './wallet.entity';
|
|
9
|
+
|
|
10
|
+
@Entity({ name: 'users' })
|
|
11
|
+
export class User extends TenantAwareBaseEntity {
|
|
12
|
+
@Column({ nullable: true })
|
|
13
|
+
firstName?: string;
|
|
14
|
+
|
|
15
|
+
@Column({ nullable: true })
|
|
16
|
+
lastName?: string;
|
|
17
|
+
|
|
18
|
+
@Column({ nullable: true })
|
|
19
|
+
phone?: string;
|
|
20
|
+
|
|
21
|
+
@Column({ nullable: true, type: 'text' })
|
|
22
|
+
bio?: string;
|
|
23
|
+
|
|
24
|
+
@Column({ nullable: true })
|
|
25
|
+
address?: string;
|
|
26
|
+
|
|
27
|
+
@Column({ nullable: true })
|
|
28
|
+
email: string;
|
|
29
|
+
|
|
30
|
+
@Column({ nullable: true })
|
|
31
|
+
password: string;
|
|
32
|
+
|
|
33
|
+
@Column({ type: 'text', nullable: true })
|
|
34
|
+
avatar?: string;
|
|
35
|
+
|
|
36
|
+
@Column({ nullable: true })
|
|
37
|
+
gender: string;
|
|
38
|
+
|
|
39
|
+
@ManyToMany(() => Role, (role) => role.users, {
|
|
40
|
+
onDelete: 'CASCADE',
|
|
41
|
+
eager: true
|
|
42
|
+
})
|
|
43
|
+
@JoinTable()
|
|
44
|
+
roles?: Role[]
|
|
45
|
+
|
|
46
|
+
@OneToMany(
|
|
47
|
+
() => RefreshToken,
|
|
48
|
+
(refreshToken) =>
|
|
49
|
+
refreshToken.user,
|
|
50
|
+
{ eager: true },
|
|
51
|
+
)
|
|
52
|
+
refreshTokens: RefreshToken[];
|
|
53
|
+
|
|
54
|
+
@OneToMany(
|
|
55
|
+
() => Wallet,
|
|
56
|
+
(wallet) =>
|
|
57
|
+
wallet.user,
|
|
58
|
+
{ eager: true },
|
|
59
|
+
)
|
|
60
|
+
wallets: Wallet[];
|
|
61
|
+
|
|
62
|
+
@OneToMany(
|
|
63
|
+
() => Transaction,
|
|
64
|
+
(transaction) =>
|
|
65
|
+
transaction.user,
|
|
66
|
+
{ eager: true },
|
|
67
|
+
)
|
|
68
|
+
transactions: Transaction[];
|
|
69
|
+
|
|
70
|
+
@OneToMany(
|
|
71
|
+
() => Property,
|
|
72
|
+
(property) =>
|
|
73
|
+
property.user,
|
|
74
|
+
)
|
|
75
|
+
properties: Property[];
|
|
76
|
+
|
|
77
|
+
@Column({
|
|
78
|
+
type: 'enum',
|
|
79
|
+
enum: UserStatus,
|
|
80
|
+
default: UserStatus.PENDING
|
|
81
|
+
})
|
|
82
|
+
status: UserStatus
|
|
83
|
+
|
|
84
|
+
@Column({ default: false })
|
|
85
|
+
isEmailVerified?: boolean;
|
|
86
|
+
|
|
87
|
+
@Column({ nullable: true })
|
|
88
|
+
emailVerificationToken: string | null
|
|
89
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Column, Entity, JoinColumn, OneToOne } from 'typeorm';
|
|
2
|
+
import { BaseEntity } from './BaseEntity';
|
|
3
|
+
import { User } from './user.entity';
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'user_suspension' })
|
|
6
|
+
export class UserSuspension extends BaseEntity {
|
|
7
|
+
@OneToOne(() => User, {
|
|
8
|
+
//eager: true,
|
|
9
|
+
onDelete: 'CASCADE',
|
|
10
|
+
onUpdate: 'CASCADE',
|
|
11
|
+
})
|
|
12
|
+
@JoinColumn({ name: 'user_id' })
|
|
13
|
+
user: User;
|
|
14
|
+
|
|
15
|
+
@Column({
|
|
16
|
+
nullable: false
|
|
17
|
+
})
|
|
18
|
+
userId: number
|
|
19
|
+
|
|
20
|
+
@Column({
|
|
21
|
+
nullable: false
|
|
22
|
+
})
|
|
23
|
+
reason: string
|
|
24
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
|
2
|
+
import { Transaction } from './transaction.entity';
|
|
3
|
+
import { User } from './user.entity';
|
|
4
|
+
import { Currency } from '../types/social.enums';
|
|
5
|
+
|
|
6
|
+
@Entity({ name: 'wallets' })
|
|
7
|
+
export class Wallet {
|
|
8
|
+
@PrimaryGeneratedColumn()
|
|
9
|
+
id: number;
|
|
10
|
+
|
|
11
|
+
@ManyToOne(() => User, (user) => user.wallets)
|
|
12
|
+
@JoinColumn({ name: 'user_id' })
|
|
13
|
+
user: User;
|
|
14
|
+
|
|
15
|
+
@Column()
|
|
16
|
+
userId: number
|
|
17
|
+
|
|
18
|
+
@Column({
|
|
19
|
+
type: 'enum',
|
|
20
|
+
enum: Currency
|
|
21
|
+
})
|
|
22
|
+
currency: number
|
|
23
|
+
|
|
24
|
+
@Column({
|
|
25
|
+
})
|
|
26
|
+
customerId: string
|
|
27
|
+
|
|
28
|
+
@Column({
|
|
29
|
+
})
|
|
30
|
+
bankName: string
|
|
31
|
+
|
|
32
|
+
@Column({
|
|
33
|
+
})
|
|
34
|
+
accountNumber: string
|
|
35
|
+
|
|
36
|
+
@Column({
|
|
37
|
+
})
|
|
38
|
+
accountName: string
|
|
39
|
+
|
|
40
|
+
@Column({ type: 'decimal', precision: 65, scale: 2, nullable: true })
|
|
41
|
+
balance: number;
|
|
42
|
+
|
|
43
|
+
@Column()
|
|
44
|
+
enabled: boolean
|
|
45
|
+
|
|
46
|
+
@CreateDateColumn()
|
|
47
|
+
createdAt: Date;
|
|
48
|
+
|
|
49
|
+
@UpdateDateColumn()
|
|
50
|
+
updatedAt: Date;
|
|
51
|
+
|
|
52
|
+
@OneToMany(() => Transaction, transaction => transaction.wallet)
|
|
53
|
+
transactions: Transaction[]
|
|
54
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
import { RequirePermission } from '../decorator/permission.decorator';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
import { User } from '../../user/user.entity';
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
export class PermissionGuard implements CanActivate {
|
|
9
|
+
constructor(private reflector: Reflector) { }
|
|
10
|
+
|
|
11
|
+
canActivate(
|
|
12
|
+
context: ExecutionContext,
|
|
13
|
+
): boolean | Promise<boolean> | Observable<boolean> {
|
|
14
|
+
const permission = this.reflector.get(RequirePermission, context.getHandler());
|
|
15
|
+
|
|
16
|
+
if (!permission) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const request = context.switchToHttp().getRequest();
|
|
21
|
+
|
|
22
|
+
const user: User = request.user;
|
|
23
|
+
|
|
24
|
+
if (!user) {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return this.matchPermission(permission, user);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
matchPermission(permission: string, user: User) {
|
|
32
|
+
const roles = user.roles
|
|
33
|
+
|
|
34
|
+
if (!roles || roles.length < 1) {
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const permissions = roles.map(role => role.permissions).reduce((acc, curr) => [...acc, ...curr]) ?? []
|
|
39
|
+
const permissionNames = permissions?.map(permission => permission.name)
|
|
40
|
+
return permissionNames.includes(permission)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default class ArrayHelper {}
|