Spaces:
Sleeping
Sleeping
Merge branch 'main' of https://github.com/PBL6-team-CATS/PBL6-informative-system
Browse files- backend/package-lock.json +34 -1
- backend/package.json +2 -1
- backend/src/common/enums/VnpCardType.enum.ts +5 -0
- backend/src/entities/payment.entity.ts +26 -3
- backend/src/migrations/1730651201156-modify_payment.ts +32 -0
- backend/src/modules/user/user.controller.ts +29 -6
- backend/src/modules/user/user.service.ts +62 -4
backend/package-lock.json
CHANGED
@@ -31,7 +31,8 @@
|
|
31 |
"pg": "^8.13.0",
|
32 |
"reflect-metadata": "^0.2.0",
|
33 |
"rxjs": "^7.8.1",
|
34 |
-
"typeorm": "^0.3.20"
|
|
|
35 |
},
|
36 |
"devDependencies": {
|
37 |
"@nestjs/cli": "^10.0.0",
|
@@ -7138,6 +7139,27 @@
|
|
7138 |
"mkdirp": "bin/cmd.js"
|
7139 |
}
|
7140 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7141 |
"node_modules/ms": {
|
7142 |
"version": "2.1.3",
|
7143 |
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
@@ -9594,6 +9616,7 @@
|
|
9594 |
"version": "0.3.20",
|
9595 |
"resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz",
|
9596 |
"integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==",
|
|
|
9597 |
"dependencies": {
|
9598 |
"@sqltools/formatter": "^1.2.5",
|
9599 |
"app-root-path": "^3.1.0",
|
@@ -9878,6 +9901,16 @@
|
|
9878 |
"node": ">= 0.8"
|
9879 |
}
|
9880 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9881 |
"node_modules/walker": {
|
9882 |
"version": "1.0.8",
|
9883 |
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
|
|
31 |
"pg": "^8.13.0",
|
32 |
"reflect-metadata": "^0.2.0",
|
33 |
"rxjs": "^7.8.1",
|
34 |
+
"typeorm": "^0.3.20",
|
35 |
+
"vnpay": "^1.6.0"
|
36 |
},
|
37 |
"devDependencies": {
|
38 |
"@nestjs/cli": "^10.0.0",
|
|
|
7139 |
"mkdirp": "bin/cmd.js"
|
7140 |
}
|
7141 |
},
|
7142 |
+
"node_modules/moment": {
|
7143 |
+
"version": "2.30.1",
|
7144 |
+
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
7145 |
+
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
7146 |
+
"license": "MIT",
|
7147 |
+
"engines": {
|
7148 |
+
"node": "*"
|
7149 |
+
}
|
7150 |
+
},
|
7151 |
+
"node_modules/moment-timezone": {
|
7152 |
+
"version": "0.5.46",
|
7153 |
+
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz",
|
7154 |
+
"integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==",
|
7155 |
+
"license": "MIT",
|
7156 |
+
"dependencies": {
|
7157 |
+
"moment": "^2.29.4"
|
7158 |
+
},
|
7159 |
+
"engines": {
|
7160 |
+
"node": "*"
|
7161 |
+
}
|
7162 |
+
},
|
7163 |
"node_modules/ms": {
|
7164 |
"version": "2.1.3",
|
7165 |
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
|
9616 |
"version": "0.3.20",
|
9617 |
"resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.20.tgz",
|
9618 |
"integrity": "sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==",
|
9619 |
+
"license": "MIT",
|
9620 |
"dependencies": {
|
9621 |
"@sqltools/formatter": "^1.2.5",
|
9622 |
"app-root-path": "^3.1.0",
|
|
|
9901 |
"node": ">= 0.8"
|
9902 |
}
|
9903 |
},
|
9904 |
+
"node_modules/vnpay": {
|
9905 |
+
"version": "1.6.0",
|
9906 |
+
"resolved": "https://registry.npmjs.org/vnpay/-/vnpay-1.6.0.tgz",
|
9907 |
+
"integrity": "sha512-+y1tdsJ1ClPC0cVGCG6v5lDi5rZZSzfUe1I670d4tqzxvHdgPbgmrYuH4LpLOEuiFs0Nwum9Thw7DfWgbztjBA==",
|
9908 |
+
"hasInstallScript": true,
|
9909 |
+
"license": "MIT",
|
9910 |
+
"dependencies": {
|
9911 |
+
"moment-timezone": "^0.5.43"
|
9912 |
+
}
|
9913 |
+
},
|
9914 |
"node_modules/walker": {
|
9915 |
"version": "1.0.8",
|
9916 |
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
backend/package.json
CHANGED
@@ -47,7 +47,8 @@
|
|
47 |
"pg": "^8.13.0",
|
48 |
"reflect-metadata": "^0.2.0",
|
49 |
"rxjs": "^7.8.1",
|
50 |
-
"typeorm": "^0.3.20"
|
|
|
51 |
},
|
52 |
"devDependencies": {
|
53 |
"@nestjs/cli": "^10.0.0",
|
|
|
47 |
"pg": "^8.13.0",
|
48 |
"reflect-metadata": "^0.2.0",
|
49 |
"rxjs": "^7.8.1",
|
50 |
+
"typeorm": "^0.3.20",
|
51 |
+
"vnpay": "^1.6.0"
|
52 |
},
|
53 |
"devDependencies": {
|
54 |
"@nestjs/cli": "^10.0.0",
|
backend/src/common/enums/VnpCardType.enum.ts
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export enum VnpCardType {
|
2 |
+
None = 0,
|
3 |
+
ATM = 1,
|
4 |
+
QRCODE = 2
|
5 |
+
}
|
backend/src/entities/payment.entity.ts
CHANGED
@@ -7,7 +7,6 @@ import {
|
|
7 |
Relation,
|
8 |
} from 'typeorm';
|
9 |
import { OrderEntity } from './order.entity.js';
|
10 |
-
import { PaymentMethod } from '../common/enums/PaymentMethod.enum.js';
|
11 |
|
12 |
@Entity('payments')
|
13 |
export class PaymentEntity extends BaseEntity {
|
@@ -18,8 +17,32 @@ export class PaymentEntity extends BaseEntity {
|
|
18 |
order: Relation<OrderEntity>;
|
19 |
|
20 |
@Column({ default: 0 })
|
21 |
-
payment_method: number;
|
22 |
|
23 |
@Column()
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
|
|
7 |
Relation,
|
8 |
} from 'typeorm';
|
9 |
import { OrderEntity } from './order.entity.js';
|
|
|
10 |
|
11 |
@Entity('payments')
|
12 |
export class PaymentEntity extends BaseEntity {
|
|
|
17 |
order: Relation<OrderEntity>;
|
18 |
|
19 |
@Column({ default: 0 })
|
20 |
+
payment_method: number;
|
21 |
|
22 |
@Column()
|
23 |
+
vnp_amount: number
|
24 |
+
|
25 |
+
@Column({ nullable: true })
|
26 |
+
vnp_bank_code: string
|
27 |
+
|
28 |
+
@Column({ nullable: true })
|
29 |
+
vnp_bank_tran_no:string
|
30 |
+
|
31 |
+
@Column({ default: 0})
|
32 |
+
vnp_card_type: number
|
33 |
+
|
34 |
+
@Column({ nullable: true })
|
35 |
+
vnp_order_info: string //Nội dung giao dịch
|
36 |
+
|
37 |
+
@Column({ nullable: true })
|
38 |
+
vnp_paydate: string
|
39 |
+
|
40 |
+
@Column({ nullable: true })
|
41 |
+
vnp_response_code: number
|
42 |
+
|
43 |
+
@Column({ nullable: true })
|
44 |
+
vnp_transaction_no: string
|
45 |
+
|
46 |
+
@Column({ nullable: true })
|
47 |
+
vnp_transaction_status: number
|
48 |
}
|
backend/src/migrations/1730651201156-modify_payment.ts
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
2 |
+
|
3 |
+
export class ModifyPayment1730651201156 implements MigrationInterface {
|
4 |
+
name = 'ModifyPayment1730651201156'
|
5 |
+
|
6 |
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
7 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "value"`);
|
8 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_amount" integer NOT NULL`);
|
9 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_bank_code" character varying`);
|
10 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_bank_tran_no" character varying`);
|
11 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_card_type" integer NOT NULL DEFAULT '0'`);
|
12 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_order_info" character varying`);
|
13 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_paydate" character varying`);
|
14 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_response_code" integer`);
|
15 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_transaction_no" character varying`);
|
16 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "vnp_transaction_status" integer`);
|
17 |
+
}
|
18 |
+
|
19 |
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
20 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_transaction_status"`);
|
21 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_transaction_no"`);
|
22 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_response_code"`);
|
23 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_paydate"`);
|
24 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_order_info"`);
|
25 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_card_type"`);
|
26 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_bank_tran_no"`);
|
27 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_bank_code"`);
|
28 |
+
await queryRunner.query(`ALTER TABLE "payments" DROP COLUMN "vnp_amount"`);
|
29 |
+
await queryRunner.query(`ALTER TABLE "payments" ADD "value" integer NOT NULL`);
|
30 |
+
}
|
31 |
+
|
32 |
+
}
|
backend/src/modules/user/user.controller.ts
CHANGED
@@ -1,17 +1,27 @@
|
|
1 |
-
import { Body, Controller, Get, Param, Post, Request } from '@nestjs/common';
|
2 |
import { UserService } from './user.service.js';
|
3 |
import { UserEntity } from 'src/entities/user.entity.js';
|
4 |
-
import {
|
|
|
|
|
5 |
|
6 |
@Controller('users')
|
7 |
export class UsersController {
|
8 |
constructor(private readonly usersService: UserService) {}
|
9 |
|
10 |
-
@Get('
|
11 |
-
|
12 |
-
|
|
|
13 |
): Promise<UserEntity | undefined> {
|
14 |
-
return this.usersService.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
16 |
|
17 |
@Post('updateUser')
|
@@ -20,4 +30,17 @@ export class UsersController {
|
|
20 |
const updateUserDto = req.body;
|
21 |
return this.usersService.updateUserById(userId, updateUserDto);
|
22 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
|
|
1 |
+
import { Body, Controller, Get, Param, Post, Query, Request } from '@nestjs/common';
|
2 |
import { UserService } from './user.service.js';
|
3 |
import { UserEntity } from 'src/entities/user.entity.js';
|
4 |
+
import { Roles } from '../authentication/authorization/roles.decorator.js';
|
5 |
+
import { Role } from '../../common/enums/role.enum.js';
|
6 |
+
import { Paginate, PaginateQuery } from 'nestjs-paginate';
|
7 |
|
8 |
@Controller('users')
|
9 |
export class UsersController {
|
10 |
constructor(private readonly usersService: UserService) {}
|
11 |
|
12 |
+
@Get('id')
|
13 |
+
@Roles(Role.ADMIN, Role.AREA_MANAGER, Role.BRANCH_MANAGER)
|
14 |
+
async getUserById(
|
15 |
+
@Query('id') id: string
|
16 |
): Promise<UserEntity | undefined> {
|
17 |
+
return this.usersService.findOneByField("id", id)
|
18 |
+
}
|
19 |
+
|
20 |
+
@Get('fullname')
|
21 |
+
@Roles(Role.ADMIN, Role.AREA_MANAGER, Role.BRANCH_MANAGER)
|
22 |
+
async getUserByFullname( @Query('full_name') fullName: string, @Paginate() query: PaginateQuery, ) {
|
23 |
+
console.log(fullName)
|
24 |
+
return this.usersService.findAllByName(fullName, query);
|
25 |
}
|
26 |
|
27 |
@Post('updateUser')
|
|
|
30 |
const updateUserDto = req.body;
|
31 |
return this.usersService.updateUserById(userId, updateUserDto);
|
32 |
}
|
33 |
+
|
34 |
+
@Get('getAll')
|
35 |
+
@Roles(Role.ADMIN, Role.AREA_MANAGER, Role.BRANCH_MANAGER)
|
36 |
+
async findAllUser(@Paginate() query: PaginateQuery) {
|
37 |
+
return this.usersService.findAllUser(query);
|
38 |
+
}
|
39 |
+
|
40 |
+
@Get('role')
|
41 |
+
@Roles(Role.ADMIN, Role.AREA_MANAGER, Role.BRANCH_MANAGER)
|
42 |
+
async getUserByRole( @Query('role') role: string, @Paginate() query: PaginateQuery, ) {
|
43 |
+
console.log(role)
|
44 |
+
return this.usersService.findAllByRole(role, query);
|
45 |
+
}
|
46 |
}
|
backend/src/modules/user/user.service.ts
CHANGED
@@ -5,6 +5,7 @@ import { UpdateUserDto } from './dto/update-user-dto.js';
|
|
5 |
import { ValidateService } from '../../validate/validate.service.js';
|
6 |
import * as bcrypt from 'bcrypt';
|
7 |
import { JwtService } from '@nestjs/jwt';
|
|
|
8 |
|
9 |
export type User = any;
|
10 |
|
@@ -15,10 +16,6 @@ export class UserService {
|
|
15 |
private jwtService: JwtService,
|
16 |
) {}
|
17 |
|
18 |
-
async findOne(username: string): Promise<UserEntity | undefined> {
|
19 |
-
return UserEntity.findOne({ where: { full_name: username } });
|
20 |
-
}
|
21 |
-
|
22 |
async create(signUpDto: SignUpDto): Promise<UserEntity | undefined>{
|
23 |
return UserEntity.create({
|
24 |
full_name: signUpDto.full_name,
|
@@ -63,4 +60,65 @@ export class UserService {
|
|
63 |
access_token: token
|
64 |
};
|
65 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
|
|
5 |
import { ValidateService } from '../../validate/validate.service.js';
|
6 |
import * as bcrypt from 'bcrypt';
|
7 |
import { JwtService } from '@nestjs/jwt';
|
8 |
+
import { FilterOperator, paginate, PaginateConfig, PaginateQuery } from 'nestjs-paginate';
|
9 |
|
10 |
export type User = any;
|
11 |
|
|
|
16 |
private jwtService: JwtService,
|
17 |
) {}
|
18 |
|
|
|
|
|
|
|
|
|
19 |
async create(signUpDto: SignUpDto): Promise<UserEntity | undefined>{
|
20 |
return UserEntity.create({
|
21 |
full_name: signUpDto.full_name,
|
|
|
60 |
access_token: token
|
61 |
};
|
62 |
}
|
63 |
+
|
64 |
+
async findAllUser(query: PaginateQuery) {
|
65 |
+
const paginateConfig: PaginateConfig<UserEntity> = {
|
66 |
+
sortableColumns: ['id', 'full_name', 'phone_number', 'email'],
|
67 |
+
nullSort: 'last',
|
68 |
+
defaultSortBy: [['id', 'DESC']],
|
69 |
+
searchableColumns: ['full_name'],
|
70 |
+
filterableColumns: {
|
71 |
+
full_name: [
|
72 |
+
FilterOperator.LT,
|
73 |
+
FilterOperator.LTE,
|
74 |
+
FilterOperator.GT,
|
75 |
+
FilterOperator.GTE,
|
76 |
+
],
|
77 |
+
item_type: [FilterOperator.EQ]
|
78 |
+
},
|
79 |
+
};
|
80 |
+
return paginate(query, UserEntity.createQueryBuilder(), paginateConfig);
|
81 |
+
}
|
82 |
+
|
83 |
+
async findAllByName(fullName: string, query: PaginateQuery) {
|
84 |
+
const queryBuilder = UserEntity.createQueryBuilder('users')
|
85 |
+
.where('users.full_name = :fullName', { fullName });
|
86 |
+
const paginateConfig: PaginateConfig<UserEntity> = {
|
87 |
+
sortableColumns: ['id', 'full_name', 'phone_number', 'email'],
|
88 |
+
nullSort: 'last',
|
89 |
+
defaultSortBy: [['id', 'DESC']],
|
90 |
+
searchableColumns: ['full_name'],
|
91 |
+
filterableColumns: {
|
92 |
+
full_name: [
|
93 |
+
FilterOperator.LT,
|
94 |
+
FilterOperator.LTE,
|
95 |
+
FilterOperator.GT,
|
96 |
+
FilterOperator.GTE,
|
97 |
+
],
|
98 |
+
item_type: [FilterOperator.EQ]
|
99 |
+
},
|
100 |
+
};
|
101 |
+
return paginate(query, queryBuilder, paginateConfig);
|
102 |
+
}
|
103 |
+
|
104 |
+
async findAllByRole(role: string, query: PaginateQuery) {
|
105 |
+
const queryBuilder = UserEntity.createQueryBuilder('users')
|
106 |
+
.where('users.role = :role', { role });
|
107 |
+
const paginateConfig: PaginateConfig<UserEntity> = {
|
108 |
+
sortableColumns: ['id', 'full_name', 'phone_number', 'email'],
|
109 |
+
nullSort: 'last',
|
110 |
+
defaultSortBy: [['id', 'DESC']],
|
111 |
+
searchableColumns: ['full_name'],
|
112 |
+
filterableColumns: {
|
113 |
+
full_name: [
|
114 |
+
FilterOperator.LT,
|
115 |
+
FilterOperator.LTE,
|
116 |
+
FilterOperator.GT,
|
117 |
+
FilterOperator.GTE,
|
118 |
+
],
|
119 |
+
item_type: [FilterOperator.EQ]
|
120 |
+
},
|
121 |
+
};
|
122 |
+
return paginate(query, queryBuilder, paginateConfig);
|
123 |
+
}
|
124 |
}
|