Skip to content

Commit 1cec5c8

Browse files
committed
feat(src) add process to manager personal loans
1 parent 13a13c6 commit 1cec5c8

15 files changed

+431
-322
lines changed

src/common/dtos/params.dto.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ export class ParamsDTO<T> {
4545

4646
@ApiProperty({ description: 'Number of records to skip' })
4747
@IsOptional()
48-
@IsPositive()
4948
@IsNumber()
50-
@Min(1)
49+
@Min(0)
5150
skip?: number;
5251

5352
@ApiProperty({ description: 'Fields to select in the query' })

src/common/services/crud/crud.service.ts

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,24 @@ export class CrudService<T> {
3333
}
3434

3535
async getAll(params: ParamsDTO<T>): Promise<ResponseDTO> {
36-
const options: FindManyOptions<T> = {
37-
where: params.filter,
38-
order: params.sort as FindOptionsOrder<T>,
39-
skip: params.skip,
40-
take: params.limit,
41-
select: this.mapSelectFields(params.fieldSelected) ?? undefined,
42-
relations: params.relations,
43-
};
44-
45-
let count = 0;
46-
if (params.limit > 0) {
47-
count = await this.count(params.filter);
48-
}
49-
5036
try {
51-
const data = await this.repository.find(options);
37+
const options: FindManyOptions<T> = {
38+
where: params.filter,
39+
order: params.sort as FindOptionsOrder<T>,
40+
skip: params.skip,
41+
take: params.limit,
42+
select: this.mapSelectFields(params.fieldSelected) ?? undefined,
43+
relations: params.relations,
44+
};
45+
46+
let count = 0;
47+
if (params.limit > 0) {
48+
count = await this.count(params.filter);
49+
}
50+
51+
const cleanedOptions = this.cleanOptions(options);
52+
53+
const data = await this.repository.find(cleanedOptions);
5254
return { data, count, skip: +params.skip, limit: +params.limit };
5355
} catch (error) {
5456
console.error(error, 'getAll error crud');
@@ -62,11 +64,16 @@ export class CrudService<T> {
6264
relations: string[] = [],
6365
): Promise<ResponseDTO> {
6466
try {
65-
const response = await this.repository.findOne({
67+
const options: FindManyOptions<T> = {
6668
where: data,
69+
order: data.sort as FindOptionsOrder<T>,
6770
select: this.mapSelectFields(fieldSelected as any) ?? undefined,
68-
relations,
69-
});
71+
relations
72+
};
73+
74+
const cleanedOptions = this.cleanOptions(options);
75+
76+
const response = await this.repository.findOne(cleanedOptions);
7077

7178
return { data: response };
7279
} catch (error) {
@@ -166,4 +173,22 @@ export class CrudService<T> {
166173
await queryRunner.release();
167174
}
168175
}
176+
177+
cleanOptions<T>(obj: T): T {
178+
const cleanedObject = Object.entries(obj).reduce((acc, [key, value]) => {
179+
if (value === undefined || value === '' || (typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0)) {
180+
return acc;
181+
}
182+
183+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
184+
acc[key] = this.cleanOptions(value);
185+
} else {
186+
acc[key] = value;
187+
}
188+
189+
return acc;
190+
}, {} as T);
191+
192+
return cleanedObject;
193+
}
169194
}

src/modules/customer/entities/customer.entity.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import {
88
UpdateDateColumn,
99
BeforeInsert,
1010
BeforeUpdate,
11+
OneToMany,
1112
} from 'typeorm';
1213
import * as bcrypt from 'bcrypt';
14+
import { PersonalLoan } from 'src/modules/personal-loan/entities/personal-loan.entity';
1315

1416
@Entity()
1517
export class Customer {
@@ -57,4 +59,7 @@ export class Customer {
5759
this.password = await bcrypt.hash(this.password, salt);
5860
}
5961
}
62+
63+
@OneToMany(() => PersonalLoan, (personalLoan) => personalLoan.customer)
64+
personalLoans: PersonalLoan[];
6065
}

src/modules/individual-customer/dtos/company-info.dto.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import { ApiProperty } from '@nestjs/swagger';
2-
import {
3-
IsString,
4-
Length
5-
} from 'class-validator';
2+
import { IsString, Length } from 'class-validator';
63

74
export class CompanyInfoDTO {
85
@ApiProperty({
Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,49 @@
11
import { ApiProperty } from '@nestjs/swagger';
22
import {
3-
IsNotEmpty,
43
IsBoolean,
54
IsString,
65
IsNumber,
7-
IsDate,
86
ArrayNotEmpty,
7+
IsOptional,
8+
IsUUID,
99
} from 'class-validator';
1010

1111
export class CreatePersonalLoanDto {
12+
@ApiProperty()
13+
@IsUUID()
14+
customerId: string;
15+
16+
@ApiProperty()
17+
@IsString()
18+
@IsOptional()
19+
monthlyIncome: string;
20+
21+
@ApiProperty()
22+
@IsString()
23+
@IsOptional()
24+
monthlyBills: string;
25+
26+
@ApiProperty()
27+
@IsNumber()
28+
amount: number;
29+
1230
@ApiProperty()
1331
@IsString()
14-
partnerUuid: string;
32+
@IsOptional()
33+
duration: string;
34+
35+
@ApiProperty()
36+
@ArrayNotEmpty()
37+
@IsOptional()
38+
assets: string[];
39+
40+
@ApiProperty()
41+
@IsNumber()
42+
@IsOptional()
43+
assetsAmount: number;
44+
45+
@ApiProperty()
46+
@IsBoolean()
47+
@IsOptional()
48+
tc: boolean;
1549
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsString, IsOptional } from 'class-validator';
3+
4+
export class LoanDetailsMounthlyDto {
5+
@ApiProperty()
6+
@IsString()
7+
@IsOptional()
8+
monthlyIncome: string;
9+
10+
@ApiProperty()
11+
@IsString()
12+
@IsOptional()
13+
monthlyBills: string;
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsArray, IsNumber } from 'class-validator';
3+
4+
export class UpdateAssetsDto {
5+
@ApiProperty({
6+
description: 'List of assets associated with the loan',
7+
example: ['Car', 'House'],
8+
required: false,
9+
})
10+
@IsArray()
11+
assets: string[];
12+
13+
@ApiProperty({
14+
description: 'Total amount of assets',
15+
example: 15000,
16+
required: false,
17+
})
18+
@IsNumber()
19+
assetsAmount: number;
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsBoolean } from 'class-validator';
3+
4+
export class UpdateTermsAndConditionsDto {
5+
@ApiProperty({
6+
description: 'Indicates whether the terms and conditions are accepted',
7+
example: true,
8+
required: false,
9+
})
10+
@IsBoolean()
11+
tc: boolean;
12+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsString, IsNumber } from 'class-validator';
3+
4+
export class UpdateTermsLoanDto {
5+
@ApiProperty({
6+
description: 'The amount of the loan',
7+
example: 10000,
8+
})
9+
@IsNumber()
10+
amount: number;
11+
12+
@ApiProperty({
13+
description: 'The duration of the loan',
14+
example: '12 months',
15+
required: false,
16+
})
17+
@IsString()
18+
duration: string;
19+
}

src/modules/personal-loan/entities/personal-loan.entity.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,47 @@ import {
44
Column,
55
CreateDateColumn,
66
UpdateDateColumn,
7+
ManyToOne,
78
} from 'typeorm';
9+
import { StatusPersonalLoan } from '../enums/personal-loan.enum';
10+
import { Customer } from 'src/modules/customer/entities/customer.entity';
811

912
@Entity()
1013
export class PersonalLoan {
1114
@PrimaryGeneratedColumn('uuid')
1215
id: string;
1316

17+
@ManyToOne(() => Customer, (customer) => customer.personalLoans)
18+
customer: Customer;
19+
20+
@Column({ nullable: true })
21+
monthlyIncome: string;
22+
23+
@Column({ nullable: true })
24+
monthlyBills: string;
25+
26+
@Column({ type: 'numeric', nullable: true })
27+
amount: number;
28+
1429
@Column({ nullable: true })
15-
partnerUuid: string;
30+
duration: string;
31+
32+
@Column('text', { array: true, nullable: true })
33+
assets: string[];
34+
35+
@Column({ type: 'numeric', nullable: true })
36+
assetsAmount: number;
37+
38+
@Column({ type: 'boolean', nullable: true })
39+
tc: boolean;
40+
41+
@Column({
42+
type: 'enum',
43+
enum: StatusPersonalLoan,
44+
default: StatusPersonalLoan.MOUNTHLY_BUDGET,
45+
nullable: true,
46+
})
47+
status: StatusPersonalLoan;
1648

1749
@Column({ type: 'boolean', default: true, nullable: true })
1850
isActive: boolean;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export enum StatusPersonalLoan {
2+
MOUNTHLY_BUDGET = 'MOUNTHLY_BUDGET',
3+
TEMRS_LOAN = 'TEMRS_LOAN',
4+
ASSETS = 'ASSETS',
5+
TC = 'TC',
6+
CREATED = 'CREATED',
7+
PENDING = 'PENDING',
8+
IN_PROCESS = 'IN_PROCESS',
9+
FAILED = 'FAILED',
10+
COMPLETED = 'COMPLETED',
11+
}
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
import { StatusPersonalLoan } from '../enums/personal-loan.enum';
2+
13
export interface IPersonalLoan {
2-
partnerUuid: string;
4+
id: string;
5+
monthlyIncome: string;
6+
monthlyBills: string;
7+
amount: number;
8+
duration: string;
9+
assets: any;
10+
assetsAmount: number;
11+
tc: boolean;
12+
status: StatusPersonalLoan;
13+
isActive: boolean;
14+
isDeleted: boolean;
15+
createdAt: Date;
16+
updatedAt: Date;
317
}

0 commit comments

Comments
 (0)