├── .editorconfig
├── .github
└── dependabot.yml
├── .gitignore
├── 01_data_transfer_objects__dtos__.md
├── 02_validation__fluentvalidation__.md
├── 03_api_controllers_.md
├── 04_database_models_.md
├── 05_database_access__dapper__.md
├── 06_authentication___authorization__jwt__.md
├── 07_request_middleware_.md
├── 08_application_configuration_.md
├── Controllers
├── CloudinanyController.cs
├── KhachHangController.cs
├── NhanVienController.cs
├── QuanLyChungController.cs
├── QuanTriVienController.cs
├── TatCaTruyCapController.cs
├── VnPayController.cs
└── XacThucController.cs
├── DTOs
├── Chung
│ ├── DangNhapDTO.cs
│ ├── NguoiDungDTO.cs
│ ├── NguoiDungDangKyDTO.cs
│ ├── ResetPasswordDTO.cs
│ └── SuaThongTinNguoiDungDTO.CS
├── HienThiTatCaXem
│ ├── DichVuDTO.cs
│ ├── FeedBackDTO.cs
│ ├── GiamGiaDTO.cs
│ ├── GiamGiaDetailDTO.cs
│ ├── PhongAnhDTO.cs
│ ├── PhongDTO.cs
│ ├── PhongDetailsDTO.cs
│ ├── PhongYeuThichDTO.cs
│ ├── TatCaBaiVietDTO.cs
│ └── TienNghiDTO.cs
├── KhachHang
│ ├── KhachHangChiTietHoaDon.cs
│ ├── KhachHangDatDichVuDTO.cs
│ ├── KhachHangDatPhongDTO.cs
│ ├── KhachHangFeedBackDTO.cs
│ ├── KhachHangHoaDonDTO.cs
│ ├── KhachHangLichSuGiaoDichDTO.cs
│ ├── KhachHangTaoHoaDonRequestDTO.cs
│ └── KhachHangThanhToanDTO.cs
├── NhanVien
│ ├── BaoCaoDTO.cs
│ ├── ChiTietBaoCaoDTO.cs
│ ├── NhanVienThemBaiVietDTO.cs
│ └── NhanVienXoaBaiVietDTO.cs
├── QuanLyChung
│ ├── QuanLyChungSuaBaiVietDTO.cs
│ ├── QuanLyChungSuaDichVuDTO.cs
│ ├── QuanLyChungSuaPhongAnhPutDTO.cs
│ ├── QuanLyChungSuaPhongGiamGiaDTO.cs
│ └── QuanLyChungSuaPhongTienNghiDTO.cs
└── QuanTriVien
│ ├── QuanTriVienApDungGiamGiaDTO.cs
│ ├── QuanTriVienSuaGiamGiaDTO.cs
│ ├── QuanTriVienSuaNoiQuyDTO.cs
│ ├── QuanTriVienSuaRoleDTO.cs
│ ├── QuanTriVienSuaTrangThaiPhDTO.cs
│ ├── QuanTriVienThem1DichVuDTO.cs
│ ├── QuanTriVienThem1NoiQuyDTO.cs
│ ├── QuanTriVienThem1PhongDTO.cs
│ ├── QuanTriVienThem1TienNghiDTO.cs
│ ├── QuanTriVienThemAnhDTO.cs
│ ├── QuanTriVienThemGiamGiaDTO.cs
│ ├── QuanTriVienThemMaGiamGiaDTO.cs
│ ├── QuanTriVienThemNhieuDichVu.cs
│ ├── QuanTriVienThemNhieuTienNghiDTO.cs
│ ├── QuanTriVienXoa1Phong.cs
│ ├── QuanTriVienXoa1TienNghiDTO.cs
│ ├── QuanTriVienXoaGiamGiaDTO.cs
│ ├── QuanTriVienXoaNhieuTienNghiDTO.cs
│ └── QuanTriVienXoaNoiQuyDTO.cs
├── Data
├── Cloudinary.cs
├── Hotelnhom2Context.cs
└── SentimentData.cs
├── FixSwagger.txt
├── Helper
├── HelperJWT.cs
└── SensitiveDataHelper.cs
├── HotelManagementAPI.csproj
├── HotelManagementAPI.http
├── HotelManagementAPI.sln
├── Models
├── BaiViet.cs
├── BaoCao.cs
├── ChiTietBaoCao.cs
├── ChiTietHoaDon.cs
├── DatDichVu.cs
├── DatPhong.cs
├── DataQlks115Nhom2Context.cs
├── DichVu.cs
├── Feedback.cs
├── GiamGium.cs
├── HoaDon.cs
├── Hotelnhom2Context.cs
├── LichSuGiaoDich.cs
├── NguoiDung.cs
├── NoiQuy.cs
├── PaymentRequest.cs
├── PaymentResponse.cs
├── PaymentResult.cs
├── Phong.cs
├── PhongAnh.cs
├── PhongYeuThich.cs
├── ThanhToan.cs
├── TienNghi.cs
└── VnpayCallbackRequest.cs
├── Program.cs
├── Properties
└── launchSettings.json
├── README.md
├── RoleMiddleware
└── RoleMiddleware.cs
├── SECURITY.md
├── SQLQuery2.sql
├── Services
├── IVnpayService.cs
└── VnpayService.cs
├── TrainML
├── Program.cs
├── data.csv
└── sentimentModel.zip
├── Validators
├── BaoCaoDTOvalidation.cs
├── ChiTietBaoCaoDTOvalidation.cs
├── DichVuDTOValidator.cs
├── FeedBackDTOvalidation.cs
├── GiamGiaDetailDTOValidator.cs
├── GiamGiaDetailvalidation.cs
├── HoaDonDTOValidator.cs
├── KhachHangHoaDonDTOvalidation.cs
├── KhachHangThanhToanDTOvalidation.cs
├── LoginDTOValidator.cs
├── NguoiDungDTOValidator.cs
├── NhanVienThemBaiVietDTOvalidation.cs
├── PhongAnhDTOValidator.cs
├── PhongDetailsDTOValidator.cs
├── QuanLyChungSuaBaiVietDTOvalidation.cs
├── QuanLyChungSuaDichVuDTOvalidation.cs
├── QuanLyChungSuaPhongAnhPutDTOvalidaton.cs
├── QuanLyChungSuaPhongGiamGiaDTOvalidation.cs
├── QuanLyChungSuaPhongTienNghiDTOvalidation.cs
├── QuanTriVienApDungGiamGiaDTOvalidation.cs
├── QuanTriVienSuaGiamGiaDTOvalidation.cs
├── QuanTriVienSuaNoiQuyDTOvalidation.cs
├── QuanTriVienSuaRoleDTOvalidation.cs
├── QuanTriVienThem1DichVuDTOvalidation.cs
├── QuanTriVienThem1NoiQuyDTOvalidation.cs
├── QuanTriVienThem1PhongDTOvalidation.cs
├── QuanTriVienThem1TienNghiDTOvalidation.cs
├── QuanTriVienThemAnhDTOvalidation.cs
├── QuanTriVienThemGiamGiaDTOvalidation.cs
├── QuanTriVienThemMaGiamGiaDTOvalidation.cs
├── QuanTriVienThemNhieuDichVuvalidation.cs
├── QuanTriVienThemNhieuTienNghiDTOvalidation.cs
├── QuanTriVienXoa1Phongvalidation.cs
├── QuanTriVienXoa1TienNghiDTOvalidation.cs
├── QuanTriVienXoaNhieuTienNghiDTOvalidation.cs
├── QuanTriVienXoaNoiQuyDTOvalidation.cs
├── ResetPasswordDTOValidator.cs
├── TaoHoaDonRequestDTOvalidator.cs
├── TatCaBaiVietDTOValidator.cs
├── ThanhToanDTOValidator.cs
└── TienNghiDTOvalidation.cs
├── appsettings.Development.json
├── appsettings.json
├── note.txt
└── wwwroot
└── swagger-custom.css
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # CS0618: Type or member is obsolete
4 | dotnet_diagnostic.CS0618.severity = warning
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5 |
6 | version: 2 # Phiên bản cấu hình Dependabot
7 | updates:
8 | - package-ecosystem: "nuget" # Hệ sinh thái package dành cho ASP.NET Core
9 | directory: "/" # Thư mục chứa tệp quản lý dependencies, thường là tại gốc dự án
10 | schedule:
11 | interval: "daily" # Lịch trình kiểm tra: hằng ngày
12 | commit-message:
13 | prefix: "chore" # Thêm tiền tố cho commit do Dependabot tạo ra
14 | open-pull-requests-limit: 5 # Giới hạn số lượng pull request đồng thời
15 | ignore:
16 | - dependency-name: "SomePackage" # Tên thư viện muốn bỏ qua
17 | versions:
18 | - "<2.0.0" # Phiên bản cụ thể muốn bỏ qua
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build results
2 | bin/
3 | obj/
4 |
5 | # User-specific files
6 | *.user
7 | *.suo
8 | *.userosscache
9 | *.sln.docstates
10 |
11 | # VS Code directory
12 | .vscode/
13 |
14 | # Visual Studio files
15 | .vs/
16 |
17 | # DLLs, EXEs and PDBs
18 | *.dll
19 | *.exe
20 | *.pdb
21 |
22 | # Cache files
23 | *.cache
24 |
25 | # Publish profiles
26 | Properties/PublishProfiles/
27 |
28 | # Backup files
29 | *~
30 | *.bak
31 | *.backup.json
32 |
33 | # Dotnet artifacts
34 | *.log
35 | *.db
36 | *.v2
37 |
38 | # Bỏ qua các thư mục build
39 |
40 | .vscode/
41 | *.user
42 | *.suo
43 | /bin/
44 | /obj/
45 | # .gitignore
46 | .config/
47 | .idea/
48 | . v s /
49 | / o b j /
50 | / b i n /
51 | b i n /
52 | o b j /
53 |
--------------------------------------------------------------------------------
/01_data_transfer_objects__dtos__.md:
--------------------------------------------------------------------------------
1 | # Chapter 1: Data Transfer Objects (DTOs)
2 |
3 | Welcome to the first chapter of the HotelManagementAPI tutorial!
4 |
5 | In any application, especially one with different parts talking to each other (like a website or mobile app talking to our API), we need a clear way to define *what* information is being exchanged. Imagine you're sending a package – you need a standard envelope or box, and maybe a form inside specifying the contents.
6 |
7 | In the world of APIs and software development, we use something similar called **Data Transfer Objects**, or **DTOs** for short.
8 |
9 | Think of DTOs as **standardized forms or containers** used specifically for sending data between different parts of our application, or between our API and the "outside world" (like a user's web browser or phone app).
10 |
11 | ## Why Do We Need DTOs?
12 |
13 | Let's consider a simple task in our Hotel Management API: an administrator wants to add a new amenity (like "Free Wi-Fi" or "Swimming Pool") to the hotel system.
14 |
15 | The administrator would likely fill out some details, like the name of the amenity and maybe a short description, on an admin webpage or app. This data then needs to be sent over the internet to our API so it can be saved.
16 |
17 | How does our API know exactly *what* data to expect? Does it need the creation date? The ID of the admin adding it? Is the description optional?
18 |
19 | This is where DTOs come in! They define a clear **contract** or **blueprint** for the data being transferred.
20 |
21 | * **For Requests:** When the client (the admin's browser) sends data *to* the API (like adding a new amenity), the DTO defines exactly what fields (`TenTienNghi`, `MoTa`) and data types (text, numbers) the API expects to receive. If the client sends something different, the API can easily tell.
22 | * **For Responses:** When the API sends data *back* to the client (like showing the details of an amenity), the DTO defines exactly what fields the client will receive. This prevents sending unnecessary internal details (like database IDs or complex internal statuses) and ensures the client gets only the data it needs.
23 |
24 | In short, DTOs make the communication between different parts of the system clean, predictable, and organized.
25 |
26 | ## Our First DTO Example: Adding a Facility
27 |
28 | Let's look at a DTO used in our `HotelManagementAPI` project specifically for adding a single new facility (Tiện nghi).
29 |
30 | You can find this code in the project at `DTOs/QuanTriVien/QuanTriVienThem1TienNghiDTO.cs`:
31 |
32 | ```csharp
33 | using System.ComponentModel.DataAnnotations;
34 |
35 | namespace HotelManagementAPI.DTOs.QuanTriVien
36 | {
37 | public class QuanTriVienThem1TienNghiDTO
38 | {
39 | [Required]
40 | [StringLength(100)]
41 | public string TenTienNghi { get; set; } = null!;
42 |
43 | [StringLength(500)]
44 | public string? MoTa { get; set; }
45 | }
46 | }
47 | ```
48 |
49 | Let's break this down:
50 |
51 | * `namespace HotelManagementAPI.DTOs.QuanTriVien`: This just tells us where this DTO "lives" within our project structure. It's in the `DTOs` folder, specifically under the `QuanTriVien` (Administrator) section, because this DTO is used for administrative tasks.
52 | * `public class QuanTriVienThem1TienNghiDTO`: This is the DTO itself. It's a simple C# class. The name tells us its purpose: it's for an Administrator (`QuanTriVien`) to Add (`Them`) One (`1`) Facility (`TienNghi`).
53 | * `public string TenTienNghi { get; set; }`: This is a property representing the **name** of the facility. `string` means it's text. `{ get; set; }` just means we can read and write its value. `null!` is a C# 8 feature indicating this property is *expected* to be non-null (which is also enforced by `[Required]`).
54 | * `public string? MoTa { get; set; }`: This property is for the **description** of the facility. The `?` after `string` means it's nullable – the description is optional.
55 | * `[Required]` and `[StringLength(100)]`: These are called **Data Annotations**. They provide extra information about the properties. `[Required]` means that when someone sends data using this DTO, the `TenTienNghi` field *must* be provided. `[StringLength(100)]` sets a maximum length for the text. We'll dive much deeper into this concept (Validation) in the [next chapter](02_validation__fluentvalidation__.md).
56 |
57 | So, this `QuanTriVienThem1TienNghiDTO` tells our API: "When someone wants to add a single facility, I expect to receive data with a `TenTienNghi` (which is required and up to 100 characters) and optionally a `MoTa` (up to 500 characters)."
58 |
59 | ## How DTOs are Used in Practice (Simple Flow)
60 |
61 | Let's visualize the simple process of adding a facility using this DTO:
62 |
63 | ```mermaid
64 | sequenceDiagram
65 | participant Client as Admin Browser/App
66 | participant ApiController as API Controller (e.g., FacilitiesController)
67 | participant AddTienNghiDTO as QuanTriVienThem1TienNghiDTO
68 |
69 | Client->>ApiController: Send HTTP POST request (e.g., /api/facilities)
with Facility data (JSON)
70 | ApiController->>AddTienNghiDTO: API framework automatically maps JSON data
to QuanTriVienThem1TienNghiDTO object
Note over AddTienNghiDTO: Creates an instance of the DTO
with data from the request (Model Binding)
71 | ApiController->>ApiController: Access data using DTO object
e.g., dto.TenTienNghi, dto.MoTa
72 | ApiController-->>Client: Send HTTP Response (Success/Error)
73 | ```
74 |
75 | As you can see, the `QuanTriVienThem1TienNghiDTO` acts as the intermediate structure that the API framework uses to understand and hold the incoming data before your controller code even starts processing it.
76 |
77 | ## DTOs for Sending Data Back (Responses)
78 |
79 | DTOs aren't just for incoming data (requests). They are also used for outgoing data (responses).
80 |
81 | Imagine a client wants to see the list of all facilities. The API will get this information, likely from a database. However, the database structure might contain internal IDs or other fields the client doesn't need or shouldn't see.
82 |
83 | The API will take the data retrieved (which might be represented by different objects called "Database Models", covered in [Chapter 4: Database Models](04_database_models_.md)) and transform it into a suitable DTO for the client.
84 |
85 | Look at `DTOs/HienThiTatCaXem/TienNghiDTO.cs`:
86 |
87 | ```csharp
88 | using System.Text.Json.Serialization;
89 | using System.ComponentModel.DataAnnotations;
90 | namespace HotelManagementAPI.DTOs
91 | {
92 | public class TienNghiDTO
93 | {
94 | [StringLength(6)]
95 | public string MaTienNghi { get; set; } = null!;
96 |
97 | [StringLength(100)]
98 | public string TenTienNghi { get; set; } = null!;
99 |
100 | public string? MoTa { get; set; }
101 | }
102 | }
103 | ```
104 |
105 | This `TienNghiDTO` is used when showing facility information. Notice it includes `MaTienNghi` (the facility code/ID), which wasn't needed when *adding* the facility (because the API would generate it), but is needed when *viewing* it. This shows how DTOs are tailored for the specific task (request or response) and the specific data needed.
106 |
107 | ## Organizing DTOs
108 |
109 | In the `HotelManagementAPI` project, you'll notice DTOs are organized into folders like `KhachHang` (Customer), `NhanVien` (Employee), `QuanTriVien` (Administrator), and `HienThiTatCaXem` (View All). This helps keep the project organized and makes it clear which DTOs are used for which purpose or by which type of user or feature.
110 |
111 | ## Summary
112 |
113 | In this first chapter, we learned that Data Transfer Objects (DTOs) are simple classes used to define the structure of data being sent into or out of our API. They act like contracts, ensuring clear and predictable communication.
114 |
115 | We saw examples of DTOs used for both receiving data (like adding a new facility with `QuanTriVienThem1TienNghiDTO`) and sending data back (like viewing facility details with `TienNghiDTO`). We also touched upon how the API framework helps in automatically mapping data to and from DTOs.
116 |
117 | DTOs are the first step in defining how our API interacts with the world. But what happens if the data sent in a DTO doesn't meet the requirements we defined (like a required field being missing)? That's where validation comes in, the topic of our next chapter!
118 |
119 | Ready to learn how to ensure the data in our DTOs is correct? Let's go to [Chapter 2: Validation (FluentValidation)](02_validation__fluentvalidation__.md)!
120 |
121 | ---
122 |
123 | Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge). **References**: [[1]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/Chung/DangNhapDTO.cs), [[2]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/Chung/NguoiDungDTO.cs), [[3]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/Chung/NguoiDungDangKyDTO.cs), [[4]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/Chung/ResetPasswordDTO.cs), [[5]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/Chung/SuaThongTinNguoiDungDTO.CS), [[6]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/DichVuDTO.cs), [[7]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/FeedBackDTO.cs), [[8]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/GiamGiaDTO.cs), [[9]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/GiamGiaDetailDTO.cs), [[10]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/PhongAnhDTO.cs), [[11]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/PhongDTO.cs), [[12]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/PhongDetailsDTO.cs), [[13]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/PhongYeuThichDTO.cs), [[14]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/TatCaBaiVietDTO.cs), [[15]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/HienThiTatCaXem/TienNghiDTO.cs), [[16]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangChiTietHoaDon.cs), [[17]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangDatDichVuDTO.cs), [[18]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangDatPhongDTO.cs), [[19]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangHoaDonDTO.cs), [[20]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangLichSuGiaoDichDTO.cs), [[21]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/KhachHangThanhToanDTO.cs), [[22]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/KhachHang/TaoHoaDonRequestDTO.cs), [[23]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/BaoCaoDTO.cs), [[24]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/ChiTietBaoCaoDTO.cs), [[25]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienSuaBaiViet.cs), [[26]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienSuaDichVuDTO.cs), [[27]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienSuaPhongAnhPutDTO.cs), [[28]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienSuaPhongGiamGiaDTO.cs), [[29]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienSuaPhongTienNghiDTO.cs), [[30]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienThemBaiVietDTO.cs), [[31]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/NhanVien/NhanVienXoaBaiVietDTO.cs), [[32]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienSuaRoleDTO.cs), [[33]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThem1DichVuDTO.cs), [[34]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThem1PhongDTO.cs), [[35]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThem1TienNghiDTO.cs), [[36]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThemAnhDTO.cs), [[37]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThemMaGiamGiaDTO.cs), [[38]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThemNhieuDichVu.cs), [[39]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/DTOs/QuanTriVien/QuanTriVienThemNhieuTienNghiDTO.cs)
124 |
--------------------------------------------------------------------------------
/02_validation__fluentvalidation__.md:
--------------------------------------------------------------------------------
1 | # Chapter 2: Validation (FluentValidation)
2 |
3 | Welcome back! In [Chapter 1: Data Transfer Objects (DTOs)](01_data_transfer_objects__dtos__.md), we learned that DTOs are like standardized forms used to exchange data with our API. They define *what* data we expect.
4 |
5 | But what happens if someone sends data that doesn't fill out the form correctly? What if they forget a required field, or provide a date that doesn't exist, or use an invalid email format?
6 |
7 | This is where **Validation** comes in. Just like a good hotel receptionist checks if your booking details are correct before giving you a room key, our API needs to check if the data it receives is valid and makes sense *before* it tries to process it.
8 |
9 | ## Why Validate Data?
10 |
11 | Imagine trying to save a new hotel booking in the database without knowing the guest's name or the check-in date. It would cause errors! Or imagine someone sending a ridiculously large number for the number of rooms – that could break things.
12 |
13 | Validation is crucial for several reasons:
14 |
15 | 1. **Preventing Bad Data:** It stops incorrect or incomplete data from entering our system (like the database).
16 | 2. **Improving Reliability:** By ensuring we only process valid data, our API functions more predictably and crashes less often.
17 | 3. **Better User Experience:** When validation fails, the API can send a clear message back to the client (like "Email address is invalid" or "Booking date is required"), helping the user correct their input.
18 | 4. **Separation of Concerns:** Validation rules are kept separate from the core business logic, making the code cleaner and easier to manage.
19 |
20 | In our `HotelManagementAPI` project, we use a popular library called **FluentValidation** to handle this process.
21 |
22 | ## Introducing FluentValidation
23 |
24 | While the Data Annotations (`[Required]`, `[StringLength]`) we saw in Chapter 1 can do basic validation, FluentValidation offers a more powerful and flexible way to define complex validation rules. It's especially good because it keeps the validation rules *separate* from the DTO class definition, making the DTOs cleaner and focusing solely on the data structure.
25 |
26 | FluentValidation works by defining **Validator classes**. Each validator class is responsible for checking the rules for a specific DTO class.
27 |
28 | Think of it like this:
29 |
30 | * **DTO:** The blank form itself (e.g., `QuanTriVienThem1TienNghiDTO` - the form for adding a facility).
31 | * **Validator:** A set of instructions or a checklist for reviewing *that specific form* (e.g., a validator class for `QuanTriVienThem1TienNghiDTO` saying "check if the Name field is filled and not too long").
32 |
33 | ## How to Define Validation Rules with FluentValidation
34 |
35 | Let's look at an example from our project. We have a DTO called `NguoiDungDTO` (User DTO), which represents data for a user (like registration or profile updates).
36 |
37 | You can find its validator at `Validators/NguoiDungDTOValidator.cs`:
38 |
39 | ```csharp
40 | using FluentValidation;
41 | using HotelManagementAPI.DTOs;
42 |
43 | // This class is the validator for the NguoiDungDTO
44 | public class NguoiDungDTOValidator : AbstractValidator
45 | {
46 | // The constructor is where we define all the validation rules
47 | public NguoiDungDTOValidator()
48 | {
49 | // Rule for the 'Email' property
50 | RuleFor(x => x.Email)
51 | .NotEmpty().WithMessage("Email là bắt buộc.") // Rule: Must not be empty
52 | .EmailAddress().WithMessage("Email không hợp lệ."); // Rule: Must be a valid email format
53 |
54 | // Rule for the 'TenTaiKhoan' (Username) property
55 | RuleFor(x => x.TenTaiKhoan)
56 | .NotEmpty().WithMessage("Tên tài khoản là bắt buộc.")
57 | .MaximumLength(50).WithMessage("Tên tài khoản không được vượt quá 50 ký tự.");
58 |
59 | // Rule for the 'MatKhau' (Password) property
60 | RuleFor(x => x.MatKhau)
61 | .NotEmpty().WithMessage("Mật khẩu là bắt buộc.")
62 | .MaximumLength(100).WithMessage("Mật khẩu không được vượt quá 100 ký tự.");
63 |
64 | // Rule for 'HoTen' (Full Name)
65 | RuleFor(x => x.HoTen)
66 | .MaximumLength(100).WithMessage("Họ tên không được vượt quá 100 ký tự."); // Optional, but has max length
67 |
68 | // Rule for 'SoDienThoai' (Phone Number)
69 | RuleFor(x => x.SoDienThoai)
70 | .NotEmpty().WithMessage("Số điện thoại là bắt buộc."); // Just checks if not empty
71 |
72 | // Rule for 'DiaChi' (Address)
73 | RuleFor(x => x.DiaChi)
74 | .NotEmpty().WithMessage("Địa chỉ là bắt buộc."); // Just checks if not empty
75 |
76 | // Rule for 'CanCuocCongDan' (Citizen ID)
77 | RuleFor(x => x.CanCuocCongDan)
78 | .NotEmpty().WithMessage("Căn cước công dân là bắt buộc.")
79 | .MaximumLength(12).WithMessage("Căn cước công dân không được vượt quá 12 ký tự.");
80 | }
81 | }
82 | ```
83 |
84 | Let's break down the key parts:
85 |
86 | * `public class NguoiDungDTOValidator : AbstractValidator`: This declares the validator class. It inherits from `AbstractValidator`, where `T` is the DTO it validates (`NguoiDungDTO`). This tells FluentValidation *which* DTO this validator is for.
87 | * `public NguoiDungDTOValidator()`: The constructor. All validation rules are defined inside this constructor.
88 | * `RuleFor(x => x.Email)`: This is how you start defining rules for a specific property. `x` represents the `NguoiDungDTO` object being validated, and `x.Email` selects the `Email` property.
89 | * `.NotEmpty()`: This is a built-in validation rule provided by FluentValidation. It checks if the property's value is not null, empty, or whitespace (for strings).
90 | * `.EmailAddress()`: Another rule that specifically checks if the string value has a format that looks like an email address.
91 | * `.MaximumLength(100)`: Checks if the string value's length does not exceed 100 characters.
92 | * `.GreaterThanOrEqualTo(0)`: (Seen in other validators like `PhongDetailsDTOValidator`) Checks if a number is greater than or equal to 0.
93 | * `.InclusiveBetween(1, 5)`: (Seen in `FeedBackDTOvalidation`) Checks if a number is within a specified range (inclusive).
94 | * `.WithMessage("...")`: This allows you to specify a custom error message that will be returned if *this specific rule* fails. This is much more user-friendly than a generic error.
95 |
96 | You chain these rules together using `.`. For example, `.NotEmpty().EmailAddress().WithMessage(...)` means "the property must not be empty AND must be a valid email format, and if either fails, use this message".
97 |
98 | You define one `RuleFor` block for each property you want to validate.
99 |
100 | ## How FluentValidation is Used in the API (Behind the Scenes)
101 |
102 | Our `HotelManagementAPI` project is set up to automatically use these validators. This setup happens when the application starts, in the `Program.cs` file.
103 |
104 | Look for these lines in `Program.cs`:
105 |
106 | ```csharp
107 | // ... other using statements ...
108 | using FluentValidation;
109 | using FluentValidation.AspNetCore; // Needed for ASP.NET Core integration
110 |
111 | // ... code before builder.Build() ...
112 |
113 | builder.Services.AddControllers(); // Configures controllers
114 | builder.Services.AddFluentValidationAutoValidation(); // Tells ASP.NET Core to use FluentValidation automatically
115 | builder.Services.AddFluentValidationClientsideAdapters(); // Optional: Helps generate client-side validation if needed (not used heavily in basic API)
116 | builder.Services.AddValidatorsFromAssemblyContaining(); // Scans the project assembly to find all validators
117 |
118 | // ... code after builder.Build() ...
119 | ```
120 |
121 | * `AddFluentValidationAutoValidation()`: This is the key line. It hooks FluentValidation into the ASP.NET Core's model validation process.
122 | * `AddValidatorsFromAssemblyContaining()`: This line tells FluentValidation to scan the assembly (the compiled project code) where the `Program.cs` file is located and automatically register *all* classes that inherit from `AbstractValidator` (like `NguoiDungDTOValidator`, `HoaDonDTOValidator`, etc.) so that the framework knows they exist and what DTO they validate.
123 |
124 | Because of this setup, you *don't* need to manually write code in your API controllers to say "now validate this DTO". The framework does it *for* you automatically before the controller action method is even executed.
125 |
126 | ## The Validation Flow
127 |
128 | When a request comes into an API endpoint that expects a DTO (like an endpoint to create a new user that takes `NguoiDungDTO` as a parameter), here's the simplified flow:
129 |
130 | ```mermaid
131 | sequenceDiagram
132 | participant Client as Browser/App
133 | participant ApiFramework as ASP.NET Core Framework
134 | participant FluentValidation as FluentValidation Library
135 | participant NguoiDungDTO as NguoiDungDTO Object
136 | participant NguoiDungValidator as NguoiDungDTOValidator
137 | participant ApiController as User Controller
138 |
139 | Client->>ApiFramework: Send HTTP POST request (e.g., /api/users)
with User data (JSON)
140 | ApiFramework->>NguoiDungDTO: Map JSON data to NguoiDungDTO object
Note over NguoiDungDTO: Object is created with incoming data (Model Binding)
141 | ApiFramework->>FluentValidation: Framework detects NguoiDungDTO parameter
and auto-triggers validation
142 | FluentValidation->>NguoiDungValidator: Find and use the registered
validator for NguoiDungDTO
143 | NguoiDungValidator->>NguoiDungDTO: Execute validation rules against the DTO object
144 | NguoiDungValidator-->>FluentValidation: Return validation results (success or list of errors)
145 | FluentValidation-->>ApiFramework: Pass validation results back
146 | ApiFramework->>ApiFramework: Check validation results (Model State)
147 | alt Validation Failed
148 | ApiFramework-->>Client: Return 400 Bad Request
with validation error details
149 | else Validation Succeeded
150 | ApiFramework->>ApiController: Execute controller action
passing the validated NguoiDungDTO object
151 | ApiController-->>Client: Return 2xx Success or other response
152 | end
153 | ```
154 |
155 | As you can see, if validation fails, the `ApiController` code *never even runs*. This keeps your controllers clean and focused on the business logic, assuming the data they receive is already valid.
156 |
157 | ## Benefits of FluentValidation in this Project
158 |
159 | * **Clean DTOs:** DTOs remain simple data containers without validation attributes cluttering them.
160 | * **Readable Rules:** The fluent interface (`RuleFor(...).NotEmpty()...`) is often easier to read and write, especially for complex rules.
161 | * **Reusable Validators:** A validator class can be reused anywhere that DTO is used as input.
162 | * **Clear Error Messages:** Easy to define custom, helpful messages.
163 | * **Automatic Integration:** Once configured in `Program.cs`, it runs automatically.
164 |
165 | ## Summary
166 |
167 | In this chapter, we explored the vital concept of Validation. We learned why checking incoming data is essential for building robust and reliable APIs, preventing bad data from entering our system and providing clear feedback to users.
168 |
169 | We saw how the `HotelManagementAPI` project uses FluentValidation to achieve this. We learned that FluentValidation uses separate Validator classes (`AbstractValidator`) to define rules (`RuleFor`, `NotEmpty`, `EmailAddress`, etc.) for our DTOs. Finally, we understood that thanks to the setup in `Program.cs`, this validation happens automatically before our controller code processes the data, ensuring that our controllers always receive valid information.
170 |
171 | Now that we know how data comes into our API (DTOs) and how we ensure that data is correct (Validation), we are ready to see where the actual API logic lives and how it receives and processes this validated data.
172 |
173 | Let's move on to [Chapter 3: API Controllers](03_api_controllers_.md)!
174 |
175 | ---
176 |
177 | Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge). **References**: [[1]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Program.cs), [[2]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/FeedBackDTOvalidation.cs), [[3]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/HoaDonDTOValidator.cs), [[4]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/LoginDTOValidator.cs), [[5]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/NguoiDungDTOValidator.cs), [[6]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/PhongAnhDTOValidator.cs), [[7]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/PhongDetailsDTOValidator.cs), [[8]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/ResetPasswordDTOValidator.cs), [[9]](https://github.com/Persinus/HotelManagementAPI/blob/36142c7f0bf93973f50c4408eb5a21a7f994eea2/Validators/ThanhToanDTOValidator.cs)
--------------------------------------------------------------------------------
/Controllers/CloudinanyController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using Microsoft.Extensions.Options;
3 | using CloudinaryDotNet;
4 | using CloudinaryDotNet.Actions;
5 | using Microsoft.AspNetCore.Authorization;
6 |
7 | [ApiController]
8 | [AllowAnonymous]
9 | [Route("api/[controller]")]
10 | public class UploadController : ControllerBase
11 | {
12 | private readonly Cloudinary _cloudinary;
13 | private readonly CloudinarySettings _settings;
14 |
15 | public UploadController(IOptions config)
16 | {
17 | _settings = config.Value;
18 |
19 | Console.WriteLine("==== Cloudinary Configuration ====");
20 | Console.WriteLine($"CloudName: {_settings.CloudName}");
21 | Console.WriteLine($"ApiKey: {_settings.ApiKey}");
22 | Console.WriteLine($"ApiSecret: {_settings.ApiSecret}");
23 | Console.WriteLine("==================================");
24 |
25 | var account = new Account(
26 | _settings.CloudName,
27 | _settings.ApiKey,
28 | _settings.ApiSecret
29 | );
30 |
31 | _cloudinary = new Cloudinary(account);
32 | }
33 |
34 | [HttpGet("config")]
35 | public IActionResult GetCloudinaryConfig()
36 | {
37 | if (string.IsNullOrWhiteSpace(_settings.CloudName) ||
38 | string.IsNullOrWhiteSpace(_settings.ApiKey) ||
39 | string.IsNullOrWhiteSpace(_settings.ApiSecret))
40 | {
41 | return BadRequest("❌ Cloudinary config is missing or invalid.");
42 | }
43 |
44 | return Ok(new
45 | {
46 | message = "✅ Cloudinary config loaded successfully.",
47 | cloudName = _settings.CloudName,
48 | apiKey = _settings.ApiKey,
49 | apiSecret = "********", // không in thật ra secret để tránh lộ key
50 | });
51 | }
52 |
53 | [HttpPost("image")]
54 | public async Task UploadImage(IFormFile file)
55 | {
56 | if (string.IsNullOrWhiteSpace(_settings.CloudName) ||
57 | string.IsNullOrWhiteSpace(_settings.ApiKey) ||
58 | string.IsNullOrWhiteSpace(_settings.ApiSecret))
59 | {
60 | return BadRequest("❌ Cloudinary settings are not configured properly.");
61 | }
62 |
63 | if (file == null || file.Length == 0)
64 | {
65 | return BadRequest("❌ No file uploaded.");
66 | }
67 |
68 | try
69 | {
70 | await using var stream = file.OpenReadStream();
71 | var uploadParams = new ImageUploadParams
72 | {
73 | File = new FileDescription(file.FileName, stream),
74 | Transformation = new Transformation().Width(800).Height(800).Crop("limit"),
75 | Folder = "test_upload"
76 | };
77 |
78 | var uploadResult = await _cloudinary.UploadAsync(uploadParams);
79 |
80 | if (uploadResult.StatusCode == System.Net.HttpStatusCode.OK)
81 | {
82 | Console.WriteLine("✅ Upload successful!");
83 | Console.WriteLine($"🔗 Image URL: {uploadResult.SecureUrl}");
84 |
85 | return Ok(new
86 | {
87 | message = "✅ Upload successful",
88 | url = uploadResult.SecureUrl.ToString()
89 | });
90 | }
91 |
92 | Console.WriteLine($"❌ Upload failed: {uploadResult.Error?.Message}");
93 | return StatusCode(500, $"❌ Upload failed: {uploadResult.Error?.Message}");
94 | }
95 | catch (Exception ex)
96 | {
97 | Console.WriteLine($"❌ Exception during upload: {ex.Message}");
98 | return StatusCode(500, $"❌ Exception during upload: {ex.Message}");
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Controllers/NhanVienController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using System.Data;
3 | using System.Threading.Tasks;
4 | using Dapper;
5 |
6 | using Microsoft.AspNetCore.Authorization;
7 | using HotelManagementAPI.DTOs.NhanVien;
8 | using System.Security.Claims;
9 | using CloudinaryDotNet;
10 | using CloudinaryDotNet.Actions;
11 | using Swashbuckle.AspNetCore.Annotations;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace HotelManagementAPI.Controllers.NhanVien
15 | {
16 | [ApiController]
17 | [Route("api/nhanvien")]
18 | [Authorize(Roles = "NhanVien")]
19 | public class NhanVienController : ControllerBase
20 | {
21 | private readonly IDbConnection _db;
22 | private readonly Cloudinary _cloudinary;
23 |
24 | public NhanVienController(
25 | IDbConnection db,
26 | IOptions cloudinaryOptions,
27 | IConfiguration config)
28 | {
29 | _db = db;
30 | var settings = cloudinaryOptions.Value;
31 | var account = new Account(
32 | settings.CloudName,
33 | settings.ApiKey,
34 | settings.ApiSecret
35 | );
36 | _cloudinary = new Cloudinary(account);
37 | }
38 |
39 | ///
40 | /// Thêm bài viết mới (nhân viên).
41 | ///
42 | [HttpPost("baiviet")]
43 | [SwaggerOperation(
44 | Summary = "Thêm bài viết mới",
45 | Description = "Nhân viên thêm bài viết mới, có thể upload ảnh kèm theo."
46 | )]
47 | [SwaggerResponse(200, "Thêm bài viết thành công.")]
48 | [SwaggerResponse(401, "Không xác định được nhân viên.")]
49 | public async Task ThemBaiViet([FromForm] NhanVienThemBaiVietDTO dto, IFormFile? file)
50 | {
51 | var maNguoiDung = User.FindFirstValue("sub") ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
52 | if (string.IsNullOrEmpty(maNguoiDung))
53 | return Unauthorized(new { Message = "❌ Không xác định được nhân viên. Vui lòng đăng nhập lại." });
54 |
55 | string? imageUrl = null;
56 | if (file != null && file.Length > 0)
57 | {
58 | await using var stream = file.OpenReadStream();
59 | var uploadParams = new ImageUploadParams
60 | {
61 | File = new FileDescription(file.FileName, stream),
62 | Transformation = new Transformation().Width(800).Height(800).Crop("limit"),
63 | Folder = "baiviet"
64 | };
65 | var uploadResult = await _cloudinary.UploadAsync(uploadParams);
66 | if (uploadResult.StatusCode == System.Net.HttpStatusCode.OK)
67 | imageUrl = uploadResult.SecureUrl.ToString();
68 | else
69 | return StatusCode(500, new { Message = $"❌ Xin lỗi, upload ảnh thất bại: {uploadResult.Error?.Message}" });
70 | }
71 |
72 | // Sinh mã bài viết tự động dạng MB001, MB002, ...
73 | const string getMaxSql = "SELECT ISNULL(MAX(CAST(SUBSTRING(MaBaiViet, 3, LEN(MaBaiViet)-2) AS INT)), 0) + 1 FROM BaiViet";
74 | var nextId = await _db.ExecuteScalarAsync(getMaxSql);
75 | var maBaiViet = $"MB{nextId:D3}";
76 | const string sql = @"
77 | INSERT INTO BaiViet (MaBaiViet, MaNguoiDung, TieuDe, NoiDung, NgayDang, HinhAnhUrl, TrangThai)
78 | VALUES (@MaBaiViet, @MaNguoiDung, @TieuDe, @NoiDung, @NgayDang, @HinhAnhUrl, @TrangThai)";
79 | await _db.ExecuteAsync(sql, new
80 | {
81 | MaBaiViet = maBaiViet,
82 | MaNguoiDung = maNguoiDung,
83 | dto.TieuDe,
84 | dto.NoiDung,
85 | NgayDang = DateTime.UtcNow.AddHours(7),
86 | HinhAnhUrl = imageUrl,
87 | TrangThai = "Chờ Duyệt"
88 | });
89 | // Thêm bài viết thành công
90 | return Ok(new
91 | {
92 | Message = "🎉 Thêm bài viết thành công! Bài viết của bạn đang chờ duyệt.",
93 | MaBaiViet = maBaiViet,
94 | HinhAnhUrl = imageUrl
95 | });
96 | }
97 |
98 |
99 | ///
100 | /// Xóa bài viết (nhân viên).
101 | ///
102 | [HttpDelete("baiviet/{maBaiViet}")]
103 | [SwaggerOperation(
104 | Summary = "Xóa bài viết",
105 | Description = "Nhân viên chỉ được xóa bài viết của chính mình."
106 | )]
107 | [SwaggerResponse(200, "Xóa bài viết thành công.")]
108 | [SwaggerResponse(401, "Không xác định được nhân viên.")]
109 | [SwaggerResponse(404, "Không tìm thấy bài viết hoặc không có quyền xóa.")]
110 | public async Task XoaBaiViet(string maBaiViet)
111 | {
112 | var maNguoiDung = User.FindFirstValue("sub") ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
113 | if (string.IsNullOrEmpty(maNguoiDung))
114 | return Unauthorized(new { Message = "❌ Không xác định được nhân viên. Vui lòng đăng nhập lại." });
115 |
116 | // Chỉ cho phép xóa bài viết của chính mình
117 | const string checkQuery = "SELECT COUNT(1) FROM BaiViet WHERE MaBaiViet = @MaBaiViet AND MaNguoiDung = @MaNguoiDung";
118 | var isExists = await _db.ExecuteScalarAsync(checkQuery, new { MaBaiViet = maBaiViet, MaNguoiDung = maNguoiDung });
119 | if (isExists == 0)
120 | return NotFound(new { Message = "❌ Xin lỗi, không tìm thấy bài viết hoặc bạn không có quyền xóa." });
121 |
122 | const string sql = "DELETE FROM BaiViet WHERE MaBaiViet = @MaBaiViet";
123 | await _db.ExecuteAsync(sql, new { MaBaiViet = maBaiViet });
124 | // Xóa bài viết thành công
125 | return Ok(new { Message = "✅ Xóa bài viết thành công! Bài viết đã được xóa khỏi hệ thống." });
126 | }
127 | }
128 |
129 | }
130 |
131 |
--------------------------------------------------------------------------------
/Controllers/QuanLyChungController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authorization;
2 | using Microsoft.AspNetCore.Mvc;
3 | using System.Data;
4 | using System.Threading.Tasks;
5 | using Dapper;
6 | using HotelManagementAPI.DTOs.QuanLyChung;
7 | using HotelManagementAPI.DTOs;
8 | using System.Security.Claims;
9 | using Swashbuckle.AspNetCore.Annotations;
10 | using Microsoft.Extensions.Configuration;
11 |
12 |
13 | namespace HotelManagementAPI.Controllers
14 | {
15 | [ApiController]
16 | [Route("api/quanlychung")]
17 | [Authorize(Roles = "NhanVien,QuanTriVien")]
18 | public class QuanLyChungController : ControllerBase
19 | {
20 | private readonly IDbConnection _db;
21 |
22 | public QuanLyChungController(IDbConnection db)
23 | {
24 | _db = db;
25 | }
26 |
27 | ///
28 | /// Cập nhật tiện nghi phòng.
29 | ///
30 | [HttpPut("phong/{maPhong}/tiennghi/{maTienNghi}")]
31 | [SwaggerOperation(
32 | Summary = "Cập nhật tiện nghi phòng",
33 | Description = "Cập nhật tiện nghi phòng, cả nhân viên và quản trị viên đều có quyền."
34 | )]
35 | [SwaggerResponse(200, "Cập nhật tiện nghi phòng thành công.")]
36 | [SwaggerResponse(404, "Tiện nghi không tồn tại.")]
37 | public async Task CapNhatTienNghi(string maPhong, string maTienNghi, [FromBody] QuanLyChungSuaPhongTienNghiDTO dto)
38 | {
39 | const string checkQuery = "SELECT COUNT(1) FROM Phong_TienNghi WHERE MaPhong = @MaPhong AND MaTienNghi = @MaTienNghi";
40 | var isExists = await _db.ExecuteScalarAsync(checkQuery, new { MaPhong = maPhong, MaTienNghi = maTienNghi });
41 |
42 | if (isExists == 0)
43 | return NotFound(new { Message = "❌ Xin lỗi, tiện nghi không tồn tại." });
44 |
45 | const string updateQuery = @"
46 | UPDATE TienNghi
47 | SET TenTienNghi = @TenTienNghi, MoTa = @MoTa
48 | WHERE MaTienNghi = @MaTienNghi";
49 | await _db.ExecuteAsync(updateQuery, new
50 | {
51 | MaTienNghi = maTienNghi,
52 | dto.TenTienNghi,
53 | dto.MoTa
54 | });
55 |
56 | return Ok(new { Message = "✅ Cập nhật tiện nghi phòng thành công!" });
57 | }
58 |
59 | ///
60 | /// Cập nhật dịch vụ.
61 | ///
62 | [HttpPut("dichvu/{maDichVu}")]
63 | [SwaggerOperation(
64 | Summary = "Cập nhật dịch vụ",
65 | Description = "Cập nhật dịch vụ, cả nhân viên và quản trị viên đều có quyền."
66 | )]
67 | [SwaggerResponse(200, "Cập nhật dịch vụ thành công.")]
68 | [SwaggerResponse(404, "Dịch vụ không tồn tại.")]
69 | public async Task UpdateDichVu(string maDichVu, [FromBody] QuanLyChungSuaDichVuDTO dto)
70 | {
71 | // Kiểm tra xem dịch vụ có tồn tại không
72 | const string checkQuery = "SELECT COUNT(1) FROM DichVu WHERE MaDichVu = @MaDichVu";
73 | var exists = await _db.ExecuteScalarAsync(checkQuery, new { MaDichVu = maDichVu });
74 | if (exists == 0)
75 | return NotFound(new { Message = "❌ Xin lỗi, dịch vụ không tồn tại." });
76 |
77 | const string sql = @"
78 | UPDATE DichVu SET
79 | TenDichVu = @TenDichVu,
80 | DonGia = @DonGia,
81 | MoTaDichVu = @MoTaDichVu,
82 | HinhAnhDichVu = @HinhAnhDichVu,
83 | SoLuong = @SoLuong,
84 | LoaiDichVu = @LoaiDichVu,
85 | DonViTinh = @DonViTinh
86 | WHERE MaDichVu = @MaDichVu";
87 | var affected = await _db.ExecuteAsync(sql, new
88 | {
89 | MaDichVu = maDichVu,
90 | dto.TenDichVu,
91 | dto.DonGia,
92 | dto.MoTaDichVu,
93 | dto.HinhAnhDichVu,
94 | dto.SoLuong,
95 | dto.LoaiDichVu,
96 | dto.DonViTinh
97 | });
98 | if (affected == 0) return NotFound();
99 | return Ok(new { Message = "✅ Cập nhật dịch vụ thành công!" });
100 | }
101 | ///
102 | /// Cập nhật thông tin giảm giá của phòng.
103 | ///
104 | /// Mã phòng
105 | /// Mã giảm giá
106 | /// Thông tin giảm giá mới
107 | // PUT: /api/nhanvien/phong/{maPhong}/giamgia/{maGiamGia}
108 | [HttpPut("{maPhong}/giamgia/{maGiamGia}")]
109 | public async Task CapNhatGiamGia(string maPhong, string maGiamGia, [FromBody] QuanLyChungSuaPhongGiamGiaDTO dto)
110 | {
111 | const string checkQuery = "SELECT COUNT(1) FROM Phong_GiamGia WHERE MaPhong = @MaPhong AND MaGiamGia = @MaGiamGia";
112 | var isExists = await _db.ExecuteScalarAsync(checkQuery, new { MaPhong = maPhong, MaGiamGia = maGiamGia });
113 |
114 | if (isExists == 0)
115 | return NotFound(new { Message = "❌ Xin lỗi, giảm giá không tồn tại." });
116 |
117 | const string updateQuery = @"
118 | UPDATE GiamGia
119 | SET TenGiamGia = @TenGiamGia, LoaiGiamGia = @LoaiGiamGia, GiaTriGiam = @GiaTriGiam,
120 | NgayBatDau = @NgayBatDau, NgayKetThuc = @NgayKetThuc, MoTa = @MoTa
121 | WHERE MaGiamGia = @MaGiamGia";
122 | await _db.ExecuteAsync(updateQuery, new
123 | {
124 | MaGiamGia = maGiamGia,
125 | dto.TenGiamGia,
126 | dto.LoaiGiamGia,
127 | dto.GiaTriGiam,
128 | dto.NgayBatDau,
129 | dto.NgayKetThuc,
130 | dto.MoTa
131 | });
132 |
133 | return Ok(new { Message = "✅ Cập nhật giảm giá cho phòng thành công!" });
134 | }
135 |
136 | ///
137 | /// Cập nhật ảnh phòng.
138 | ///
139 | /// Mã phòng
140 | /// Mã ảnh
141 | /// Thông tin ảnh mới
142 | // PUT: /api/nhanvien/phong/{maPhong}/phonganh/{maAnh}
143 | [HttpPut("{maPhong}/phonganh/{maAnh}")]
144 | public async Task CapNhatPhongAnh(string maPhong, string maAnh, [FromBody] QuanLyChungSuaPhongAnhDTO dto)
145 | {
146 | const string checkQuery = "SELECT COUNT(1) FROM PhongAnh WHERE MaPhong = @MaPhong AND MaAnh = @MaAnh";
147 | var isExists = await _db.ExecuteScalarAsync(checkQuery, new { MaPhong = maPhong, MaAnh = maAnh });
148 |
149 | if (isExists == 0)
150 | return NotFound(new { Message = "❌ Xin lỗi, ảnh không tồn tại." });
151 |
152 | const string updateQuery = @"
153 | UPDATE PhongAnh
154 | SET UrlAnh = @UrlAnh
155 | WHERE MaPhong = @MaPhong AND MaAnh = @MaAnh";
156 | await _db.ExecuteAsync(updateQuery, new
157 | {
158 | MaPhong = maPhong,
159 | MaAnh = maAnh,
160 | dto.UrlAnh
161 | });
162 |
163 | return Ok(new { Message = "✅ Cập nhật ảnh phòng thành công!" });
164 | }
165 |
166 | // Xem tất cả mã giảm giá
167 | [HttpGet("giamgia/all")]
168 | [SwaggerOperation(Summary = "Lấy tất cả mã giảm giá", Description = "Lấy danh sách tất cả mã giảm giá.")]
169 | [SwaggerResponse(200, "Danh sách mã giảm giá.")]
170 | public async Task GetAllGiamGia()
171 | {
172 | const string query = "SELECT * FROM GiamGia";
173 | var list = await _db.QueryAsync(query);
174 | return Ok(new { Message = "✅ Lấy danh sách mã giảm giá thành công!", Data = list });
175 | }
176 |
177 | // Xem chi tiết mã giảm giá theo mã
178 | [HttpGet("giamgia/{maGiamGia}")]
179 | [SwaggerOperation(Summary = "Lấy chi tiết mã giảm giá", Description = "Lấy chi tiết một mã giảm giá theo mã.")]
180 | [SwaggerResponse(200, "Chi tiết mã giảm giá.")]
181 | [SwaggerResponse(404, "Không tìm thấy mã giảm giá.")]
182 | public async Task GetGiamGiaByMa(string maGiamGia)
183 | {
184 | const string query = "SELECT * FROM GiamGia WHERE MaGiamGia = @MaGiamGia";
185 | var result = await _db.QueryFirstOrDefaultAsync(query, new { MaGiamGia = maGiamGia });
186 | if (result == null)
187 | return NotFound(new { Message = "❌ Không tìm thấy mã giảm giá." });
188 | return Ok(new { Message = "✅ Lấy chi tiết mã giảm giá thành công!", Data = result });
189 | }
190 | ///
191 | /// Sửa bài viết (nhân viên).
192 | ///
193 | [HttpPut("baiviet")]
194 | [SwaggerOperation(
195 | Summary = "Sửa bài viết",
196 | Description = "Nhân viên chỉ được sửa bài viết của chính mình."
197 | )]
198 | [SwaggerResponse(200, "Sửa bài viết thành công.")]
199 | [SwaggerResponse(401, "Không xác định được nhân viên.")]
200 | [SwaggerResponse(404, "Không tìm thấy bài viết hoặc không có quyền sửa.")]
201 | public async Task SuaBaiViet([FromBody] QuanLyChungSuaBaiVietDTO dto)
202 | {
203 | var maNguoiDung = User.FindFirstValue("sub") ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
204 | if (string.IsNullOrEmpty(maNguoiDung))
205 | return Unauthorized(new { Message = "❌ Không xác định được nhân viên. Vui lòng đăng nhập lại." });
206 |
207 | // Chỉ cho phép sửa bài viết của chính mình
208 | const string checkQuery = "SELECT COUNT(1) FROM BaiViet WHERE MaBaiViet = @MaBaiViet AND MaNguoiDung = @MaNguoiDung";
209 | var isExists = await _db.ExecuteScalarAsync(checkQuery, new { dto.MaBaiViet, MaNguoiDung = maNguoiDung });
210 | if (isExists == 0)
211 | return NotFound(new { Message = "❌ Không tìm thấy bài viết hoặc bạn không có quyền sửa." });
212 |
213 | const string sql = @"
214 | UPDATE BaiViet
215 | SET TieuDe = @TieuDe, NoiDung = @NoiDung, HinhAnhUrl = @HinhAnhUrl
216 | WHERE MaBaiViet = @MaBaiViet";
217 | await _db.ExecuteAsync(sql, new
218 | {
219 | dto.MaBaiViet,
220 | dto.TieuDe,
221 | dto.NoiDung,
222 | dto.HinhAnhUrl
223 | });
224 | return Ok(new { Message = "✅ Sửa bài viết thành công!" });
225 | }
226 | }
227 | }
--------------------------------------------------------------------------------
/Controllers/VnPayController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 |
3 | using System.Collections.Generic;
4 | using HotelManagementAPI.Models;
5 | using HotelManagementAPI.Services;
6 | using VNPAY.NET.Enums;
7 | namespace MyApp.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | [ApiController]
11 | public class VnpayController : ControllerBase
12 | {
13 | private readonly IVnpayService _vnpayService;
14 |
15 | public VnpayController(IVnpayService vnpayService)
16 | {
17 | _vnpayService = vnpayService;
18 | }
19 |
20 | [HttpGet("CreatePaymentUrl")]
21 | public IActionResult CreatePaymentUrl(double moneyToPay, string description)
22 | {
23 | try
24 | {
25 | var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
26 | var uniqueId = DateTime.UtcNow.Ticks.ToString() + new Random().Next(1000, 9999).ToString();
27 | var nowUtcPlus7 = DateTime.UtcNow.AddHours(7); // Giờ VN (UTC+7)
28 |
29 | var paymentRequest = new PaymentRequest
30 | {
31 | PaymentId = uniqueId, // Lưu dưới dạng chuỗi
32 | Money = moneyToPay,
33 | Description = description,
34 | IpAddress = ipAddress,
35 | BankCode = BankCode.ANY.ToString(),
36 | CreatedDate = nowUtcPlus7,
37 | ExpireDate = nowUtcPlus7.AddMinutes(15), // Thời gian hết hạn sau 15 phút
38 |
39 | Currency = Currency.VND.ToString(),
40 | Language = DisplayLanguage.Vietnamese.ToString()
41 | // Nếu có ExpireDate, set ví dụ: ExpireDate = nowUtcPlus7.AddMinutes(15)
42 | };
43 |
44 | var paymentUrl = _vnpayService.CreatePaymentUrl(paymentRequest);
45 | return Created(paymentUrl, paymentUrl);
46 | }
47 | catch (Exception ex)
48 | {
49 | return BadRequest(ex.Message);
50 | }
51 |
52 | }
53 |
54 | [HttpGet("IpnAction")]
55 | public IActionResult IpnAction()
56 | {
57 | if (Request.QueryString.HasValue)
58 | {
59 | try
60 | {
61 | var queryParams = new Dictionary();
62 | foreach (var key in Request.Query.Keys)
63 | {
64 | queryParams[key] = Request.Query[key];
65 | }
66 |
67 | var paymentResult = _vnpayService.HandleIpn(queryParams);
68 |
69 | if (paymentResult.IsSuccess)
70 | {
71 | return Ok("Payment succeeded");
72 | }
73 |
74 | return BadRequest("Payment failed");
75 | }
76 | catch (Exception ex)
77 | {
78 | return BadRequest(ex.Message);
79 | }
80 | }
81 |
82 | return NotFound("No query string found");
83 | }
84 | [HttpGet("Callback")]
85 | public IActionResult Callback()
86 | {
87 | if (Request.QueryString.HasValue)
88 | {
89 | try
90 | {
91 | var queryParams = new Dictionary();
92 | foreach (var key in Request.Query.Keys)
93 | {
94 | queryParams[key] = Request.Query[key];
95 | }
96 |
97 | // Process query params as needed for callback
98 | return Ok("Callback handled successfully");
99 | }
100 | catch (Exception ex)
101 | {
102 | return BadRequest(ex.Message);
103 | }
104 | }
105 |
106 | return NotFound("No query string found");
107 | }
108 |
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Controllers/XacThucController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authorization;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Caching.Memory;
4 | using System.Security.Claims;
5 | using System.Data;
6 | using Dapper;
7 | using System;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using HotelManagementAPI.DTOs;
11 | using CloudinaryDotNet;
12 | using CloudinaryDotNet.Actions;
13 | using Microsoft.Extensions.Options;
14 |
15 | namespace HotelManagementAPI.Controllers
16 | {
17 | [ApiController]
18 | [Authorize]
19 | [Route("api/xacthuc")]
20 | public class XacThucController : ControllerBase
21 | {
22 | private readonly IMemoryCache _cache;
23 | private readonly IDbConnection _db;
24 | private readonly Cloudinary _cloudinary;
25 |
26 | public XacThucController(
27 | IMemoryCache cache,
28 | IDbConnection db,
29 | IOptions cloudinaryOptions)
30 | {
31 | _cache = cache;
32 | _db = db;
33 | var settings = cloudinaryOptions.Value;
34 | var account = new Account(
35 | settings.CloudName,
36 | settings.ApiKey,
37 | settings.ApiSecret
38 | );
39 | _cloudinary = new Cloudinary(account);
40 | }
41 |
42 |
43 | ///
44 | /// Lấy thông tin profile người dùng.
45 | ///
46 | [HttpGet("profile")]
47 |
48 | public async Task GetProfile()
49 | {
50 | var maNguoiDung = User.FindFirstValue("sub") ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
51 | if (string.IsNullOrEmpty(maNguoiDung))
52 | return Unauthorized(new { Message = "❌ Không xác định được người dùng. Vui lòng đăng nhập lại." });
53 |
54 | const string query = @"SELECT * FROM NguoiDung WHERE MaNguoiDung = @MaNguoiDung";
55 | var profile = await _db.QueryFirstOrDefaultAsync(query, new { MaNguoiDung = maNguoiDung });
56 |
57 | // Giải mã CCCD nếu có
58 | try
59 | {
60 | profile.CanCuocCongDan = HotelManagementAPI.Helper.SensitiveDataHelper.Decrypt(profile.CanCuocCongDan);
61 | }
62 | catch
63 | {
64 | profile.CanCuocCongDan = "Không giải mã được";
65 | }
66 |
67 | if (profile == null)
68 | return NotFound(new { Message = "❌ Không tìm thấy thông tin người dùng." });
69 |
70 | return Ok(new { Message = "✅ Lấy thông tin người dùng thành công.", Data = profile });
71 | }
72 |
73 |
74 | ///
75 | /// Sửa thông tin người dùng dựa vào token.
76 | ///
77 | [HttpPut("profile")]
78 | public async Task UpdateProfile([FromForm] SuaThongTinNguoiDungDTO dto, IFormFile? file)
79 | {
80 | var maNguoiDung = User.FindFirstValue("sub") ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
81 | if (string.IsNullOrEmpty(maNguoiDung))
82 | return Unauthorized(new { Message = "❌ Không xác định được người dùng. Vui lòng đăng nhập lại." });
83 |
84 | // Lấy link ảnh cũ
85 | const string getSql = "SELECT HinhAnhUrl, CanCuocCongDan FROM NguoiDung WHERE MaNguoiDung = @MaNguoiDung";
86 | var user = await _db.QueryFirstOrDefaultAsync(getSql, new { MaNguoiDung = maNguoiDung });
87 | string? imageUrl = user?.HinhAnhUrl;
88 | string? canCuocCongDan = user?.CanCuocCongDan;
89 |
90 | // Upload ảnh mới nếu có
91 | if (file != null && file.Length > 0)
92 | {
93 | await using var stream = file.OpenReadStream();
94 | var uploadParams = new ImageUploadParams
95 | {
96 | File = new FileDescription(file.FileName, stream),
97 | Transformation = new Transformation().Width(400).Height(400).Crop("limit"),
98 | Folder = "avatar"
99 | };
100 | var uploadResult = await _cloudinary.UploadAsync(uploadParams);
101 | if (uploadResult.StatusCode == System.Net.HttpStatusCode.OK)
102 | imageUrl = uploadResult.SecureUrl.ToString();
103 | else
104 | return StatusCode(500, new { Message = $"❌ Upload ảnh thất bại: {uploadResult.Error?.Message}" });
105 | }
106 |
107 | // Mã hóa CCCD nếu có cập nhật mới
108 | if (!string.IsNullOrEmpty(dto.CanCuocCongDan))
109 | canCuocCongDan = HotelManagementAPI.Helper.SensitiveDataHelper.Encrypt(dto.CanCuocCongDan);
110 |
111 | const string sql = @"
112 | UPDATE NguoiDung SET
113 | HoTen = @HoTen,
114 | SoDienThoai = @SoDienThoai,
115 | DiaChi = @DiaChi,
116 | NgaySinh = @NgaySinh,
117 | GioiTinh = @GioiTinh,
118 | HinhAnhUrl = @HinhAnhUrl,
119 | CanCuocCongDan = @CanCuocCongDan
120 | WHERE MaNguoiDung = @MaNguoiDung";
121 |
122 | var affected = await _db.ExecuteAsync(sql, new
123 | {
124 | MaNguoiDung = maNguoiDung,
125 | dto.HoTen,
126 | dto.SoDienThoai,
127 | dto.DiaChi,
128 | dto.NgaySinh,
129 | dto.GioiTinh,
130 | HinhAnhUrl = imageUrl,
131 | CanCuocCongDan = canCuocCongDan
132 | });
133 |
134 | if (affected == 0)
135 | return NotFound(new { Message = "❌ Không tìm thấy người dùng để cập nhật." });
136 |
137 | return Ok(new { Message = "🎉 Cập nhật thông tin thành công! Chúc bạn một ngày tốt lành.", HinhAnhUrl = imageUrl });
138 | }
139 | }
140 | }
--------------------------------------------------------------------------------
/DTOs/Chung/DangNhapDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | namespace HotelManagementAPI.DTOs
3 | {
4 | public class LoginDTO
5 | {
6 |
7 | public string TenTaiKhoan { get; set; } // Bắt buộc
8 |
9 | public string MatKhau { get; set; } // Bắt buộc
10 | }
11 | }
--------------------------------------------------------------------------------
/DTOs/Chung/NguoiDungDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class NguoiDungDTO
7 | {
8 | [JsonIgnore]
9 | public string? MaNguoiDung { get; set; }
10 |
11 | [JsonIgnore]
12 | public string? Vaitro { get; set; }
13 |
14 | public string Email { get; set; } = null!;
15 | public string TenTaiKhoan { get; set; } = null!;
16 | public string MatKhau { get; set; } = null!;
17 | public string? HoTen { get; set; }
18 | public string? SoDienThoai { get; set; }
19 | public string? DiaChi { get; set; }
20 | public DateTime? NgaySinh { get; set; }
21 | public string? GioiTinh { get; set; }
22 | public string? HinhAnhUrl { get; set; }
23 | public string? CanCuocCongDan { get; set; }
24 | public DateTime? NgayTao { get; set; }
25 | }
26 | }
--------------------------------------------------------------------------------
/DTOs/Chung/NguoiDungDangKyDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class NguoiDungDangKyDTO
6 | {
7 | public string TenTaiKhoan { get; set; } = null!;
8 | public string MatKhau { get; set; } = null!;
9 | public string HoTen { get; set; } = null!;
10 | public string SoDienThoai { get; set; } = null!;
11 | public string DiaChi { get; set; } = null!;
12 | public DateTime? NgaySinh { get; set; }
13 | public string? GioiTinh { get; set; }
14 | public string Email { get; set; } = null!;
15 | public string? CanCuocCongDan { get; set; }
16 |
17 | // Không cần HinhAnhUrl vì sẽ upload qua Cloudinary và gán ở controller
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/DTOs/Chung/ResetPasswordDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class ResetPasswordDTO
6 | {
7 | public string Email { get; set; } = null!;
8 | public string NewPassword { get; set; } = null!;
9 | }
10 | }
--------------------------------------------------------------------------------
/DTOs/Chung/SuaThongTinNguoiDungDTO.CS:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class SuaThongTinNguoiDungDTO
7 | {
8 |
9 | public string Email { get; set; } = null!;
10 | public string TenTaiKhoan { get; set; } = null!;
11 |
12 | public string? HoTen { get; set; }
13 | public string? SoDienThoai { get; set; }
14 | public string? DiaChi { get; set; }
15 | public DateTime? NgaySinh { get; set; }
16 | public string? GioiTinh { get; set; }
17 |
18 | public string? CanCuocCongDan { get; set; }
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/DichVuDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class DichVuDTO
7 | {
8 |
9 | public string? MaDichVu { get; set; }
10 |
11 | [Required]
12 | [StringLength(100)]
13 | public string TenDichVu { get; set; } = null!;
14 |
15 | [Required]
16 | [Range(0, double.MaxValue, ErrorMessage = "Đơn giá phải lớn hơn hoặc bằng 0.")]
17 | public decimal DonGia { get; set; }
18 |
19 | [Required]
20 |
21 | public string? MoTaDichVu { get; set; }
22 |
23 | [Required]
24 | [Url(ErrorMessage = "URL hình ảnh không hợp lệ.")]
25 | public string HinhAnhDichVu { get; set; } = null!;
26 |
27 | [Required]
28 | [Range(0, int.MaxValue, ErrorMessage = "Số lượng phải lớn hơn hoặc bằng 0.")]
29 | public int SoLuong { get; set; }
30 |
31 |
32 |
33 | [Required]
34 | [StringLength(50)]
35 | public string LoaiDichVu { get; set; } = null!;
36 |
37 | [Required]
38 | [StringLength(50)]
39 | public string DonViTinh { get; set; } = null!;
40 | }
41 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/FeedBackDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 | using System.Text.Json.Serialization;
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class FeedBackDTO
7 | {
8 | [JsonIgnore]
9 | public string? MaFeedback { get; set; } = null!;
10 | [JsonIgnore]
11 | public string? MaPhong { get; set; } = null!;
12 | [JsonIgnore]
13 | public string? MaNguoiDung { get; set; } = null!;
14 | public int SoSao { get; set; }
15 | public string? BinhLuan { get; set; }
16 | [JsonIgnore]
17 | public DateTime? NgayFeedback { get; set; }
18 | public string PhanLoai { get; set; } = null!;
19 | }
20 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/GiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class GiamGiaDTO
6 | {
7 |
8 | public string MaGiamGia { get; set; } = null!;
9 | public decimal GiaTriGiam { get; set; }
10 | public DateTime NgayKetThuc { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/GiamGiaDetailDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class GiamGiaDetailDTO
6 | {
7 | [StringLength(6)]
8 | public string MaGiamGia { get; set; } = null!;
9 |
10 | [StringLength(50)]
11 | public string TenGiamGia { get; set; } = null!;
12 |
13 | [Range(0, double.MaxValue)]
14 | public decimal GiaTriGiam { get; set; }
15 |
16 | public DateTime NgayBatDau { get; set; }
17 |
18 | public DateTime NgayKetThuc { get; set; }
19 |
20 | [StringLength(255)]
21 | public string? MoTa { get; set; }
22 | }
23 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/PhongAnhDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class PhongAnhDTO
6 | {
7 |
8 | public string MaAnh { get; set; } = null!;
9 |
10 |
11 | public string MaPhong { get; set; } = null!;
12 |
13 | public string UrlAnh { get; set; } = null!;
14 | }
15 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/PhongDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class PhongDTO
6 | {
7 | public string MaPhong { get; set; } = null!;
8 | public string LoaiPhong { get; set; } = null!;
9 | public decimal GiaPhong { get; set; }
10 | public decimal GiaUuDai { get; set; }
11 | public int Tang { get; set; }
12 | public string TinhTrang { get; set; } = null!;
13 | public string DonViTinh { get; set; } = null!;
14 | public decimal SoSaoTrungBinh { get; set; }
15 | public string MoTa { get; set; } = null!;
16 | public string UrlAnhChinh { get; set; } = null!;
17 | public List GiamGia { get; set; } = new List();
18 | }
19 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/PhongDetailsDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class PhongDetailsDTO
7 | {
8 | public string MaPhong { get; set; } = null!;
9 | public string LoaiPhong { get; set; } = null!;
10 | public decimal GiaPhong { get; set; }
11 | public string TinhTrang { get; set; } = null!;
12 | [JsonIgnore]
13 | public int SoLuongPhong { get; set; }
14 | public int Tang { get; set; }
15 | public string KieuGiuong { get; set; } = null!;
16 | public string? MoTa { get; set; }
17 | public string UrlAnhChinh { get; set; } = null!;
18 | public string? MotaPhong { get; set; }
19 | public int SucChua { get; set; }
20 | public int SoGiuong { get; set; }
21 | public string DonViTinh { get; set; } = null!;
22 | public decimal SoSaoTrungBinh { get; set; }
23 | public List UrlAnhPhu { get; set; } = new List();
24 | public List TienNghi { get; set; } = new List();
25 | public List GiamGia { get; set; } = new List();
26 | public List Feedbacks { get; set; } = new List();
27 | public List YeuThich { get; set; } = new List();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/PhongYeuThichDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class PhongYeuThichDTO
6 | {
7 | public int Id { get; set; }
8 | public string MaPhong { get; set; } = null!;
9 | public string MaNguoiDung { get; set; } = null!;
10 | public DateTime? NgayYeuThich { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/TatCaBaiVietDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HotelManagementAPI.DTOs
4 | {
5 | public class TatCaBaiVietDTO
6 | {
7 | public string MaBaiViet { get; set; } = null!;
8 | public string MaNguoiDung { get; set; } = null!;
9 | public string TieuDe { get; set; } = null!;
10 | public string NoiDung { get; set; } = null!;
11 | public DateTime? NgayDang { get; set; }
12 | public string? HinhAnhUrl { get; set; }
13 | public string? TrangThai { get; set; }
14 |
15 | // Nếu muốn show tên người đăng bài, có thể thêm:
16 | // public string? TenNguoiDung { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/DTOs/HienThiTatCaXem/TienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 | using System.ComponentModel.DataAnnotations;
3 | namespace HotelManagementAPI.DTOs
4 | {
5 |
6 |
7 | public class TienNghiDTO
8 |
9 | {
10 | [StringLength(6)]
11 | public string MaTienNghi { get; set; } = null!;
12 |
13 | [StringLength(100)]
14 | public string TenTienNghi { get; set; } = null!;
15 |
16 | public string? MoTa { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangChiTietHoaDon.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs.KhachHang
4 | {
5 | public class KhachHangChiTietHoaDonDTO
6 | {
7 | [Required]
8 | [StringLength(6)]
9 | public string MaChiTiet { get; set; } = null!;
10 |
11 | [Required]
12 | [StringLength(6)]
13 | public string MaHoaDon { get; set; } = null!;
14 |
15 | [Required]
16 | [StringLength(12)]
17 | public string LoaiKhoanMuc { get; set; } = null!;
18 |
19 | [Required]
20 | [StringLength(12)]
21 | public string MaKhoanMuc { get; set; } = null!;
22 |
23 | [Required]
24 | [Range(1, int.MaxValue, ErrorMessage = "Số lượng phải lớn hơn hoặc bằng 1.")]
25 | public int SoLuong { get; set; }
26 |
27 | [Required]
28 | [Range(0, double.MaxValue, ErrorMessage = "Thành tiền phải lớn hơn hoặc bằng 0.")]
29 | public decimal ThanhTien { get; set; }
30 | }
31 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangDatDichVuDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs.KhachHang
5 | {
6 | public class KhachHangDatDichVuDTO
7 | {
8 | [JsonIgnore]
9 | public string? MaDatDichVu { get; set; } // Không required, BE tự sinh
10 | [JsonIgnore]
11 | public string? MaDatPhong { get; set; } // BE tự gán khi đặt dịch vụ kèm phòng
12 |
13 | public string MaDichVu { get; set; }
14 | public int SoLuong { get; set; }
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangDatPhongDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.Json.Serialization;
3 | using System;
4 |
5 | namespace HotelManagementAPI.DTOs.KhachHang
6 | {
7 | public class KhachHangDatPhongDTO
8 | {
9 | [JsonIgnore]
10 | public string? MaDatPhong { get; set; }
11 | [JsonIgnore]
12 | public string? MaNguoiDung { get; set; }
13 |
14 | public string? MaPhong { get; set; }
15 | [JsonIgnore]
16 | public DateTime NgayDat { get; set; }
17 |
18 | // Đổi tên cho đúng với DB
19 | public DateTime NgayCheckIn { get; set; }
20 | public DateTime NgayCheckOut { get; set; }
21 | // Nếu DB không có cột TongTien thì bỏ dòng này
22 | // public decimal TongTien { get; set; }
23 | [JsonIgnore]
24 | public byte TinhTrangDatPhong { get; set; }
25 | public List? DichVuDiKem { get; set; }
26 | }
27 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangFeedBackDTO.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.DTOs.KhachHang
2 | {
3 | public class KhachHangFeedBackDTO
4 | {
5 | public string MaPhong { get; set; } = null!;
6 | public int SoSao { get; set; }
7 | public string? BinhLuan { get; set; }
8 |
9 | }
10 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangHoaDonDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace HotelManagementAPI.DTOs.KhachHang
6 | {
7 | public class KhachHangHoaDonDTO
8 | {
9 |
10 | public string MaHoaDon { get; set; } = null!; // Tự động tạo
11 |
12 |
13 | public string MaNguoiDung { get; set; } = null!; // Bắt buộc
14 |
15 |
16 | public string MaDatPhong { get; set; } = null!; // Bắt buộc
17 |
18 | public decimal TongTien { get; set; } // Bắt buộc
19 |
20 | [JsonIgnore]
21 | public DateTime? NgayTaoHoaDon { get; set; } // Tự động tạo
22 |
23 | public DateTime? NgayThanhToan { get; set; } // Tùy chọn
24 |
25 | [Required]
26 | public byte TinhTrangHoaDon { get; set; } // 1: Chưa thanh toán, 2: Đã thanh toán
27 | }
28 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangLichSuGiaoDichDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.KhachHang
5 | {
6 | public class KhachHangLichSuGiaoDichDTO
7 | {
8 | [Required]
9 | [StringLength(6)]
10 | public string MaGiaoDich { get; set; } = null!; // Tự động tạo
11 |
12 | [Required]
13 | [StringLength(6)]
14 | public string MaNguoiDung { get; set; } = null!; // Bắt buộc
15 |
16 | [Required]
17 | public string LoaiGiaoDich { get; set; } = null!; // Bắt buộc
18 |
19 | public DateTime? ThoiGianGiaoDich { get; set; } // Tự động tạo
20 |
21 | public string? MoTa { get; set; } // Tùy chọn
22 | }
23 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangTaoHoaDonRequestDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.KhachHang
5 | {
6 | ///
7 | /// DTO để tạo hóa đơn từ yêu cầu của khách hàng.
8 | ///
9 | ///
10 | /// Chứa thông tin cần thiết để tạo hóa đơn, bao gồm mã đặt phòng và giá trị giảm giá.
11 | ///
12 | public class TaoHoaDonRequestDTO
13 | {
14 | public string MaDatPhong { get; set; } = null!;
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/DTOs/KhachHang/KhachHangThanhToanDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.KhachHang
5 | {
6 | public class KhachHangThanhToanDTO
7 | {
8 |
9 |
10 | [Required]
11 | [StringLength(6)]
12 | public string MaHoaDon { get; set; } = null!;
13 |
14 |
15 | public decimal SoTienThanhToan { get; set; }
16 |
17 |
18 |
19 | [Required]
20 | public string PhuongThucThanhToan { get; set; } = null!;
21 |
22 |
23 | }}
--------------------------------------------------------------------------------
/DTOs/NhanVien/BaoCaoDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs
5 | {
6 | public class BaoCaoDTO
7 | {
8 | [Required]
9 | [StringLength(6)]
10 | public string MaBaoCao { get; set; } = null!;
11 |
12 | [Required]
13 | public string LoaiBaoCao { get; set; } = null!;
14 | [Required]
15 | public DateTime? ThoiGian { get; set; }
16 |
17 | [Required]
18 | public string? NoiDung { get; set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/DTOs/NhanVien/ChiTietBaoCaoDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.NhanVien
5 | {
6 | public class ChiTietBaoCaoDTO
7 | {
8 | [Required]
9 | [StringLength(6)]
10 | public string MaChiTiet { get; set; } = null!;
11 |
12 | [Required]
13 | [StringLength(6)]
14 | public string MaBaoCao { get; set; } = null!;
15 |
16 | [Required]
17 | public string NoiDungChiTiet { get; set; } = null!;
18 |
19 | [Required]
20 | [Range(0, double.MaxValue, ErrorMessage = "Giá trị phải lớn hơn hoặc bằng 0.")]
21 | public decimal GiaTri { get; set; }
22 | }
23 | }
--------------------------------------------------------------------------------
/DTOs/NhanVien/NhanVienThemBaiVietDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace HotelManagementAPI.DTOs.NhanVien
5 | {
6 | public class NhanVienThemBaiVietDTO
7 | {
8 | public string TieuDe { get; set; } = null!;
9 | public string NoiDung { get; set; } = null!;
10 | // KHÔNG có TrangThai
11 | }
12 | }
--------------------------------------------------------------------------------
/DTOs/NhanVien/NhanVienXoaBaiVietDTO.cs:
--------------------------------------------------------------------------------
1 | //DTO xóa bài viết
2 | using System.ComponentModel.DataAnnotations;
3 | namespace HotelManagementAPI.DTOs.NhanVien
4 | {
5 | public class NhanVienXoaBaiVietDTO
6 | {
7 | [Required]
8 | [StringLength(6, ErrorMessage = "Mã bài viết phải có độ dài từ 1 đến 6 ký tự.")]
9 | public string MaBaiViet { get; set; } = null!;
10 |
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/DTOs/QuanLyChung/QuanLyChungSuaBaiVietDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace HotelManagementAPI.DTOs.QuanLyChung
6 | {
7 | public class QuanLyChungSuaBaiVietDTO
8 | {
9 | [Required]
10 | public string MaBaiViet { get; set; } = null!;
11 |
12 | [Required]
13 | [StringLength(100)]
14 | public string TieuDe { get; set; } = null!;
15 |
16 | [Required]
17 | public string NoiDung { get; set; } = null!;
18 |
19 | [JsonIgnore]
20 | public string? HinhAnhUrl { get; set; }
21 |
22 | // Ngày cập nhật nên xử lý trong backend, không để client truyền
23 | // public DateTime? NgayCapNhat { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DTOs/QuanLyChung/QuanLyChungSuaDichVuDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs.QuanLyChung
4 | {
5 | public class QuanLyChungSuaDichVuDTO
6 | {
7 |
8 |
9 | [Required]
10 | [StringLength(100)]
11 | public string TenDichVu { get; set; } = null!;
12 |
13 | [Required]
14 | [Range(0, double.MaxValue, ErrorMessage = "Đơn giá phải lớn hơn hoặc bằng 0.")]
15 | public decimal DonGia { get; set; }
16 |
17 | [Required]
18 | public string? MoTaDichVu { get; set; }
19 |
20 | [Required]
21 | [Url(ErrorMessage = "URL hình ảnh không hợp lệ.")]
22 | public string HinhAnhDichVu { get; set; } = null!;
23 |
24 | [Required]
25 | [Range(0, int.MaxValue, ErrorMessage = "Số lượng phải lớn hơn hoặc bằng 0.")]
26 | public int SoLuong { get; set; }
27 |
28 | [Required]
29 | [Range(0, 1, ErrorMessage = "Trạng thái phải là 0 (không hoạt động) hoặc 1 (hoạt động).")]
30 | public byte TrangThai { get; set; }
31 |
32 | [Required]
33 | [StringLength(50)]
34 | public string LoaiDichVu { get; set; } = null!;
35 |
36 | [Required]
37 | [StringLength(50)]
38 | public string DonViTinh { get; set; } = null!;
39 | }
40 | }
--------------------------------------------------------------------------------
/DTOs/QuanLyChung/QuanLyChungSuaPhongAnhPutDTO.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Text.Json.Serialization;
5 | // HotelManagementAPI.DTOs.QuanLyChung
6 | namespace HotelManagementAPI.DTOs.QuanLyChung
7 | {
8 | public class QuanLyChungSuaPhongAnhDTO
9 | {
10 | public string UrlAnh { get; set; } = null!;
11 | }
12 | }
--------------------------------------------------------------------------------
/DTOs/QuanLyChung/QuanLyChungSuaPhongGiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | // HotelManagementAPI.DTOs.QuanLyChung
4 | namespace HotelManagementAPI.DTOs.QuanLyChung{
5 | public class QuanLyChungSuaPhongGiamGiaDTO
6 | {
7 |
8 | public string TenGiamGia { get; set; } = null!;
9 |
10 | public string? LoaiGiamGia { get; set; }
11 |
12 | public decimal GiaTriGiam { get; set; }
13 |
14 | public DateTime NgayBatDau { get; set; }
15 |
16 | public DateTime NgayKetThuc { get; set; }
17 |
18 |
19 | public string? MoTa { get; set; }
20 | }
21 | }
--------------------------------------------------------------------------------
/DTOs/QuanLyChung/QuanLyChungSuaPhongTienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | // Project: QuanLyChung
2 | // File: DTOs/QuanLyChung/NhanVienSuaPhongTienNghiDTO.cs
3 | using System.ComponentModel.DataAnnotations;
4 | // HotelManagementAPI.DTOs.QuanLyChung
5 | namespace HotelManagementAPI.DTOs.QuanLyChung{
6 | public class QuanLyChungSuaPhongTienNghiDTO
7 | {
8 | public string TenTienNghi { get; set; } = null!;
9 |
10 | public string? MoTa { get; set; }
11 | }}
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienApDungGiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace HotelManagementAPI.DTOs.QuanTriVien
4 | {
5 | public class QuanTriVienApDungGiamGiaDTO
6 | {
7 | public string MaGiamGia { get; set; } = null!;
8 | public string TenGiamGia { get; set; } = null!;
9 | public decimal GiaTriGiam { get; set; }
10 | public DateTime NgayBatDau { get; set; }
11 | public DateTime NgayKetThuc { get; set; }
12 | public string? MoTa { get; set; }
13 | public List DanhSachMaPhong { get; set; } = new();
14 | }
15 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienSuaGiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.DTOs.QuanTriVien
2 | {
3 | public class QuanTriVienSuaGiamGiaDTO
4 | {
5 | public string MaGiamGia { get; set; } = null!;
6 | public string TenGiamGia { get; set; } = null!;
7 | public string? LoaiGiamGia { get; set; }
8 | public decimal GiaTriGiam { get; set; }
9 | public DateTime NgayBatDau { get; set; }
10 | public DateTime NgayKetThuc { get; set; }
11 | public string? MoTa { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienSuaNoiQuyDTO.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace HotelManagementAPI.DTOs.QuanTriVien
9 | {
10 | public class QuanTriVienSuaNoiQuyDTO
11 | {
12 | public int Id { get; set; }
13 | public string TenNoiQuy { get; set; }
14 | public string MoTa { get; set; }
15 | public DateTime NgayCapNhat { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienSuaRoleDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs.QuanTriVien
4 | {
5 | public class QuanTriVienSuaRoleDTO
6 | {
7 | [Required]
8 | public string VaiTroMoi { get; set; } = null!;
9 | }
10 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienSuaTrangThaiPhDTO.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Persinus/HotelManagementAPI/201422e12606043055a775309c98a2d7ce5b8470/DTOs/QuanTriVien/QuanTriVienSuaTrangThaiPhDTO.cs
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThem1DichVuDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs.QuanTriVien
4 | {
5 | public class QuanTriVienThem1DichVuDTO
6 | {
7 | [Required]
8 | [StringLength(100)]
9 | public string TenDichVu { get; set; } = null!;
10 |
11 | [Required]
12 | [Range(0, double.MaxValue, ErrorMessage = "Đơn giá phải lớn hơn hoặc bằng 0.")]
13 | public decimal DonGia { get; set; }
14 |
15 | [Required]
16 | public string? MoTaDichVu { get; set; }
17 |
18 |
19 |
20 | [Required]
21 | [Range(0, int.MaxValue, ErrorMessage = "Số lượng phải lớn hơn hoặc bằng 0.")]
22 | public int SoLuong { get; set; }
23 |
24 |
25 |
26 | [Required]
27 | [StringLength(50)]
28 | public string LoaiDichVu { get; set; } = null!;
29 |
30 | [Required]
31 | [StringLength(50)]
32 | public string DonViTinh { get; set; } = null!;
33 | }
34 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThem1NoiQuyDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace HotelManagementAPI.DTOs.QuanTriVien
8 | {
9 | public class QuanTriVienThem1NoiQuyDTO
10 | {
11 | public int Id { get; set; }
12 | public string TenNoiQuy { get; set; }
13 | public string MoTa { get; set; }
14 | public DateTime NgayTao { get; set; }
15 | public DateTime NgayCapNhat { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThem1PhongDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienThem1PhongDTO
7 | {
8 | public string LoaiPhong { get; set; }
9 | public decimal GiaPhong { get; set; }
10 |
11 | public int Tang { get; set; }
12 | public string KieuGiuong { get; set; }
13 | public string? MoTa { get; set; }
14 | public int SucChua { get; set; }
15 | public int SoGiuong { get; set; }
16 |
17 | // KHÔNG có List, mảng, object phức tạp ở đây!
18 | }
19 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThem1TienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace HotelManagementAPI.DTOs.QuanTriVien
4 | {
5 | public class QuanTriVienThem1TienNghiDTO
6 | {
7 | [Required]
8 | [StringLength(100)]
9 | public string TenTienNghi { get; set; } = null!;
10 |
11 | [StringLength(500)]
12 | public string? MoTa { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThemAnhDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienThemAnhDTO
7 | {
8 | [Required]
9 | public string MaPhong { get; set; } = null!;
10 |
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThemGiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.DTOs.QuanTriVien
2 | {
3 | public class QuanTriVienThemGiamGiaDTO
4 | {
5 | public string TenGiamGia { get; set; } = null!;
6 | public string? LoaiGiamGia { get; set; }
7 | public decimal GiaTriGiam { get; set; }
8 | public DateTime NgayBatDau { get; set; }
9 | public DateTime NgayKetThuc { get; set; }
10 | public string? MoTa { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThemMaGiamGiaDTO.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienThemMaGiamGiaDTO
7 | {
8 | [Required]
9 | [StringLength(50)]
10 | public string TenGiamGia { get; set; } = null!;
11 |
12 | [Required]
13 | [StringLength(6)]
14 | public string LoaiGiamGia { get; set; } = null!; // Ví dụ: "phantram" hoặc "trutien"
15 |
16 | [Required]
17 | [Range(0, double.MaxValue)]
18 | public decimal GiaTriGiam { get; set; }
19 |
20 | [Required]
21 | public DateTime NgayBatDau { get; set; }
22 |
23 | [Required]
24 | public DateTime NgayKetThuc { get; set; }
25 |
26 | [StringLength(255)]
27 | public string? MoTa { get; set; }
28 | }
29 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThemNhieuDichVu.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienThemNhieuDichVuDTO
7 | {
8 | [Required]
9 | public List DanhSachDichVu { get; set; } = new();
10 | }
11 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienThemNhieuTienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienThemNhieuTienNghiDTO
7 | {
8 | [Required]
9 | public List DanhSachTienNghi { get; set; } = new();
10 | }
11 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienXoa1Phong.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.DTOs.QuanTriVien
2 | {
3 | public class QuanTriVienXoa1PhongDTO
4 | {
5 | public string MaPhong { get; set; } = null!;
6 | }
7 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienXoa1TienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.DTOs.QuanTriVien
2 | {
3 | public class QuanTriVienXoa1TienNghiDTO
4 | {
5 | public string MaTienNghi { get; set; } = null!;
6 | }
7 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienXoaGiamGiaDTO.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Persinus/HotelManagementAPI/201422e12606043055a775309c98a2d7ce5b8470/DTOs/QuanTriVien/QuanTriVienXoaGiamGiaDTO.cs
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienXoaNhieuTienNghiDTO.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienXoaNhieuTienNghiDTO
7 | {
8 | [Required]
9 | public List DanhSachMaTienNghi { get; set; } = new();
10 | }
11 | }
--------------------------------------------------------------------------------
/DTOs/QuanTriVien/QuanTriVienXoaNoiQuyDTO.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.DTOs.QuanTriVien
5 | {
6 | public class QuanTriVienXoaNoiQuyDTO
7 | {
8 | public int Id { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/Data/Cloudinary.cs:
--------------------------------------------------------------------------------
1 | public class CloudinarySettings
2 | {
3 | public string CloudName { get; set; }
4 | public string ApiKey { get; set; }
5 | public string ApiSecret { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/Data/Hotelnhom2Context.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using HotelManagementAPI.Models;
4 | using Microsoft.EntityFrameworkCore;
5 |
6 | namespace HotelManagementAPI.Data;
7 |
8 | public partial class Hotelnhom2Context : DbContext
9 | {
10 | public Hotelnhom2Context()
11 | {
12 | }
13 |
14 | public Hotelnhom2Context(DbContextOptions options)
15 | : base(options)
16 | {
17 | }
18 |
19 | public virtual DbSet Feedbacks { get; set; }
20 |
21 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
22 | #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
23 | => optionsBuilder.UseSqlServer("Server=118.69.126.49;Database=data_QLKS_115_Nhom2;User Id=user_115_nhom2;Password=123456789;TrustServerCertificate=True;");
24 |
25 | protected override void OnModelCreating(ModelBuilder modelBuilder)
26 | {
27 | modelBuilder.Entity(entity =>
28 | {
29 | entity.HasKey(e => e.MaFeedback).HasName("PK__Feedback__63042CF68D0745C0");
30 |
31 | entity.ToTable("Feedback");
32 |
33 | entity.Property(e => e.MaFeedback).HasMaxLength(6);
34 | entity.Property(e => e.BinhLuan).HasMaxLength(500);
35 | entity.Property(e => e.MaNguoiDung).HasMaxLength(6);
36 | entity.Property(e => e.MaPhong).HasMaxLength(6);
37 | entity.Property(e => e.NgayFeedback)
38 | .HasDefaultValueSql("(getdate())")
39 | .HasColumnType("datetime");
40 | entity.Property(e => e.PhanLoai).HasMaxLength(10);
41 | });
42 |
43 | OnModelCreatingPartial(modelBuilder);
44 | }
45 |
46 | partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
47 | }
48 |
--------------------------------------------------------------------------------
/Data/SentimentData.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ML.Data;
2 |
3 | namespace SentimentAnalysisExample.Data // Hoặc Models
4 | {
5 | public class SentimentData
6 | {
7 | public string SentimentText { get; set; }
8 | }
9 |
10 | public class SentimentPrediction : SentimentData
11 | {
12 | [ColumnName("PredictedLabel")]
13 | public bool Prediction { get; set; }
14 |
15 | [ColumnName("Probability")]
16 | public float Probability { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/Helper/HelperJWT.cs:
--------------------------------------------------------------------------------
1 | using System.IdentityModel.Tokens.Jwt;
2 | using System.Security.Claims;
3 | using System.Text;
4 | using Microsoft.IdentityModel.Tokens;
5 | using HotelManagementAPI.Models; // Added namespace for NguoiDung
6 |
7 | namespace HotelManagementAPI.Helper
8 | {
9 | public static class JwtHelper
10 | {
11 | public static string GenerateJwtToken(NguoiDung nguoiDung, string secretKey, string issuer, string audience)
12 | {
13 | var claims = new[]
14 | {
15 | new Claim(JwtRegisteredClaimNames.Sub, nguoiDung.MaNguoiDung.ToString()),
16 | new Claim("Vaitro", nguoiDung.Vaitro), // Đảm bảo claim "Vaitro" được thêm
17 | new Claim(JwtRegisteredClaimNames.Email, nguoiDung.Email),
18 | new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
19 | };
20 |
21 | // Ghi log các claims khi tạo token
22 | Console.WriteLine("Claims khi tạo JWT token:");
23 | foreach (var claim in claims)
24 | {
25 | Console.WriteLine($"Claim Type: {claim.Type}, Claim Value: {claim.Value}");
26 | }
27 |
28 | var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
29 | var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
30 |
31 | var token = new JwtSecurityToken(
32 | issuer: issuer,
33 | audience: audience,
34 | claims: claims,
35 | expires: DateTime.Now.AddHours(1),
36 | signingCredentials: creds
37 | );
38 |
39 | return new JwtSecurityTokenHandler().WriteToken(token);
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Helper/SensitiveDataHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography;
3 | using System.Text;
4 |
5 | namespace HotelManagementAPI.Helper
6 | {
7 | public static class SensitiveDataHelper
8 | {
9 | private static readonly string Key = "12345678901234567890123456789012"; // 32 ký tự
10 |
11 | public static string Encrypt(string plainText)
12 | {
13 | using var aes = Aes.Create();
14 | aes.Key = Encoding.UTF8.GetBytes(Key);
15 | aes.GenerateIV();
16 | var iv = aes.IV;
17 | using var encryptor = aes.CreateEncryptor(aes.Key, iv);
18 | var plainBytes = Encoding.UTF8.GetBytes(plainText);
19 | var encrypted = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
20 | var result = new byte[iv.Length + encrypted.Length];
21 | Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
22 | Buffer.BlockCopy(encrypted, 0, result, iv.Length, encrypted.Length);
23 | return Convert.ToBase64String(result);
24 | }
25 |
26 | public static string Decrypt(string cipherText)
27 | {
28 | var fullCipher = Convert.FromBase64String(cipherText);
29 | using var aes = Aes.Create();
30 | aes.Key = Encoding.UTF8.GetBytes(Key);
31 | var iv = new byte[16];
32 | Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
33 | aes.IV = iv;
34 | using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
35 | var cipher = new byte[fullCipher.Length - iv.Length];
36 | Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length);
37 | var decrypted = decryptor.TransformFinalBlock(cipher, 0, cipher.Length);
38 | return Encoding.UTF8.GetString(decrypted);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/HotelManagementAPI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | False
8 | False
9 |
10 |
11 | true
12 | 1591
13 |
14 |
15 | HotelManagementAPI
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | runtime; build; native; contentfiles; analyzers; buildtransitive
37 | all
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/HotelManagementAPI.http:
--------------------------------------------------------------------------------
1 | @HotelManagementAPI_HostAddress = http://localhost:5170
2 |
3 | GET {{HotelManagementAPI_HostAddress}}/weatherforecast/
4 | Accept: application/json
5 |
6 | ###
7 |
--------------------------------------------------------------------------------
/HotelManagementAPI.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 17
3 | VisualStudioVersion = 17.5.2.0
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotelManagementAPI", "HotelManagementAPI.csproj", "{3442737D-C627-B7C8-706D-0CBB731A2A87}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {3442737D-C627-B7C8-706D-0CBB731A2A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {3442737D-C627-B7C8-706D-0CBB731A2A87}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {3442737D-C627-B7C8-706D-0CBB731A2A87}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {3442737D-C627-B7C8-706D-0CBB731A2A87}.Release|Any CPU.Build.0 = Release|Any CPU
17 | EndGlobalSection
18 | GlobalSection(SolutionProperties) = preSolution
19 | HideSolutionNode = FALSE
20 | EndGlobalSection
21 | GlobalSection(ExtensibilityGlobals) = postSolution
22 | SolutionGuid = {BAD32C3D-E217-4C25-9EDC-CD32340A7CD8}
23 | EndGlobalSection
24 | EndGlobal
25 |
--------------------------------------------------------------------------------
/Models/BaiViet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class BaiViet
7 | {
8 | public string MaBaiViet { get; set; } = null!;
9 |
10 | public string MaNguoiDung { get; set; } = null!;
11 |
12 | public string TieuDe { get; set; } = null!;
13 |
14 | public string NoiDung { get; set; } = null!;
15 |
16 | public DateTime? NgayDang { get; set; }
17 |
18 | public string? HinhAnhUrl { get; set; }
19 |
20 | public string? TrangThai { get; set; }
21 |
22 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
23 | }
24 |
--------------------------------------------------------------------------------
/Models/BaoCao.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class BaoCao
7 | {
8 | public string MaBaoCao { get; set; } = null!;
9 |
10 | public string LoaiBaoCao { get; set; } = null!;
11 |
12 | public DateTime? ThoiGian { get; set; }
13 |
14 | public string? NoiDung { get; set; }
15 |
16 | public virtual ICollection ChiTietBaoCaos { get; set; } = new List();
17 | }
18 |
--------------------------------------------------------------------------------
/Models/ChiTietBaoCao.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class ChiTietBaoCao
7 | {
8 | public string MaChiTiet { get; set; } = null!;
9 |
10 | public string MaBaoCao { get; set; } = null!;
11 |
12 | public string NoiDungChiTiet { get; set; } = null!;
13 |
14 | public decimal GiaTri { get; set; }
15 |
16 | public virtual BaoCao MaBaoCaoNavigation { get; set; } = null!;
17 | }
18 |
--------------------------------------------------------------------------------
/Models/ChiTietHoaDon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class ChiTietHoaDon
7 | {
8 | public string MaChiTiet { get; set; } = null!;
9 |
10 | public string MaHoaDon { get; set; } = null!;
11 |
12 | public string LoaiKhoanMuc { get; set; } = null!;
13 |
14 | public string MaKhoanMuc { get; set; } = null!;
15 |
16 | public int SoLuong { get; set; }
17 |
18 | public decimal ThanhTien { get; set; }
19 |
20 | public virtual HoaDon MaHoaDonNavigation { get; set; } = null!;
21 | }
22 |
--------------------------------------------------------------------------------
/Models/DatDichVu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class DatDichVu
7 | {
8 | public string MaDatDichVu { get; set; } = null!;
9 |
10 | public string MaDatPhong { get; set; } = null!;
11 |
12 | public string MaDichVu { get; set; } = null!;
13 |
14 | public int SoLuong { get; set; }
15 |
16 | public virtual DatPhong MaDatPhongNavigation { get; set; } = null!;
17 |
18 | public virtual DichVu MaDichVuNavigation { get; set; } = null!;
19 | }
20 |
--------------------------------------------------------------------------------
/Models/DatPhong.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class DatPhong
7 | {
8 | public string MaDatPhong { get; set; } = null!;
9 |
10 | public string MaNguoiDung { get; set; } = null!;
11 |
12 | public string MaPhong { get; set; } = null!;
13 |
14 | public DateTime? NgayDat { get; set; }
15 |
16 | public DateTime? NgayCheckIn { get; set; }
17 |
18 | public DateTime? NgayCheckOut { get; set; }
19 |
20 | public byte TinhTrangDatPhong { get; set; }
21 |
22 | public virtual ICollection DatDichVus { get; set; } = new List();
23 |
24 | public virtual ICollection HoaDons { get; set; } = new List();
25 |
26 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
27 |
28 | public virtual Phong MaPhongNavigation { get; set; } = null!;
29 | }
30 |
--------------------------------------------------------------------------------
/Models/DichVu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class DichVu
7 | {
8 | public string MaDichVu { get; set; } = null!;
9 |
10 | public string TenDichVu { get; set; } = null!;
11 |
12 | public decimal DonGia { get; set; }
13 |
14 | public string? MoTaDichVu { get; set; }
15 |
16 | public string HinhAnhDichVu { get; set; } = null!;
17 |
18 | public int SoLuong { get; set; }
19 |
20 | public byte TrangThai { get; set; }
21 |
22 | public string LoaiDichVu { get; set; } = null!;
23 |
24 | public string DonViTinh { get; set; } = null!;
25 |
26 | public virtual ICollection DatDichVus { get; set; } = new List();
27 | }
28 |
--------------------------------------------------------------------------------
/Models/Feedback.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class Feedback
7 | {
8 | public string MaFeedback { get; set; } = null!;
9 |
10 | public string MaPhong { get; set; } = null!;
11 |
12 | public string MaNguoiDung { get; set; } = null!;
13 |
14 | public int SoSao { get; set; }
15 |
16 | public string? BinhLuan { get; set; }
17 |
18 | public DateTime? NgayFeedback { get; set; }
19 |
20 | public string PhanLoai { get; set; } = null!;
21 |
22 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
23 |
24 | public virtual Phong MaPhongNavigation { get; set; } = null!;
25 | }
26 |
--------------------------------------------------------------------------------
/Models/GiamGium.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class GiamGium
7 | {
8 | public string MaGiamGia { get; set; } = null!;
9 |
10 | public string TenGiamGia { get; set; } = null!;
11 |
12 | public string? LoaiGiamGia { get; set; }
13 |
14 | public decimal GiaTriGiam { get; set; }
15 |
16 | public DateTime NgayBatDau { get; set; }
17 |
18 | public DateTime NgayKetThuc { get; set; }
19 |
20 | public string? MoTa { get; set; }
21 |
22 | public virtual ICollection MaPhongs { get; set; } = new List();
23 | }
24 |
--------------------------------------------------------------------------------
/Models/HoaDon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class HoaDon
7 | {
8 | public string MaHoaDon { get; set; } = null!;
9 |
10 | public string MaNguoiDung { get; set; } = null!;
11 |
12 | public string MaDatPhong { get; set; } = null!;
13 |
14 | public decimal TongTien { get; set; }
15 |
16 | public DateTime? NgayTaoHoaDon { get; set; }
17 |
18 | public DateTime? NgayThanhToan { get; set; }
19 |
20 | public byte TinhTrangHoaDon { get; set; }
21 |
22 | public virtual ICollection ChiTietHoaDons { get; set; } = new List();
23 |
24 | public virtual DatPhong MaDatPhongNavigation { get; set; } = null!;
25 |
26 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
27 |
28 | public virtual ICollection ThanhToans { get; set; } = new List();
29 | }
30 |
--------------------------------------------------------------------------------
/Models/Hotelnhom2Context.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Microsoft.EntityFrameworkCore;
4 |
5 | namespace HotelManagementAPI.Models;
6 |
7 | public partial class Hotelnhom2Context : DbContext
8 | {
9 | public Hotelnhom2Context()
10 | {
11 | }
12 |
13 | public Hotelnhom2Context(DbContextOptions options)
14 | : base(options)
15 | {
16 | }
17 |
18 | public virtual DbSet BaoCaos { get; set; }
19 |
20 | public virtual DbSet ChiTietBaoCaos { get; set; }
21 |
22 | public virtual DbSet ChiTietHoaDons { get; set; }
23 |
24 | public virtual DbSet DatDichVus { get; set; }
25 |
26 | public virtual DbSet DatPhongs { get; set; }
27 |
28 | public virtual DbSet DichVus { get; set; }
29 |
30 | public virtual DbSet Feedbacks { get; set; }
31 |
32 | public virtual DbSet GiamGia { get; set; }
33 |
34 | public virtual DbSet HoaDons { get; set; }
35 |
36 | public virtual DbSet LichSuGiaoDiches { get; set; }
37 |
38 | public virtual DbSet NguoiDungs { get; set; }
39 |
40 |
41 |
42 | public virtual DbSet Phongs { get; set; }
43 |
44 | public virtual DbSet PhongAnhs { get; set; }
45 |
46 | public virtual DbSet ThanhToans { get; set; }
47 |
48 | public virtual DbSet TienNghis { get; set; }
49 |
50 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
51 | #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
52 | => optionsBuilder.UseSqlServer("Server=118.69.126.49;Database=data_QLKS_115_Nhom2;User Id=user_115_nhom2;Password=123456789;TrustServerCertificate=True;");
53 |
54 | protected override void OnModelCreating(ModelBuilder modelBuilder)
55 | {
56 | modelBuilder.Entity(entity =>
57 | {
58 | entity.HasKey(e => e.MaBaoCao).HasName("PK__BaoCao__25A9188CFE4D38CB");
59 |
60 | entity.Property(e => e.ThoiGian).HasDefaultValueSql("(getdate())");
61 | });
62 |
63 | modelBuilder.Entity(entity =>
64 | {
65 | entity.HasKey(e => e.MaChiTiet).HasName("PK__ChiTietB__CDF0A114D9662651");
66 |
67 | entity.HasOne(d => d.MaBaoCaoNavigation).WithMany(p => p.ChiTietBaoCaos)
68 | .OnDelete(DeleteBehavior.ClientSetNull)
69 | .HasConstraintName("FK__ChiTietBa__MaBao__1F198FD4");
70 | });
71 |
72 | modelBuilder.Entity(entity =>
73 | {
74 | entity.HasKey(e => e.MaChiTiet).HasName("PK__ChiTietH__CDF0A114167F4AE2");
75 |
76 | entity.Property(e => e.SoLuong).HasDefaultValue(1);
77 |
78 | entity.HasOne(d => d.MaHoaDonNavigation).WithMany(p => p.ChiTietHoaDons)
79 | .OnDelete(DeleteBehavior.ClientSetNull)
80 | .HasConstraintName("FK__ChiTietHo__MaHoa__07420643");
81 | });
82 |
83 | modelBuilder.Entity(entity =>
84 | {
85 | entity.HasKey(e => e.MaDatDichVu).HasName("PK__DatDichV__35B4F60ADECC2C14");
86 |
87 | entity.Property(e => e.SoLuong).HasDefaultValue(1);
88 |
89 | entity.HasOne(d => d.MaDatPhongNavigation).WithMany(p => p.DatDichVus)
90 | .OnDelete(DeleteBehavior.ClientSetNull)
91 | .HasConstraintName("FK__DatDichVu__MaDat__01892CED");
92 |
93 | entity.HasOne(d => d.MaDichVuNavigation).WithMany(p => p.DatDichVus)
94 | .OnDelete(DeleteBehavior.ClientSetNull)
95 | .HasConstraintName("FK__DatDichVu__MaDic__027D5126");
96 |
97 |
98 | });
99 |
100 | modelBuilder.Entity(entity =>
101 | {
102 | entity.HasKey(e => e.MaDatPhong).HasName("PK__DatPhong__6344ADEAE1DFB5FB");
103 |
104 | entity.Property(e => e.NgayDat).HasDefaultValueSql("(getdate())");
105 |
106 | entity.HasOne(d => d.MaNguoiDungNavigation).WithMany(p => p.DatPhongs)
107 | .OnDelete(DeleteBehavior.ClientSetNull)
108 | .HasConstraintName("FK__DatPhong__MaNguo__7152C524");
109 |
110 | entity.HasOne(d => d.MaPhongNavigation).WithMany(p => p.DatPhongs)
111 | .OnDelete(DeleteBehavior.ClientSetNull)
112 | .HasConstraintName("FK__DatPhong__MaPhon__7246E95D");
113 | });
114 |
115 | modelBuilder.Entity(entity =>
116 | {
117 | entity.HasKey(e => e.MaDichVu).HasName("PK__DichVu__C0E6DE8F7A8A9E20");
118 |
119 | entity.Property(e => e.DonViTinh).HasDefaultValue("1 l?n");
120 | entity.Property(e => e.LoaiDichVu).HasDefaultValue("Khac");
121 | entity.Property(e => e.TrangThai).HasDefaultValue((byte)1);
122 | });
123 |
124 | modelBuilder.Entity(entity =>
125 | {
126 | entity.HasKey(e => e.MaFeedback).HasName("PK__Feedback__63042CF68D0745C0");
127 |
128 | entity.Property(e => e.NgayFeedback).HasDefaultValueSql("(getdate())");
129 |
130 | entity.Property(e => e.PhanLoai)
131 | .HasMaxLength(10)
132 | .IsRequired()
133 | .HasColumnName("PhanLoai");
134 |
135 | entity.HasOne(d => d.MaNguoiDungNavigation)
136 | .WithMany(p => p.Feedbacks)
137 | .OnDelete(DeleteBehavior.ClientSetNull)
138 | .HasConstraintName("FK__Feedback__MaNguo__11BF94B6");
139 |
140 | entity.HasOne(d => d.MaPhongNavigation)
141 | .WithMany(p => p.Feedbacks)
142 | .OnDelete(DeleteBehavior.ClientSetNull)
143 | .HasConstraintName("FK__Feedback__MaPhon__10CB707D");
144 | });
145 |
146 | modelBuilder.Entity(entity =>
147 | {
148 | entity.HasKey(e => e.MaGiamGia).HasName("PK__GiamGia__EF9458E4A95B060A");
149 | });
150 |
151 | modelBuilder.Entity(entity =>
152 | {
153 | entity.HasKey(e => e.MaHoaDon).HasName("PK__HoaDon__835ED13B75D2C79D");
154 |
155 | entity.Property(e => e.NgayTaoHoaDon).HasDefaultValueSql("(getdate())");
156 |
157 | entity.HasOne(d => d.MaDatPhongNavigation).WithMany(p => p.HoaDons)
158 | .OnDelete(DeleteBehavior.ClientSetNull)
159 | .HasConstraintName("FK__HoaDon__MaDatPho__7DB89C09");
160 |
161 | entity.HasOne(d => d.MaNguoiDungNavigation).WithMany(p => p.HoaDons)
162 | .OnDelete(DeleteBehavior.ClientSetNull)
163 | .HasConstraintName("FK__HoaDon__MaNguoiD__7CC477D0");
164 | });
165 |
166 | modelBuilder.Entity(entity =>
167 | {
168 | entity.HasKey(e => e.MaGiaoDich).HasName("PK__LichSuGi__0A2A24EBEB8C6320");
169 |
170 | entity.Property(e => e.ThoiGianGiaoDich).HasDefaultValueSql("(getdate())");
171 |
172 | entity.HasOne(d => d.MaNguoiDungNavigation).WithMany(p => p.LichSuGiaoDiches)
173 | .OnDelete(DeleteBehavior.ClientSetNull)
174 | .HasConstraintName("FK__LichSuGia__MaNgu__1960B67E");
175 | });
176 |
177 | modelBuilder.Entity(entity =>
178 | {
179 | entity.HasKey(e => e.MaNguoiDung).HasName("PK__NguoiDun__C539D76271D1E9B0");
180 |
181 | entity.Property(e => e.HinhAnhUrl).HasDefaultValue("https://i.pinimg.com/736x/20/ef/6b/20ef6b554ea249790281e6677abc4160.jpg");
182 | entity.Property(e => e.NgayTao).HasDefaultValueSql("(getdate())");
183 | entity.Property(e => e.Vaitro).HasDefaultValue("KhachHang");
184 | });
185 |
186 |
187 | modelBuilder.Entity(entity =>
188 | {
189 | entity.HasKey(e => e.MaPhong).HasName("PK__Phong__20BD5E5B3E27A9BD");
190 |
191 | entity.Property(e => e.DonViTinh).HasDefaultValue("1 dêm");
192 | entity.Property(e => e.SoGiuong).HasDefaultValue(1);
193 | entity.Property(e => e.SoLuongPhong).HasDefaultValue(1);
194 | entity.Property(e => e.SucChua).HasDefaultValue(2);
195 |
196 | entity.HasMany(d => d.MaGiamGia).WithMany(p => p.MaPhongs)
197 | .UsingEntity>(
198 | "PhongGiamGium",
199 | r => r.HasOne().WithMany()
200 | .HasForeignKey("MaGiamGia")
201 | .OnDelete(DeleteBehavior.ClientSetNull)
202 | .HasConstraintName("FK__Phong_Gia__MaGia__64ECEE3F"),
203 | l => l.HasOne().WithMany()
204 | .HasForeignKey("MaPhong")
205 | .OnDelete(DeleteBehavior.ClientSetNull)
206 | .HasConstraintName("FK__Phong_Gia__MaPho__63F8CA06"),
207 | j =>
208 | {
209 | j.HasKey("MaPhong", "MaGiamGia").HasName("PK__Phong_Gi__7E441BD5C7C12056");
210 | j.ToTable("Phong_GiamGia");
211 | j.IndexerProperty("MaPhong").HasMaxLength(6);
212 | j.IndexerProperty("MaGiamGia").HasMaxLength(6);
213 | });
214 |
215 | entity.HasMany(d => d.MaTienNghis).WithMany(p => p.MaPhongs)
216 | .UsingEntity>(
217 | "PhongTienNghi",
218 | r => r.HasOne().WithMany()
219 | .HasForeignKey("MaTienNghi")
220 | .HasConstraintName("FK__Phong_Tie__MaTie__5E3FF0B0"),
221 | l => l.HasOne().WithMany()
222 | .HasForeignKey("MaPhong")
223 | .HasConstraintName("FK__Phong_Tie__MaPho__5D4BCC77"),
224 | j =>
225 | {
226 | j.HasKey("MaPhong", "MaTienNghi").HasName("PK__Phong_Ti__EE6AE6AF744EE6E8");
227 | j.ToTable("Phong_TienNghi");
228 | j.IndexerProperty("MaPhong").HasMaxLength(6);
229 | j.IndexerProperty("MaTienNghi").HasMaxLength(6);
230 | });
231 | });
232 |
233 | modelBuilder.Entity(entity =>
234 | {
235 | entity.HasKey(e => e.MaAnh).HasName("PK__PhongAnh__356240DFA45F6A84");
236 |
237 | entity.HasOne(d => d.MaPhongNavigation).WithMany(p => p.PhongAnhs).HasConstraintName("FK__PhongAnh__MaPhon__5887175A");
238 | });
239 |
240 | modelBuilder.Entity(entity =>
241 | {
242 | entity.HasKey(e => e.MaThanhToan).HasName("PK__ThanhToa__D4B2584443D246C5");
243 |
244 | entity.Property(e => e.NgayThanhToan).HasDefaultValueSql("(getdate())");
245 |
246 | entity.HasOne(d => d.MaHoaDonNavigation).WithMany(p => p.ThanhToans)
247 | .OnDelete(DeleteBehavior.ClientSetNull)
248 | .HasConstraintName("FK__ThanhToan__MaHoa__0C06BB60");
249 | });
250 |
251 | modelBuilder.Entity(entity =>
252 | {
253 | entity.HasKey(e => e.MaTienNghi).HasName("PK__TienNghi__ED7B8F4D1BA362DD");
254 | });
255 |
256 | OnModelCreatingPartial(modelBuilder);
257 | }
258 |
259 | partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
260 | }
261 |
--------------------------------------------------------------------------------
/Models/LichSuGiaoDich.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class LichSuGiaoDich
7 | {
8 | public string MaGiaoDich { get; set; } = null!;
9 |
10 | public string MaNguoiDung { get; set; } = null!;
11 |
12 | public string LoaiGiaoDich { get; set; } = null!;
13 |
14 | public DateTime? ThoiGianGiaoDich { get; set; }
15 |
16 | public string? MoTa { get; set; }
17 |
18 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
19 | }
20 |
--------------------------------------------------------------------------------
/Models/NguoiDung.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class NguoiDung
7 | {
8 | public string MaNguoiDung { get; set; } = null!;
9 |
10 | public string? Vaitro { get; set; }
11 |
12 | public string Email { get; set; } = null!;
13 |
14 | public string? TenTaiKhoan { get; set; }
15 |
16 | public string? MatKhau { get; set; }
17 |
18 | public string? HoTen { get; set; }
19 |
20 | public string? CanCuocCongDan { get; set; }
21 |
22 | public string? SoDienThoai { get; set; }
23 |
24 | public string? DiaChi { get; set; }
25 |
26 | public DateTime? NgaySinh { get; set; }
27 |
28 | public string? GioiTinh { get; set; }
29 |
30 | public string HinhAnhUrl { get; set; } = null!;
31 |
32 | public DateTime? NgayTao { get; set; }
33 |
34 | public virtual ICollection BaiViets { get; set; } = new List();
35 |
36 | public virtual ICollection DatPhongs { get; set; } = new List();
37 |
38 | public virtual ICollection Feedbacks { get; set; } = new List();
39 |
40 | public virtual ICollection HoaDons { get; set; } = new List();
41 |
42 | public virtual ICollection LichSuGiaoDiches { get; set; } = new List();
43 |
44 | public virtual ICollection PhongYeuThiches { get; set; } = new List();
45 | }
46 |
--------------------------------------------------------------------------------
/Models/NoiQuy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class NoiQuy
7 | {
8 | public int Id { get; set; }
9 |
10 | public int SoThuTu { get; set; }
11 |
12 | public string TieuDe { get; set; } = null!;
13 |
14 | public string NoiDung { get; set; } = null!;
15 |
16 | public string? HinhAnh { get; set; }
17 | }
18 |
--------------------------------------------------------------------------------
/Models/PaymentRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace HotelManagementAPI.Models
4 | {
5 | public class PaymentRequest
6 | {
7 | public string PaymentId { get; set; }
8 | public double Money { get; set; }
9 | public string Description { get; set; }
10 |
11 | // Thêm các trường mở rộng cho VNPAY
12 | public string IpAddress { get; set; }
13 | public string BankCode { get; set; } // Có thể dùng enum nếu muốn
14 | public DateTime CreatedDate { get; set; }
15 | public DateTime ExpireDate { get; set; } // <-- thêm cái này
16 | public string Currency { get; set; }
17 | public string Language { get; set; }
18 |
19 |
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Models/PaymentResponse.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.Models
2 | {
3 | public class VnpayCallbackRequest
4 | {
5 | public string Vnp_TmnCode { get; set; }
6 | public string Vnp_Amount { get; set; }
7 | public string Vnp_OrderInfo { get; set; }
8 | public string Vnp_TxnRef { get; set; }
9 | public string Vnp_ResponseCode { get; set; }
10 | public string Vnp_SecureHash { get; set; }
11 | // Add other fields as needed
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Models/PaymentResult.cs:
--------------------------------------------------------------------------------
1 | namespace HotelManagementAPI.Models
2 | {
3 | public class PaymentResult
4 | {
5 | public bool IsSuccess { get; set; }
6 | public string Message { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Models/Phong.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class Phong
7 | {
8 | public string MaPhong { get; set; } = null!;
9 |
10 | public string LoaiPhong { get; set; } = null!;
11 |
12 | public decimal GiaPhong { get; set; }
13 |
14 | public byte TinhTrang { get; set; }
15 |
16 | public int SoLuongPhong { get; set; }
17 |
18 | public int Tang { get; set; }
19 |
20 | public string KieuGiuong { get; set; } = null!;
21 |
22 | public string? MoTa { get; set; }
23 |
24 | public string UrlAnhChinh { get; set; } = null!;
25 |
26 | public int SucChua { get; set; }
27 |
28 | public int SoGiuong { get; set; }
29 |
30 | public string DonViTinh { get; set; } = null!;
31 |
32 | public decimal SoSaoTrungBinh { get; set; }
33 |
34 | public virtual ICollection DatPhongs { get; set; } = new List();
35 |
36 | public virtual ICollection Feedbacks { get; set; } = new List();
37 |
38 | public virtual ICollection PhongAnhs { get; set; } = new List();
39 |
40 | public virtual ICollection PhongYeuThiches { get; set; } = new List();
41 |
42 | public virtual ICollection MaGiamGia { get; set; } = new List();
43 |
44 | public virtual ICollection MaTienNghis { get; set; } = new List();
45 | }
46 |
--------------------------------------------------------------------------------
/Models/PhongAnh.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class PhongAnh
7 | {
8 | public string MaAnh { get; set; } = null!;
9 |
10 | public string MaPhong { get; set; } = null!;
11 |
12 | public string UrlAnh { get; set; } = null!;
13 |
14 | public virtual Phong MaPhongNavigation { get; set; } = null!;
15 | }
16 |
--------------------------------------------------------------------------------
/Models/PhongYeuThich.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class PhongYeuThich
7 | {
8 | public int Id { get; set; }
9 |
10 | public string MaPhong { get; set; } = null!;
11 |
12 | public string MaNguoiDung { get; set; } = null!;
13 |
14 | public DateTime? NgayYeuThich { get; set; }
15 |
16 | public virtual NguoiDung MaNguoiDungNavigation { get; set; } = null!;
17 |
18 | public virtual Phong MaPhongNavigation { get; set; } = null!;
19 | }
20 |
--------------------------------------------------------------------------------
/Models/ThanhToan.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class ThanhToan
7 | {
8 | public string MaThanhToan { get; set; } = null!;
9 |
10 | public string MaHoaDon { get; set; } = null!;
11 |
12 | public decimal SoTienThanhToan { get; set; }
13 |
14 | public DateTime? NgayThanhToan { get; set; }
15 |
16 | public string PhuongThucThanhToan { get; set; } = null!;
17 |
18 | public string TinhTrangThanhToan { get; set; } = null!;
19 |
20 | public virtual HoaDon MaHoaDonNavigation { get; set; } = null!;
21 | }
22 |
--------------------------------------------------------------------------------
/Models/TienNghi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Models;
5 |
6 | public partial class TienNghi
7 | {
8 | public string MaTienNghi { get; set; } = null!;
9 |
10 | public string TenTienNghi { get; set; } = null!;
11 |
12 | public string? MoTa { get; set; }
13 |
14 | public virtual ICollection MaPhongs { get; set; } = new List();
15 | }
16 |
--------------------------------------------------------------------------------
/Models/VnpayCallbackRequest.cs:
--------------------------------------------------------------------------------
1 | namespace YourNamespace.Models
2 | {
3 | public class VnpayCallbackRequest
4 | {
5 | public string Vnp_TmnCode { get; set; }
6 | public string Vnp_Amount { get; set; }
7 | public string Vnp_OrderInfo { get; set; }
8 | public string Vnp_TxnRef { get; set; }
9 | public string Vnp_ResponseCode { get; set; }
10 | public string Vnp_SecureHash { get; set; }
11 | // Add other fields as needed
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Reflection;
3 | using Microsoft.Data.SqlClient;
4 | using Microsoft.AspNetCore.Authentication.JwtBearer;
5 | using Microsoft.IdentityModel.Tokens;
6 | using System.Text;
7 | using Microsoft.OpenApi.Models;
8 | using FluentValidation;
9 | using FluentValidation.AspNetCore;
10 | using HotelManagementAPI.Services;
11 | var builder = WebApplication.CreateBuilder(args);
12 |
13 | // Cấu hình chuỗi kết nối
14 | var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
15 |
16 | // Đăng ký IDbConnection với DI
17 | builder.Services.AddScoped(sp => new SqlConnection(connectionString));
18 |
19 | builder.Logging.AddConsole();
20 |
21 | // Cấu hình CORS
22 | builder.Services.AddCors(options =>
23 | {
24 | options.AddPolicy("AllowAllOrigins", policy =>
25 | {
26 |
27 | policy.AllowAnyOrigin() // Cho phép mọi domain
28 | .AllowAnyHeader() // Cho phép mọi header
29 | .AllowAnyMethod(); // Cho phép mọi HTTP method (GET, POST, PUT, DELETE...)
30 |
31 |
32 | });
33 | });
34 |
35 | builder.Services.AddHttpClient();
36 |
37 | // Đọc cấu hình SentimentModelPath từ appsettings.json
38 | var sentimentModelPath = builder.Configuration["SentimentModelPath"];
39 | builder.Services.AddSingleton(new SentimentModelConfig { ModelPath = sentimentModelPath });
40 |
41 | // Thêm Swagger và các dịch vụ khác
42 | builder.Services.AddEndpointsApiExplorer();
43 | builder.Services.AddSwaggerGen(options =>
44 | {
45 | var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
46 | var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
47 | options.IncludeXmlComments(xmlPath);
48 | options.UseInlineDefinitionsForEnums(); // ✅ Hiển thị enum trong Swagger
49 | options.EnableAnnotations(); // ✅ Bật hỗ trợ ghi chú trong Swagger
50 | options.DescribeAllParametersInCamelCase(); // ✅ Hiển thị tham số theo camelCase
51 | options.CustomSchemaIds(type => type.FullName); // Sử dụng tên đầy đủ của lớp làm ID schema
52 |
53 |
54 | options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
55 | {
56 | Name = "Authorization",
57 | Type = SecuritySchemeType.ApiKey,
58 | Scheme = "Bearer",
59 | BearerFormat = "JWT",
60 | In = ParameterLocation.Header,
61 | Description = "Nhập 'Bearer' [space] và sau đó là token của bạn.",
62 | });
63 |
64 | options.AddSecurityRequirement(new OpenApiSecurityRequirement
65 | {
66 | {
67 | new OpenApiSecurityScheme
68 | {
69 | Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
70 | },
71 | new string[] {}
72 | }
73 | });
74 |
75 |
76 | // Thêm thông tin mô tả API
77 | options.SwaggerDoc("v1", new OpenApiInfo
78 | {
79 | Title = "🏨 Hệ thống Quản lý Khách sạn",
80 | Version = "v1",
81 | Description = @"
82 | 📘 **Đề tài:** Xây dựng hệ thống quản lý khách sạn.
83 |
84 | 🔧 **Công nghệ sử dụng:**
85 | - ASP.NET Core Web API
86 | - SQL Server
87 | - Entity Framework/Dapper
88 | - JWT Authentication
89 | - Swagger UI
90 | - (Tuỳ chọn: React/Vue cho frontend, nếu có)
91 |
92 | 🎯 **Chức năng chính:**
93 | - Đăng ký người dùng bao gồm admin, nhân viên, khách hàng
94 | + admin*(quản trị viên) có quyền thêm sửa xóa phòng ,xem trạng thái phòng ,thêm tiện nghi
95 | + nhân viên có quyền sửa phòng
96 | + khách hàng có quyền đặt phòng
97 |
98 | - Đặt phòng, thanh toán, và xuất hoá đơn, và xem lịch sử giao dịch
99 | - Quản lý dịch vụ đi kèm
100 | - Xem phản hồi từ khách hàng (feedback)
101 | - Phân quyền người dùng (admin, nhân viên, khách hàng)
102 |
103 | 🔗 **GitHub Repository:** [https://github.com/Persinus/HotelManagementAPI](https://github.com/Persinus/HotelManagementAPI)
104 | "
105 | });
106 | });
107 | builder.Services.AddControllers();
108 | builder.Services.AddFluentValidationAutoValidation();
109 | builder.Services.AddFluentValidationClientsideAdapters();
110 | builder.Services.AddValidatorsFromAssemblyContaining();
111 |
112 | // Đăng ký IMemoryCache
113 | builder.Services.AddMemoryCache();
114 | // Cấu hình Cloudinary
115 | builder.Services.Configure(
116 | builder.Configuration.GetSection("CloudinarySettings"));
117 | // Cấu hình JWT
118 | builder.Services.AddAuthentication("Bearer")
119 | .AddJwtBearer(options =>
120 | {
121 |
122 |
123 | options.TokenValidationParameters = new TokenValidationParameters
124 | {
125 | ValidateIssuer = true, // Kiểm tra Issuer
126 | ValidateAudience = true, // Kiểm tra Audience
127 | ValidateLifetime = true, // Kiểm tra thời gian sống của token
128 | ValidateIssuerSigningKey = true, // Kiểm tra chữ ký của token
129 | ValidIssuer = "your-issuer", // Thay thế với Issuer của bạn
130 | ValidAudience = "your-audience", // Thay thế với Audience của bạn
131 | IssuerSigningKey = new SymmetricSecurityKey(
132 | Encoding.UTF8.GetBytes("your_super_secret_key_1234567890") // Khóa bí mật của bạn
133 | ),
134 | NameClaimType = "sub", // Chỉ định claim `sub` làm `Name`
135 | RoleClaimType = "Vaitro" // Chỉ định claim `Vaitro` làm `Role`
136 | };
137 |
138 | options.Events = new JwtBearerEvents
139 | {
140 | OnChallenge = context =>
141 | {
142 | if (!context.Request.Headers.ContainsKey("Authorization"))
143 | {
144 | context.Response.StatusCode = StatusCodes.Status401Unauthorized;
145 | context.Response.ContentType = "application/json";
146 | return context.Response.WriteAsync("{\"error\":\"Unauthorized. Authorization header is missing.\"}");
147 | }
148 |
149 | context.Response.StatusCode = StatusCodes.Status401Unauthorized;
150 | context.Response.ContentType = "application/json";
151 | return context.Response.WriteAsync("{\"error\":\"Unauthorized. Token is missing or invalid.\"}");
152 | },
153 | OnAuthenticationFailed = context =>
154 | {
155 | context.Response.StatusCode = StatusCodes.Status401Unauthorized;
156 | context.Response.ContentType = "application/json";
157 | return context.Response.WriteAsync("{\"error\":\"Authentication failed. Invalid token.\"}");
158 | }
159 | };
160 |
161 | });
162 |
163 |
164 | builder.Services.AddAuthorization(options =>
165 | {
166 | options.AddPolicy("QuanTriVienPolicy", policy =>
167 | policy.RequireClaim("Vaitro", "QuanTriVien"));
168 |
169 | options.AddPolicy("NhanVienPolicy", policy =>
170 | policy.RequireClaim("Vaitro", "NhanVien", "QuanTriVien"));
171 |
172 | options.AddPolicy("KhachHangPolicy", policy =>
173 | policy.RequireClaim("Vaitro", "KhachHang","NhanVien", "QuanTriVien"));
174 | });
175 |
176 |
177 | builder.Services.AddSingleton();
178 |
179 | var app = builder.Build();
180 |
181 | // Cấu hình Swagger
182 | var enableSwagger = builder.Configuration.GetValue("Swagger:Enable");
183 | if (enableSwagger || app.Environment.IsDevelopment())
184 | {
185 | app.UseSwagger();
186 | app.UseSwaggerUI(c =>
187 | {
188 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "Hotel Management API V1");
189 | c.RoutePrefix = string.Empty;
190 |
191 |
192 |
193 | c.DocumentTitle = "Hotel Management API Documentation";
194 | c.DisplayRequestDuration();
195 | c.ConfigObject.PersistAuthorization = true;
196 | c.ConfigObject.ShowExtensions = true;
197 | c.ConfigObject.ShowCommonExtensions = true;
198 | c.ConfigObject.DisplayOperationId = true;
199 | c.ConfigObject.DisplayRequestDuration = true;
200 |
201 | c.ConfigObject.DeepLinking = true;
202 |
203 |
204 |
205 |
206 |
207 | });
208 | }
209 |
210 | app.UseCors("AllowAllOrigins"); // Áp dụng chính sách CORS đã cấu hình
211 |
212 | // Thêm middleware xác thực và phân quyền
213 | app.UseAuthentication();
214 | app.UseMiddleware();
215 | app.UseAuthorization();
216 |
217 | // Định tuyến các controller
218 | app.MapControllers();
219 |
220 | // Cấu hình chuyển hướng HTTPS
221 | app.UseHttpsRedirection();
222 |
223 | app.Run();
224 |
225 | // Lớp cấu hình cho SentimentModelPath
226 | public class SentimentModelConfig
227 | {
228 | public string ModelPath { get; set; }
229 | }
230 |
--------------------------------------------------------------------------------
/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "http": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "launchBrowser": false,
8 | "applicationUrl": "http://localhost:5170",
9 | "environmentVariables": {
10 | "ASPNETCORE_ENVIRONMENT": "Development"
11 | }
12 | },
13 | "https": {
14 | "commandName": "Project",
15 | "dotnetRunMessages": true,
16 | "launchBrowser": false,
17 | "applicationUrl": "https://localhost:7272;http://localhost:5170",
18 | "environmentVariables": {
19 | "ASPNETCORE_ENVIRONMENT": "Development"
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tutorial: HotelManagementAPI
2 |
3 | This project is a **Hotel Management API** built using ASP.NET Core.
4 | It acts as the backend system for a hotel, allowing various users (**guests, staff, administrators**) to interact with hotel operations.
5 | Key functions include **managing rooms and services**, handling **user authentication and authorization**, facilitating **room booking and payments**, and providing features for **reporting and feedback**.
6 |
7 |
8 | ## Visual Overview
9 |
10 | ```mermaid
11 | flowchart TD
12 | A0["API Controllers
13 | "]
14 | A1["Database Models
15 | "]
16 | A2["Data Transfer Objects (DTOs)
17 | "]
18 | A3["Database Access (Dapper)
19 | "]
20 | A4["Authentication & Authorization (JWT)
21 | "]
22 | A5["Request Middleware
23 | "]
24 | A6["Validation (FluentValidation)
25 | "]
26 | A7["Application Configuration
27 | "]
28 | A0 -- "Process" --> A2
29 | A0 -- "Utilize" --> A3
30 | A0 -- "Enforce/Use" --> A4
31 | A1 -- "Represent data for" --> A3
32 | A2 -- "Are validated by" --> A6
33 | A3 -- "Map data to" --> A1
34 | A4 -- "Implemented by" --> A5
35 | A4 -- "Uses settings from" --> A7
36 | A5 -- "Applies rules from" --> A4
37 | A6 -- "Define rules for" --> A2
38 | A7 -- "Configures" --> A3
39 | A7 -- "Provides settings to" --> A0
40 | ```
41 |
42 | ## Chapters
43 |
44 | 1. [Data Transfer Objects (DTOs)
45 | ](01_data_transfer_objects__dtos__.md)
46 | 2. [Validation (FluentValidation)
47 | ](02_validation__fluentvalidation__.md)
48 | 3. [API Controllers
49 | ](03_api_controllers_.md)
50 | 4. [Database Models
51 | ](04_database_models_.md)
52 | 5. [Database Access (Dapper)
53 | ](05_database_access__dapper__.md)
54 | 6. [Authentication & Authorization (JWT)
55 | ](06_authentication___authorization__jwt__.md)
56 | 7. [Request Middleware
57 | ](07_request_middleware_.md)
58 | 8. [Application Configuration
59 | ](08_application_configuration_.md)
60 |
61 | ---
62 |
63 | Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge).
64 |
--------------------------------------------------------------------------------
/RoleMiddleware/RoleMiddleware.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using Microsoft.AspNetCore.Authorization;
3 | using System.Linq;
4 | using System.Security.Claims;
5 | using System.Threading.Tasks;
6 | using Microsoft.Extensions.Caching.Memory;
7 |
8 | public class RoleMiddleware
9 | {
10 | private readonly RequestDelegate _next;
11 |
12 | public RoleMiddleware(RequestDelegate next)
13 | {
14 | _next = next;
15 | }
16 |
17 | public async Task InvokeAsync(HttpContext context)
18 | {
19 | // Bỏ qua kiểm tra nếu endpoint cho phép truy cập ẩn danh
20 | var endpoint = context.GetEndpoint();
21 | if (endpoint?.Metadata?.GetMetadata() != null)
22 | {
23 | await _next(context);
24 | return;
25 | }
26 |
27 | // Lấy thông tin vai trò từ token
28 | var userRole = context.User.Claims.FirstOrDefault(c => c.Type == "Vaitro")?.Value;
29 |
30 | // Kiểm tra nếu người dùng chưa đăng nhập
31 | if (string.IsNullOrEmpty(userRole))
32 | {
33 | context.Response.StatusCode = StatusCodes.Status401Unauthorized;
34 | await context.Response.WriteAsync("Bạn cần đăng nhập để truy cập tài nguyên này.");
35 | return;
36 | }
37 |
38 | // Phân quyền dựa trên đường dẫn
39 | if (context.Request.Path.StartsWithSegments("/api/quantrivien") && userRole != "QuanTriVien")
40 | {
41 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
42 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
43 | return;
44 | }
45 | else if (context.Request.Path.StartsWithSegments("/api/nhanvien") && userRole != "NhanVien" && userRole != "QuanTriVien")
46 | {
47 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
48 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
49 | return;
50 | }
51 | else if (context.Request.Path.StartsWithSegments("/api/quanlychung") && userRole != "NhanVien" && userRole != "QuanTriVien")
52 | {
53 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
54 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
55 | return;
56 | }
57 | else if (context.Request.Path.StartsWithSegments("/api/khachhang") && userRole != "KhachHang" && userRole != "NhanVien" && userRole != "QuanTriVien")
58 | {
59 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
60 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
61 | return;
62 | }
63 |
64 | // Nếu không có vấn đề gì, tiếp tục xử lý request
65 | await _next(context);
66 | }
67 | }
68 |
69 | public class TokenBlacklistMiddleware
70 | {
71 | private readonly RequestDelegate _next;
72 | private readonly IMemoryCache _cache;
73 |
74 | public TokenBlacklistMiddleware(RequestDelegate next, IMemoryCache cache)
75 | {
76 | _next = next;
77 | _cache = cache;
78 | }
79 |
80 | public async Task InvokeAsync(HttpContext context)
81 | {
82 | var token = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
83 |
84 | if (!string.IsNullOrEmpty(token) && _cache.TryGetValue(token, out _))
85 | {
86 | context.Response.StatusCode = StatusCodes.Status401Unauthorized;
87 | await context.Response.WriteAsync("Token đã bị thu hồi. Vui lòng đăng nhập lại.");
88 | return;
89 | }
90 |
91 | await _next(context);
92 | }
93 | }
94 |
95 | ///
96 | /// Provides extension methods for ClaimsPrincipal.
97 | ///
98 | public static class ClaimsPrincipalExtensions
99 | {
100 | ///
101 | /// Gets the user role from the claims.
102 | ///
103 | /// The ClaimsPrincipal instance.
104 | /// The user role as a string.
105 | public static string GetUserRole(this ClaimsPrincipal user)
106 | {
107 | // Lấy giá trị của claim "Vaitro" (vai trò người dùng)
108 | return user?.Claims.FirstOrDefault(c => c.Type == "Vaitro")?.Value;
109 | }
110 |
111 | ///
112 | /// Gets the user ID (sub) from the claims.
113 | ///
114 | /// The ClaimsPrincipal instance.
115 | /// The user ID as a string.
116 | public static string GetUserSub(this ClaimsPrincipal user)
117 | {
118 | // Lấy giá trị của claim "sub" (ID người dùng)
119 | return user?.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
120 | }
121 |
122 | ///
123 | /// Gets the user email from the claims.
124 | ///
125 | /// The ClaimsPrincipal instance.
126 | /// The user email as a string.
127 | public static string GetUserEmail(this ClaimsPrincipal user)
128 | {
129 | // Lấy giá trị của claim "email"
130 | return user?.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/SQLQuery2.sql:
--------------------------------------------------------------------------------
1 | -- Bảng NguoiDung
2 | CREATE TABLE NguoiDung (
3 | MaNguoiDung NVARCHAR(6) PRIMARY KEY, -- Mã định danh người dùng tự động tăng
4 | Vaitro NVARCHAR(6) NOT NULL DEFAULT 'KhachHang', -- Vai trò mặc định là Khách hàng
5 | Email NVARCHAR(100) UNIQUE NOT NULL, -- Email (đăng nhập)
6 | TenTaiKhoan NVARCHAR(50) NULL, -- Tên tài khoản (đăng nhập, có thể NULL nếu dùng Google/Facebook)
7 | MatKhau NVARCHAR(255) NULL, -- Mật khẩu (NULL nếu dùng Google/Facebook)
8 | HoTen NVARCHAR(50) NULL, -- Họ và tên
9 | CanCuocCongDan INT UNIQUE NULL, -- Số CCCD
10 | SoDienThoai INT UNIQUE NULL, -- Số điện thoại
11 | DiaChi NVARCHAR(100) NULL, -- Địa chỉ
12 | NgaySinh DATE NULL, -- Ngày sinh
13 | GioiTinh NVARCHAR(10) NULL, -- Giới tính
14 | HinhAnhURL NVARCHAR(255) NOT NULL DEFAULT 'https://i.pinimg.com/736x/20/ef/6b/20ef6b554ea249790281e6677abc4160.jpg', -- URL ảnh mặc định
15 | NgayTao DATETIME DEFAULT GETDATE() -- Ngày tạo
16 | );
17 |
18 |
19 | ALTER TABLE NguoiDung
20 | ALTER COLUMN CanCuocCongDan NVARCHAR(20); -- hoặc NVARCHAR(12) nếu chắc chắn là CCCD Việt Nam
21 |
22 | ALTER TABLE NguoiDung
23 | ALTER COLUMN SoDienThoai NVARCHAR(15); -- đủ dài để chứa số điện thoại Việt Nam, kể cả mã quốc gia
24 |
25 | ALTER TABLE NguoiDung
26 | ALTER COLUMN Vaitro NVARCHAR(15);
27 |
28 | ALTER TABLE NguoiDung DROP CONSTRAINT UQ__NguoiDun__9A7D3DD7ACBA3F05;
29 | ALTER TABLE NguoiDung ALTER COLUMN CanCuocCongDan NVARCHAR(20);
30 | ALTER TABLE NguoiDung ADD CONSTRAINT UQ_CanCuocCongDan UNIQUE (CanCuocCongDan);
31 |
32 | ALTER TABLE NguoiDung DROP CONSTRAINT UQ__NguoiDun__0389B7BD3800E751; -- Cho SoDienThoai
33 | ALTER TABLE NguoiDung ALTER COLUMN SoDienThoai NVARCHAR(15);
34 | ALTER TABLE NguoiDung ADD CONSTRAINT UQ_SoDienThoai UNIQUE (SoDienThoai);
35 |
36 | select * from NguoiDung
37 |
38 | INSERT INTO NguoiDung (
39 | MaNguoiDung, Vaitro, Email, TenTaiKhoan, MatKhau, HoTen,
40 | CanCuocCongDan, SoDienThoai, DiaChi, NgaySinh, GioiTinh
41 | )
42 | VALUES (
43 | 'ND002', 'QuanTriVien', 'admin@example.com', 'admin01', 'admin123',
44 | N'Nguyễn Quản Trị', 123456789, 912345678, N'Hà Nội', '1990-01-01', N'Nam'
45 | );
46 |
47 | INSERT INTO NguoiDung (
48 | MaNguoiDung, Vaitro, Email, TenTaiKhoan, MatKhau, HoTen,
49 | CanCuocCongDan, SoDienThoai, DiaChi, NgaySinh, GioiTinh
50 | )
51 | VALUES (
52 | 'ND004', 'NhanVien', 'admin@xample.com', 'admin01', 'admin123',
53 | N'Nguyễn Quản Trị', 123456786, 9123459678, N'Hà Nội', '1990-01-01', N'Nam'
54 | );
55 |
56 |
57 |
58 | INSERT INTO NguoiDung (
59 | MaNguoiDung, Vaitro, Email, TenTaiKhoan, MatKhau, HoTen,
60 | CanCuocCongDan, SoDienThoai, DiaChi, NgaySinh, GioiTinh
61 | )
62 | VALUES (
63 | 'ND005', 'NhanVien', 'admisn@xample.com', '11111', '11111',
64 | N'Nguyễn Quản Trị', 1234586243, 9512345678, N'Hà Nội', '1990-01-01', N'Nam'
65 | );
66 | -- Bảng Phong
67 | CREATE TABLE Phong (
68 | MaPhong NVARCHAR(6) PRIMARY KEY, -- Mã phòng tự động tăng
69 | LoaiPhong NVARCHAR(50) NOT NULL, -- Loại phòng
70 | GiaPhong DECIMAL(18,2) NOT NULL, -- Giá phòng gốc
71 | TinhTrang TINYINT CHECK (TinhTrang IN (1, 2, 3, 4)) NOT NULL, -- 1: Trống, 2: Đã đặt, 3: Đang sử dụng, 4: Đang vệ sinh
72 | SoLuongPhong INT NOT NULL DEFAULT 1, -- Số lượng phòng
73 | Tang INT NOT NULL, -- Tầng
74 | KieuGiuong NVARCHAR(50) NOT NULL, -- Kiểu giường
75 | MoTa NVARCHAR(500) NULL, -- Mô tả chi tiết về phòng
76 | UrlAnhChinh NVARCHAR(255) NOT NULL, -- URL ảnh chính
77 | SucChua INT NOT NULL DEFAULT 2, -- Sức chứa tối đa
78 | SoGiuong INT NOT NULL DEFAULT 1, -- Số lượng giường
79 | DonViTinh NVARCHAR(50) NOT NULL DEFAULT '1 đêm', -- Đơn vị tính giá phòng
80 | SoSaoTrungBinh DECIMAL(3,2) NOT NULL DEFAULT 0 -- Số sao trung bình
81 | );
82 |
83 | -- Bảng PhongAnh
84 | CREATE TABLE PhongAnh (
85 | MaAnh NVARCHAR(6) PRIMARY KEY, -- Mã ảnh tự động tăng
86 | MaPhong NVARCHAR(6) NOT NULL, -- Mã phòng liên kết
87 | UrlAnh NVARCHAR(255) NOT NULL, -- URL ảnh
88 | FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong) ON DELETE CASCADE -- Ràng buộc với bảng Phong
89 | );
90 |
91 | -- Bảng TienNghi
92 | CREATE TABLE TienNghi (
93 | MaTienNghi NVARCHAR(6) PRIMARY KEY, -- Mã tiện nghi tự động tăng
94 | TenTienNghi NVARCHAR(100) NOT NULL, -- Tên tiện nghi
95 | MoTa NVARCHAR(500) NULL -- Mô tả chi tiết về tiện nghi (nếu cần)
96 | );
97 |
98 | -- Bảng Phong_TienNghi
99 | CREATE TABLE Phong_TienNghi (
100 | MaPhong NVARCHAR(6) NOT NULL, -- Mã phòng
101 | MaTienNghi NVARCHAR(6) NOT NULL, -- Mã tiện nghi
102 | FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong) ON DELETE CASCADE,
103 | FOREIGN KEY (MaTienNghi) REFERENCES TienNghi(MaTienNghi) ON DELETE CASCADE,
104 | PRIMARY KEY (MaPhong, MaTienNghi) -- Chỉ định khóa chính cho cặp mã
105 | );
106 |
107 | -- Bảng GiamGia
108 | CREATE TABLE GiamGia (
109 | MaGiamGia NVARCHAR(6) PRIMARY KEY, -- Mã giảm giá tự động tăng
110 | TenGiamGia NVARCHAR(50) NOT NULL, -- Tên chương trình giảm giá
111 | LoaiGiamGia NVARCHAR(6) CHECK (LoaiGiamGia IN ('PhanTram', 'SoTien')), -- Loại giảm giá
112 | GiaTriGiam DECIMAL(18,2) NOT NULL, -- Giá trị giảm
113 | NgayBatDau DATETIME NOT NULL, -- Ngày bắt đầu áp dụng giảm giá
114 | NgayKetThuc DATETIME NOT NULL, -- Ngày kết thúc áp dụng giảm giá
115 | MoTa NVARCHAR(255) NULL -- Mô tả chi tiết về chương trình giảm giá
116 | );
117 |
118 | -- Bảng Phong_GiamGia
119 | CREATE TABLE Phong_GiamGia (
120 | MaPhong NVARCHAR(6) NOT NULL, -- Mã phòng
121 | MaGiamGia NVARCHAR(6) NOT NULL, -- Mã giảm giá
122 | PRIMARY KEY (MaPhong, MaGiamGia), -- Chỉ định khóa chính cho cặp mã
123 | FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong),
124 | FOREIGN KEY (MaGiamGia) REFERENCES GiamGia(MaGiamGia)
125 | );
126 |
127 | -- Bảng DichVu
128 | CREATE TABLE DichVu (
129 | MaDichVu NVARCHAR(6) PRIMARY KEY, -- Mã dịch vụ tự động tăng
130 | TenDichVu NVARCHAR(100) NOT NULL, -- Tên dịch vụ
131 | DonGia DECIMAL(18,2) NOT NULL, -- Đơn giá
132 | MoTaDichVu NVARCHAR(300) NULL, -- Mô tả dịch vụ
133 | HinhAnhDichVu NVARCHAR(255) NOT NULL, -- URL ảnh dịch vụ
134 | SoLuong INT NOT NULL DEFAULT 0, -- Số lượng dịch vụ
135 | TrangThai TINYINT NOT NULL DEFAULT 1, -- Trạng thái dịch vụ
136 | LoaiDichVu NVARCHAR(50) NOT NULL DEFAULT 'Khac', -- Loại dịch vụ
137 | DonViTinh NVARCHAR(50) NOT NULL DEFAULT '1 lần', -- Đơn vị tính giá dịch vụ
138 | CONSTRAINT CK_DichVu_TrangThai CHECK (TrangThai IN (0, 1)), -- Kiểm tra trạng thái hợp lệ
139 | CONSTRAINT CK_DichVu_SoLuong CHECK (SoLuong >= 0) -- Kiểm tra số lượng không âm
140 | );
141 |
142 | -- Bảng DatPhong
143 | CREATE TABLE DatPhong (
144 | MaDatPhong NVARCHAR(6) PRIMARY KEY, -- Mã đặt phòng tự động tăng
145 | MaNguoiDung NVARCHAR(6) NOT NULL, -- Mã người dùng
146 | MaPhong NVARCHAR(6) NOT NULL, -- Mã phòng
147 | NgayDat DATETIME DEFAULT GETDATE(), -- Ngày đặt
148 | NgayCheckIn DATETIME, -- Ngày check-in
149 | NgayCheckOut DATETIME, -- Ngày check-out
150 | TinhTrangDatPhong TINYINT CHECK (TinhTrangDatPhong IN (1, 2, 3)) NOT NULL, -- 1: Đã xác nhận, 2: Đang chờ, 3: Hủy
151 | FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung),
152 | FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong)
153 | );
154 |
155 | -- Bảng DatDichVu
156 | CREATE TABLE DatDichVu (
157 | MaDatDichVu NVARCHAR(6) PRIMARY KEY, -- Mã đặt dịch vụ tự động tăng
158 | MaDatPhong NVARCHAR(6) NOT NULL, -- Mã đặt phòng
159 | MaDichVu NVARCHAR(6) NOT NULL, -- Mã dịch vụ
160 | SoLuong INT NOT NULL DEFAULT 1, -- Số lượng dịch vụ
161 | MaHoaDon NVarchar(6) NULL, -- Mã hóa đơn liên kết
162 | FOREIGN KEY (MaDatPhong) REFERENCES DatPhong(MaDatPhong),
163 | FOREIGN KEY (MaDichVu) REFERENCES DichVu(MaDichVu),
164 |
165 | );
166 |
167 | -- Xóa ràng buộc FK nếu chưa đặt tên, cần lấy tên bằng cách truy vấn (xem phía dưới nếu cần)
168 | ALTER TABLE DatDichVu
169 | DROP CONSTRAINT FK__DatDichVu__MaHoa__0371755F; -- Tên này có thể khác, cần thay đúng tên
170 |
171 | -- Xóa cột
172 | ALTER TABLE DatDichVu
173 | DROP COLUMN MaHoaDon;
174 |
175 | SELECT name
176 | FROM sys.foreign_keys
177 | WHERE parent_object_id = OBJECT_ID('DatDichVu');
178 |
179 | -- Bảng HoaDon
180 | CREATE TABLE HoaDon (
181 | MaHoaDon NVARCHAR(6) PRIMARY KEY, -- Mã hóa đơn tự động tăng
182 | MaNguoiDung NVARCHAR(6) NOT NULL, -- Mã người dùng
183 | MaDatPhong NVARCHAR(6) NOT NULL, -- Mã đặt phòng
184 | TongTien DECIMAL(18,2) NOT NULL, -- Tổng tiền phải trả
185 | NgayTaoHoaDon DATETIME DEFAULT GETDATE(), -- Ngày tạo hóa đơn
186 | NgayThanhToan DATETIME NULL, -- Ngày thanh toán
187 | TinhTrangHoaDon TINYINT CHECK (TinhTrangHoaDon IN (1, 2)) NOT NULL, -- 1: Đã thanh toán, 2: Chưa thanh toán
188 | FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung),
189 | FOREIGN KEY (MaDatPhong) REFERENCES DatPhong(MaDatPhong)
190 | );
191 |
192 | -- Bảng ChiTietHoaDon
193 | CREATE TABLE ChiTietHoaDon (
194 | MaChiTiet NVARCHAR(6) PRIMARY KEY, -- Mã chi tiết hóa đơn
195 | MaHoaDon NVARCHAR(6) NOT NULL, -- Mã hóa đơn
196 | LoaiKhoanMuc NVARCHAR(12) NOT NULL, -- Loại khoản mục (Phong, DichVu, GiamGia)
197 | MaKhoanMuc NVARCHAR(12) NOT NULL, -- Mã khoản mục (MaPhong, MaDichVu, MaGiamGia)
198 | SoLuong INT NOT NULL DEFAULT 1, -- Số lượng
199 | ThanhTien DECIMAL(18,2) NOT NULL, -- Thành tiền
200 | FOREIGN KEY (MaHoaDon) REFERENCES HoaDon(MaHoaDon)
201 | );
202 |
203 | -- Bảng ThanhToan
204 | CREATE TABLE ThanhToan (
205 | MaThanhToan NVARCHAR(6) PRIMARY KEY, -- Mã thanh toán với tiền tố 'TT'
206 | MaHoaDon NVARCHAR(6) NOT NULL, -- Mã hóa đơn
207 | SoTienThanhToan DECIMAL(18,2) NOT NULL, -- Số tiền thanh toán
208 | NgayThanhToan DATETIME DEFAULT GETDATE(), -- Ngày thanh toán
209 | PhuongThucThanhToan NVARCHAR(50) NOT NULL, -- Phương thức thanh toán
210 | TinhTrangThanhToan NVARCHAR(1) CHECK (TinhTrangThanhToan IN ('1', '2')) NOT NULL, -- 1: Hoàn tất, 2: Chưa hoàn tất
211 | FOREIGN KEY (MaHoaDon) REFERENCES HoaDon(MaHoaDon)
212 | );
213 |
214 | -- Bảng Feedback
215 | CREATE TABLE Feedback (
216 | MaFeedback NVARCHAR(6) PRIMARY KEY, -- Mã phản hồi với tiền tố 'FB'
217 | MaPhong NVARCHAR(6) NOT NULL, -- Mã phòng
218 | MaNguoiDung NVARCHAR(6) NOT NULL, -- Mã người dùng
219 | SoSao INT CHECK (SoSao BETWEEN 1 AND 5) NOT NULL, -- Số sao (1-5 sao)
220 | BinhLuan NVARCHAR(500) NULL, -- Bình luận của người dùng
221 | NgayFeedback DATETIME DEFAULT GETDATE(), -- Ngày tạo phản hồi
222 | FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong),
223 | FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung)
224 | );
225 |
226 | ALTER TABLE Feedback
227 | ADD PhanLoai NVARCHAR(10) NOT NULL
228 | CHECK (PhanLoai IN ('TichCuc', 'TieuCuc'));
229 |
230 | -- Bảng NhanVien
231 | CREATE TABLE NhanVien (
232 | MaNhanVien NVARCHAR(6) PRIMARY KEY, -- Mã nhân viên
233 | MaNguoiDung NVARCHAR(6) NOT NULL, -- Mã người dùng
234 | ChucVu NVARCHAR(50) NOT NULL, -- Chức vụ
235 | Luong DECIMAL(18,2) NOT NULL, -- Lương
236 | NgayVaoLam DATETIME DEFAULT GETDATE(), -- Ngày vào làm
237 | CaLamViec NVARCHAR(50) NULL, -- Ca làm việc (Sáng, Chiều, Tối)
238 | FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung)
239 | );
240 |
241 | -- Bảng LichSuGiaoDich
242 | CREATE TABLE LichSuGiaoDich (
243 | MaGiaoDich NVARCHAR(6) PRIMARY KEY, -- Mã giao dịch
244 | MaNguoiDung NVARCHAR(6) NOT NULL, -- Mã người dùng
245 | LoaiGiaoDich NVARCHAR(50) NOT NULL, -- Loại giao dịch (DatPhong, HuyPhong, ThanhToan, ...)
246 | ThoiGianGiaoDich DATETIME DEFAULT GETDATE(), -- Thời gian giao dịch
247 | MoTa NVARCHAR(255) NULL, -- Mô tả giao dịch
248 | FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung)
249 | );
250 |
251 | -- Bảng BaoCao
252 | CREATE TABLE BaoCao (
253 | MaBaoCao NVARCHAR(6) PRIMARY KEY, -- Mã báo cáo
254 | LoaiBaoCao NVARCHAR(50) NOT NULL, -- Loại báo cáo (DoanhThu, SuDungPhong, ...)
255 | ThoiGian DATETIME DEFAULT GETDATE(), -- Thời gian tạo báo cáo
256 | NoiDung TEXT NULL -- Nội dung báo cáo
257 | );
258 |
259 | -- Bảng ChiTietBaoCao
260 | CREATE TABLE ChiTietBaoCao (
261 | MaChiTiet NVARCHAR(6) PRIMARY KEY, -- Mã chi tiết báo cáo
262 | MaBaoCao NVARCHAR(6) NOT NULL, -- Mã báo cáo
263 | NoiDungChiTiet NVARCHAR(255) NOT NULL, -- Nội dung chi tiết
264 | GiaTri DECIMAL(18,2) NOT NULL, -- Giá trị (ví dụ: doanh thu, tỷ lệ sử dụng)
265 | FOREIGN KEY (MaBaoCao) REFERENCES BaoCao(MaBaoCao)
266 | );
267 |
268 | CREATE TABLE PhongYeuThich (
269 | Id INT IDENTITY PRIMARY KEY,
270 | MaPhong NVARCHAR(6) NOT NULL,
271 | MaNguoiDung INT NOT NULL,
272 | NgayYeuThich DATETIME DEFAULT GETDATE(),
273 | CONSTRAINT FK_PhongYeuThich_Phong FOREIGN KEY (MaPhong) REFERENCES Phong(MaPhong),
274 | CONSTRAINT FK_PhongYeuThich_NguoiDung FOREIGN KEY (MaNguoiDung) REFERENCES NguoiDung(MaNguoiDung),
275 | CONSTRAINT UQ_PhongYeuThich UNIQUE (MaPhong, MaNguoiDung) -- 1 người chỉ thích 1 phòng 1 lần
276 | );
277 |
278 |
279 | CREATE TABLE NoiQuy (
280 | id INT PRIMARY KEY ,
281 | soThuTu INT NOT NULL, -- Số thứ tự hiển thị
282 | tieuDe NVARCHAR(255) NOT NULL, -- Tiêu đề ngắn (vd: Giờ nhận phòng)
283 | noiDung NVARCHAR(MAX) NOT NULL, -- Nội dung
284 | hinhAnh NVARCHAR(500) -- Link ảnh minh họa
285 | );
286 |
287 | DROP TABLE NhanVien;
288 | SELECT p.MaPhong, p.LoaiPhong, p.GiaPhong, p.TinhTrang, p.SoLuongPhong, p.Tang,
289 | p.KieuGiuong, p.MoTa, p.UrlAnhChinh, p.SucChua, p.SoGiuong,
290 | p.DonViTinh, p.SoSaoTrungBinh
291 | FROM Phong p
292 |
293 |
294 | SELECT tn.MaTienNghi, tn.TenTienNghi, tn.MoTa
295 | FROM TienNghi tn
296 | JOIN Phong_TienNghi ptn ON tn.MaTienNghi = ptn.MaTienNghi
297 | WHERE ptn.MaPhong = 'P001'
298 | SELECT gg.MaGiamGia, gg.TenGiamGia, gg.LoaiGiamGia, gg.GiaTriGiam, gg.NgayBatDau, gg.NgayKetThuc, gg.MoTa
299 | FROM GiamGia gg
300 | JOIN Phong_GiamGia pg ON gg.MaGiamGia = pg.MaGiamGia
301 | WHERE pg.MaPhong = 'P001'
302 |
303 | Select* from Phong
--------------------------------------------------------------------------------
/Services/IVnpayService.cs:
--------------------------------------------------------------------------------
1 | using HotelManagementAPI.Models;
2 | using System.Collections.Generic;
3 |
4 | namespace HotelManagementAPI.Services
5 | {
6 | public interface IVnpayService
7 | {
8 | string CreatePaymentUrl(PaymentRequest request);
9 | PaymentResult HandleIpn(Dictionary queryParams);
10 | bool ValidateCallback(VnpayCallbackRequest callbackRequest);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Services/VnpayService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Security.Cryptography;
3 | using System.Text;
4 | using Microsoft.Extensions.Configuration;
5 | using HotelManagementAPI.Models;
6 | using PaymentRequest = HotelManagementAPI.Models.PaymentRequest;
7 |
8 |
9 |
10 | namespace HotelManagementAPI.Services
11 | {
12 | public class VnpayService : IVnpayService
13 | {
14 | private readonly IConfiguration _configuration;
15 |
16 | public VnpayService(IConfiguration configuration)
17 | {
18 | _configuration = configuration;
19 | }
20 |
21 | public string CreatePaymentUrl(PaymentRequest request)
22 | {
23 | var vnpayConfig = _configuration.GetSection("Vnpay");
24 | var tmnCode = vnpayConfig["TmnCode"];
25 | var hashSecret = vnpayConfig["HashSecret"];
26 | var baseUrl = vnpayConfig["BaseUrl"];
27 | var returnUrl = vnpayConfig["ReturnUrl"];
28 |
29 | var queryParams = new SortedDictionary
30 | {
31 | {"vnp_Version", "2.1.0"},
32 | {"vnp_Command", "pay"},
33 | {"vnp_TmnCode", tmnCode},
34 | {"vnp_Amount", ((long)(request.Money * 100)).ToString()},
35 | {"vnp_CreateDate", DateTime.UtcNow.AddHours(7).ToString("yyyyMMddHHmmss")},
36 | {"vnp_CurrCode", "VND"},
37 | {"vnp_IpAddr", request.IpAddress},
38 | {"vnp_ExpireDate", DateTime.UtcNow.AddHours(7).AddMinutes(15).ToString("yyyyMMddHHmmss")},
39 | {"vnp_Locale", "vn"},
40 | {"vnp_OrderInfo", request.Description},
41 | {"vnp_OrderType", "other"}, // hoặc "topup", "fashion", "other" nếu VNPAY cho phép
42 | {"vnp_ReturnUrl", returnUrl},
43 | {"vnp_TxnRef", request.PaymentId.ToString()}
44 | };
45 |
46 | // Tạo chuỗi dữ liệu để ký
47 | var hashData = new StringBuilder();
48 | foreach (var kvp in queryParams)
49 | {
50 | if (hashData.Length > 0)
51 | hashData.Append('&');
52 | hashData.Append($"{kvp.Key}={kvp.Value}");
53 | }
54 |
55 | // Nối secret key vào cuối chuỗi
56 | var dataToSign = hashData.ToString() + hashSecret;
57 |
58 | // Tạo HMAC SHA512 hash (chuẩn VNPAY)
59 | string hash;
60 | using (var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(hashSecret)))
61 | {
62 | var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(hashData.ToString()));
63 | hash = BitConverter.ToString(hashBytes).Replace("-", "").ToUpper();
64 | }
65 |
66 | return $"{baseUrl}?{hashData}&vnp_SecureHash={hash}";
67 | }
68 | public PaymentResult HandleIpn(Dictionary queryParams)
69 | {
70 | // Xử lý logic IPN (Instant Payment Notification) ở đây
71 | // Ví dụ giả lập thành công
72 | return new PaymentResult
73 | {
74 | IsSuccess = true,
75 | Message = "IPN processed successfully"
76 | };
77 | }
78 | public bool ValidateCallback(HotelManagementAPI.Models.VnpayCallbackRequest callbackRequest)
79 | {
80 | // Implement callback validation based on VNPAY documentation
81 | return true;
82 | }
83 | }
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/TrainML/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ML;
2 | using Microsoft.ML.Data;
3 | using System;
4 |
5 | namespace SentimentAnalysisExample
6 | {
7 | public class SentimentData
8 | {
9 | [LoadColumn(0)]
10 | public string? SentimentText { get; set; }
11 |
12 | [LoadColumn(1)]
13 | public bool Sentiment { get; set; }
14 | }
15 |
16 | public class SentimentPrediction
17 | {
18 | [ColumnName("PredictedLabel")]
19 | public bool Prediction { get; set; }
20 | public float Probability { get; set; }
21 | public float Score { get; set; }
22 | }
23 |
24 | class Program
25 | {
26 | static void Main(string[] args)
27 | {
28 | var context = new MLContext();
29 |
30 | // Đọc dữ liệu từ file CSV
31 | var data = context.Data.LoadFromTextFile("data.csv", separatorChar: ',', hasHeader: true);
32 |
33 | // Tạo pipeline cho việc phân loại cảm xúc
34 | var pipeline = context.Transforms.Text.FeaturizeText("Features", nameof(SentimentData.SentimentText))
35 | .Append(context.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: nameof(SentimentData.Sentiment))); // Chỉ định cột nhãn
36 |
37 | // Huấn luyện mô hình
38 | var model = pipeline.Fit(data);
39 |
40 | // Dữ liệu mới để dự đoán
41 | var newSentiment = new SentimentData { SentimentText = "Phòng này sạch và tiện nghi." };
42 | var predictionFunction = context.Model.CreatePredictionEngine(model);
43 | var result = predictionFunction.Predict(newSentiment);
44 |
45 | // Kết quả
46 | Console.WriteLine($"Sentiment: {(result.Prediction ? "Positive" : "Negative")} with probability of {result.Probability}");
47 | context.Model.Save(model, data.Schema, "sentimentModel.zip");
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/TrainML/sentimentModel.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Persinus/HotelManagementAPI/201422e12606043055a775309c98a2d7ce5b8470/TrainML/sentimentModel.zip
--------------------------------------------------------------------------------
/Validators/BaoCaoDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class BaoCaoDTOValidator : AbstractValidator
5 | {
6 | public BaoCaoDTOValidator()
7 | {
8 | RuleFor(x => x.MaBaoCao)
9 | .NotEmpty().WithMessage("Mã báo cáo là bắt buộc.")
10 | .Length(6).WithMessage("Mã báo cáo phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.LoaiBaoCao)
13 | .NotEmpty().WithMessage("Loại báo cáo là bắt buộc.");
14 |
15 | RuleFor(x => x.ThoiGian)
16 | .NotNull().WithMessage("Thời gian là bắt buộc.");
17 |
18 | RuleFor(x => x.NoiDung)
19 | .NotEmpty().WithMessage("Nội dung là bắt buộc.");
20 | }
21 | }
--------------------------------------------------------------------------------
/Validators/ChiTietBaoCaoDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.NhanVien;
3 |
4 | public class ChiTietBaoCaoDTOValidator : AbstractValidator
5 | {
6 | public ChiTietBaoCaoDTOValidator()
7 | {
8 | RuleFor(x => x.MaChiTiet)
9 | .NotEmpty().WithMessage("Mã chi tiết là bắt buộc.")
10 | .Length(6).WithMessage("Mã chi tiết phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.MaBaoCao)
13 | .NotEmpty().WithMessage("Mã báo cáo là bắt buộc.")
14 | .Length(6).WithMessage("Mã báo cáo phải đúng 6 ký tự.");
15 |
16 | RuleFor(x => x.NoiDungChiTiet)
17 | .NotEmpty().WithMessage("Nội dung chi tiết là bắt buộc.");
18 |
19 | RuleFor(x => x.GiaTri)
20 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị phải lớn hơn hoặc bằng 0.");
21 | }
22 | }
--------------------------------------------------------------------------------
/Validators/DichVuDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class DichVuDTOValidator : AbstractValidator
5 | {
6 | public DichVuDTOValidator()
7 | {
8 | // MaDichVu có thể null hoặc empty khi tạo mới, nếu cần validate thì thêm rule
9 | RuleFor(x => x.TenDichVu)
10 | .NotEmpty().WithMessage("Tên dịch vụ là bắt buộc.")
11 | .MaximumLength(100).WithMessage("Tên dịch vụ tối đa 100 ký tự.");
12 |
13 | RuleFor(x => x.DonGia)
14 | .GreaterThanOrEqualTo(0).WithMessage("Đơn giá phải lớn hơn hoặc bằng 0.");
15 |
16 | RuleFor(x => x.MoTaDichVu)
17 | .NotEmpty().WithMessage("Mô tả dịch vụ là bắt buộc.");
18 |
19 | RuleFor(x => x.HinhAnhDichVu)
20 | .NotEmpty().WithMessage("Hình ảnh dịch vụ là bắt buộc.")
21 | .Must(url => Uri.TryCreate(url, UriKind.Absolute, out var uriResult)
22 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps))
23 | .WithMessage("URL hình ảnh không hợp lệ.");
24 |
25 | RuleFor(x => x.SoLuong)
26 | .GreaterThanOrEqualTo(0).WithMessage("Số lượng phải lớn hơn hoặc bằng 0.");
27 |
28 | RuleFor(x => x.LoaiDichVu)
29 | .NotEmpty().WithMessage("Loại dịch vụ là bắt buộc.")
30 | .MaximumLength(50).WithMessage("Loại dịch vụ tối đa 50 ký tự.");
31 |
32 | RuleFor(x => x.DonViTinh)
33 | .NotEmpty().WithMessage("Đơn vị tính là bắt buộc.")
34 | .MaximumLength(50).WithMessage("Đơn vị tính tối đa 50 ký tự.");
35 | }
36 | }
--------------------------------------------------------------------------------
/Validators/FeedBackDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class FeedBackDTOvalidation : AbstractValidator
5 | {
6 | public FeedBackDTOvalidation()
7 | {
8 | RuleFor(x => x.MaPhong)
9 | .NotEmpty().WithMessage("Mã phòng là bắt buộc.");
10 |
11 | RuleFor(x => x.SoSao)
12 | .InclusiveBetween(1, 5).WithMessage("Số sao phải từ 1 đến 5.");
13 |
14 | RuleFor(x => x.BinhLuan)
15 | .MaximumLength(500).WithMessage("Bình luận tối đa 500 ký tự.");
16 |
17 | RuleFor(x => x.PhanLoai)
18 | .NotNull().WithMessage("Phân loại là bắt buộc.");
19 | }
20 | }
--------------------------------------------------------------------------------
/Validators/GiamGiaDetailDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class GiamGiaDetailDTOValidator : AbstractValidator
5 | {
6 | public GiamGiaDetailDTOValidator()
7 | {
8 | RuleFor(x => x.MaGiamGia)
9 | .NotEmpty().WithMessage("Mã giảm giá là bắt buộc.")
10 | .Length(6).WithMessage("Mã giảm giá phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.TenGiamGia)
13 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.")
14 | .MaximumLength(50).WithMessage("Tên giảm giá tối đa 50 ký tự.");
15 |
16 | RuleFor(x => x.GiaTriGiam)
17 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
18 |
19 | RuleFor(x => x.NgayBatDau)
20 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
21 |
22 | RuleFor(x => x.NgayKetThuc)
23 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
24 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
25 |
26 | RuleFor(x => x.MoTa)
27 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
28 | }
29 | }
--------------------------------------------------------------------------------
/Validators/GiamGiaDetailvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class GiamGiaDetailDTOvalidator : AbstractValidator
5 | {
6 | public GiamGiaDetailDTOvalidator()
7 | {
8 | RuleFor(x => x.MaGiamGia)
9 | .NotEmpty().WithMessage("Mã giảm giá là bắt buộc.")
10 | .Length(6).WithMessage("Mã giảm giá phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.TenGiamGia)
13 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.")
14 | .MaximumLength(50).WithMessage("Tên giảm giá tối đa 50 ký tự.");
15 |
16 | RuleFor(x => x.GiaTriGiam)
17 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
18 |
19 | RuleFor(x => x.NgayBatDau)
20 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
21 |
22 | RuleFor(x => x.NgayKetThuc)
23 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
24 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
25 |
26 | RuleFor(x => x.MoTa)
27 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
28 | }
29 | }
--------------------------------------------------------------------------------
/Validators/HoaDonDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.KhachHang;
3 |
4 | public class HoaDonDTOValidator : AbstractValidator
5 | {
6 | public HoaDonDTOValidator()
7 | {
8 | RuleFor(x => x.MaHoaDon)
9 | .NotEmpty().WithMessage("Mã hóa đơn là bắt buộc.")
10 | .Length(5).WithMessage("Mã hóa đơn phải đúng 5 ký tự.");
11 |
12 | RuleFor(x => x.MaNguoiDung)
13 | .NotEmpty().WithMessage("Mã người dùng là bắt buộc.")
14 | .Length(6).WithMessage("Mã người dùng phải đúng 6 ký tự.");
15 |
16 | RuleFor(x => x.MaDatPhong)
17 | .NotEmpty().WithMessage("Mã đặt phòng là bắt buộc.")
18 | .Length(6).WithMessage("Mã đặt phòng phải đúng 6 ký tự.");
19 |
20 | RuleFor(x => x.TongTien)
21 | .GreaterThanOrEqualTo(0).WithMessage("Tổng tiền phải lớn hơn hoặc bằng 0.");
22 |
23 | RuleFor(x => x.TinhTrangHoaDon)
24 | .NotEmpty().WithMessage("Tình trạng hóa đơn là bắt buộc.");
25 | }
26 | }
--------------------------------------------------------------------------------
/Validators/KhachHangHoaDonDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.KhachHang;
3 |
4 | public class KhachHangHoaDonDTOValidator : AbstractValidator
5 | {
6 | public KhachHangHoaDonDTOValidator()
7 | {
8 | RuleFor(x => x.MaHoaDon)
9 | .NotEmpty().WithMessage("Mã hóa đơn là bắt buộc.");
10 |
11 | RuleFor(x => x.MaNguoiDung)
12 | .NotEmpty().WithMessage("Mã người dùng là bắt buộc.");
13 |
14 | RuleFor(x => x.MaDatPhong)
15 | .NotEmpty().WithMessage("Mã đặt phòng là bắt buộc.");
16 |
17 | RuleFor(x => x.TongTien)
18 | .GreaterThanOrEqualTo(0).WithMessage("Tổng tiền phải lớn hơn hoặc bằng 0.");
19 |
20 | RuleFor(x => x.TinhTrangHoaDon)
21 | .InclusiveBetween((byte)1, (byte)2).WithMessage("Tình trạng hóa đơn phải là 1 (Chưa thanh toán) hoặc 2 (Đã thanh toán).");
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/Validators/KhachHangThanhToanDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.KhachHang;
3 |
4 | public class KhachHangThanhToanDTOValidator : AbstractValidator
5 | {
6 | public KhachHangThanhToanDTOValidator()
7 | {
8 |
9 |
10 | RuleFor(x => x.MaHoaDon)
11 | .NotEmpty().WithMessage("Mã hóa đơn là bắt buộc.")
12 | .Length(5).WithMessage("Mã hóa đơn phải đúng 6 ký tự.");
13 |
14 | RuleFor(x => x.SoTienThanhToan)
15 | .GreaterThanOrEqualTo(0).WithMessage("Số tiền thanh toán phải lớn hơn hoặc bằng 0.");
16 |
17 |
18 | RuleFor(x => x.PhuongThucThanhToan)
19 | .NotEmpty().WithMessage("Phương thức thanh toán là bắt buộc.");
20 |
21 |
22 | }
23 | }
--------------------------------------------------------------------------------
/Validators/LoginDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class LoginDTOValidator : AbstractValidator
5 | {
6 | public LoginDTOValidator()
7 | {
8 | RuleFor(x => x.TenTaiKhoan)
9 | .NotEmpty().WithMessage("Tên tài khoản không được để trống.");
10 |
11 | RuleFor(x => x.MatKhau)
12 | .NotEmpty().WithMessage("Mật khẩu không được để trống.");
13 | }
14 | }
--------------------------------------------------------------------------------
/Validators/NguoiDungDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class NguoiDungDTOValidator : AbstractValidator
5 | {
6 | public NguoiDungDTOValidator()
7 | {
8 | RuleFor(x => x.Email)
9 | .NotEmpty().WithMessage("Email là bắt buộc.")
10 | .EmailAddress().WithMessage("Email không hợp lệ.")
11 | .Matches(@"^[a-zA-Z0-9._%+-]+@gmail\.com$").WithMessage("Email phải có định dạng @gmail.com");
12 |
13 | RuleFor(x => x.TenTaiKhoan)
14 | .NotEmpty().WithMessage("Tên tài khoản là bắt buộc.")
15 | .MaximumLength(50).WithMessage("Tên tài khoản không được vượt quá 50 ký tự.");
16 |
17 | RuleFor(x => x.MatKhau)
18 | .NotEmpty().WithMessage("Mật khẩu là bắt buộc.")
19 | .MaximumLength(100).WithMessage("Mật khẩu không được vượt quá 100 ký tự.");
20 |
21 | RuleFor(x => x.HoTen)
22 | .MaximumLength(100).WithMessage("Họ tên không được vượt quá 100 ký tự.");
23 |
24 | RuleFor(x => x.SoDienThoai)
25 | .NotEmpty().WithMessage("Số điện thoại là bắt buộc.");
26 |
27 | RuleFor(x => x.DiaChi)
28 | .NotEmpty().WithMessage("Địa chỉ là bắt buộc.");
29 |
30 | RuleFor(x => x.CanCuocCongDan)
31 | .NotEmpty().WithMessage("Căn cước công dân là bắt buộc.")
32 | .MaximumLength(12).WithMessage("Căn cước công dân không được vượt quá 12 ký tự.");
33 | }
34 | }
--------------------------------------------------------------------------------
/Validators/NhanVienThemBaiVietDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.NhanVien;
3 |
4 | public class NhanVienThemBaiVietDTOValidator : AbstractValidator
5 | {
6 | public NhanVienThemBaiVietDTOValidator()
7 | {
8 | RuleFor(x => x.TieuDe)
9 | .NotEmpty().WithMessage("Tiêu đề là bắt buộc.")
10 | .MaximumLength(200).WithMessage("Tiêu đề tối đa 200 ký tự.");
11 |
12 | RuleFor(x => x.NoiDung)
13 | .NotEmpty().WithMessage("Nội dung là bắt buộc.");
14 | }
15 | }
--------------------------------------------------------------------------------
/Validators/PhongAnhDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class PhongAnhDTOValidator : AbstractValidator
5 | {
6 | public PhongAnhDTOValidator()
7 | {
8 | RuleFor(x => x.MaAnh)
9 | .NotEmpty().WithMessage("Mã ảnh không được để trống.")
10 | .Length(6).WithMessage("Mã ảnh phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.MaPhong)
13 | .NotEmpty().WithMessage("Mã phòng không được để trống.")
14 | .Length(6).WithMessage("Mã phòng phải đúng 6 ký tự.");
15 |
16 | RuleFor(x => x.UrlAnh)
17 | .NotEmpty().WithMessage("Url ảnh không được để trống.");
18 | }
19 | }
--------------------------------------------------------------------------------
/Validators/PhongDetailsDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class PhongDetailsDTOValidator : AbstractValidator
5 | {
6 | public PhongDetailsDTOValidator()
7 | {
8 | RuleFor(x => x.MaPhong).NotEmpty();
9 | RuleFor(x => x.LoaiPhong).NotEmpty();
10 | RuleFor(x => x.GiaPhong).GreaterThanOrEqualTo(0).WithMessage("Giá phòng phải lớn hơn hoặc bằng 0.");
11 | RuleFor(x => x.TinhTrang).NotEmpty();
12 | RuleFor(x => x.Tang).GreaterThanOrEqualTo(1).WithMessage("Tầng phải lớn hơn hoặc bằng 1.");
13 | RuleFor(x => x.KieuGiuong).NotEmpty();
14 | RuleFor(x => x.UrlAnhChinh).NotEmpty().Must(url => Uri.TryCreate(url, UriKind.Absolute, out _)).WithMessage("URL ảnh chính không hợp lệ.");
15 | RuleFor(x => x.SucChua).GreaterThanOrEqualTo(1).WithMessage("Sức chứa phải lớn hơn hoặc bằng 1.");
16 | RuleFor(x => x.SoGiuong).GreaterThanOrEqualTo(1).WithMessage("Số giường phải lớn hơn hoặc bằng 1.");
17 | RuleFor(x => x.DonViTinh).NotEmpty();
18 | RuleFor(x => x.SoSaoTrungBinh).InclusiveBetween(0, 5).WithMessage("Số sao trung bình phải nằm trong khoảng từ 0 đến 5.");
19 |
20 | }
21 | }
--------------------------------------------------------------------------------
/Validators/QuanLyChungSuaBaiVietDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanLyChung;
3 |
4 | public class QuanLyChungSuaBaiVietDTOValidator : AbstractValidator
5 | {
6 | public QuanLyChungSuaBaiVietDTOValidator()
7 | {
8 | RuleFor(x => x.MaBaiViet)
9 | .NotEmpty().WithMessage("Mã bài viết là bắt buộc.");
10 |
11 | RuleFor(x => x.TieuDe)
12 | .NotEmpty().WithMessage("Tiêu đề là bắt buộc.")
13 | .MaximumLength(100).WithMessage("Tiêu đề tối đa 100 ký tự.");
14 |
15 | RuleFor(x => x.NoiDung)
16 | .NotEmpty().WithMessage("Nội dung là bắt buộc.");
17 | }
18 | }
--------------------------------------------------------------------------------
/Validators/QuanLyChungSuaDichVuDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanLyChung;
3 |
4 | public class QuanLyChungSuaDichVuDTOValidator : AbstractValidator
5 | {
6 | public QuanLyChungSuaDichVuDTOValidator()
7 | {
8 | RuleFor(x => x.TenDichVu)
9 | .NotEmpty().WithMessage("Tên dịch vụ là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên dịch vụ tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.DonGia)
13 | .GreaterThanOrEqualTo(0).WithMessage("Đơn giá phải lớn hơn hoặc bằng 0.");
14 |
15 | RuleFor(x => x.MoTaDichVu)
16 | .NotEmpty().WithMessage("Mô tả dịch vụ là bắt buộc.");
17 |
18 | RuleFor(x => x.HinhAnhDichVu)
19 | .NotEmpty().WithMessage("Hình ảnh dịch vụ là bắt buộc.")
20 | .Must(url => Uri.TryCreate(url, UriKind.Absolute, out var uriResult)
21 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps))
22 | .WithMessage("URL hình ảnh không hợp lệ.");
23 |
24 | RuleFor(x => x.SoLuong)
25 | .GreaterThanOrEqualTo(0).WithMessage("Số lượng phải lớn hơn hoặc bằng 0.");
26 |
27 | RuleFor(x => x.TrangThai)
28 | .InclusiveBetween((byte)0, (byte)1).WithMessage("Trạng thái phải là 0 (không hoạt động) hoặc 1 (hoạt động).");
29 |
30 | RuleFor(x => x.LoaiDichVu)
31 | .NotEmpty().WithMessage("Loại dịch vụ là bắt buộc.")
32 | .MaximumLength(50).WithMessage("Loại dịch vụ tối đa 50 ký tự.");
33 |
34 | RuleFor(x => x.DonViTinh)
35 | .NotEmpty().WithMessage("Đơn vị tính là bắt buộc.")
36 | .MaximumLength(50).WithMessage("Đơn vị tính tối đa 50 ký tự.");
37 | }
38 | }
--------------------------------------------------------------------------------
/Validators/QuanLyChungSuaPhongAnhPutDTOvalidaton.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanLyChung;
3 |
4 | public class QuanLyChungSuaPhongAnhDTOValidator : AbstractValidator
5 | {
6 | public QuanLyChungSuaPhongAnhDTOValidator()
7 | {
8 | RuleFor(x => x.UrlAnh)
9 | .NotEmpty().WithMessage("URL ảnh là bắt buộc.")
10 | .Must(url => Uri.TryCreate(url, UriKind.Absolute, out var uriResult)
11 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps))
12 | .WithMessage("URL ảnh không hợp lệ.");
13 | }
14 | }
--------------------------------------------------------------------------------
/Validators/QuanLyChungSuaPhongGiamGiaDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanLyChung;
3 |
4 | public class QuanLyChungSuaPhongGiamGiaDTOValidator : AbstractValidator
5 | {
6 | public QuanLyChungSuaPhongGiamGiaDTOValidator()
7 | {
8 | RuleFor(x => x.TenGiamGia)
9 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.");
10 |
11 | RuleFor(x => x.GiaTriGiam)
12 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
13 |
14 | RuleFor(x => x.NgayBatDau)
15 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
16 |
17 | RuleFor(x => x.NgayKetThuc)
18 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
19 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
20 |
21 | RuleFor(x => x.MoTa)
22 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
23 | }
24 | }
--------------------------------------------------------------------------------
/Validators/QuanLyChungSuaPhongTienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanLyChung;
3 |
4 | public class QuanLyChungSuaPhongTienNghiDTOValidator : AbstractValidator
5 | {
6 | public QuanLyChungSuaPhongTienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.TenTienNghi)
9 | .NotEmpty().WithMessage("Tên tiện nghi là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên tiện nghi tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.MoTa)
13 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
14 | }
15 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienApDungGiamGiaDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienApDungGiamGiaDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienApDungGiamGiaDTOValidator()
7 | {
8 | RuleFor(x => x.MaGiamGia)
9 | .NotEmpty().WithMessage("Mã giảm giá là bắt buộc.");
10 |
11 | RuleFor(x => x.TenGiamGia)
12 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.");
13 |
14 | RuleFor(x => x.GiaTriGiam)
15 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
16 |
17 | RuleFor(x => x.NgayBatDau)
18 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
19 |
20 | RuleFor(x => x.NgayKetThuc)
21 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
22 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
23 |
24 | RuleFor(x => x.MoTa)
25 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
26 |
27 | RuleFor(x => x.DanhSachMaPhong)
28 | .NotNull().WithMessage("Danh sách mã phòng là bắt buộc.")
29 | .Must(list => list.Count > 0).WithMessage("Danh sách mã phòng không được để trống.");
30 | }
31 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienSuaGiamGiaDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienSuaGiamGiaDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienSuaGiamGiaDTOValidator()
7 | {
8 | RuleFor(x => x.MaGiamGia)
9 | .NotEmpty().WithMessage("Mã giảm giá là bắt buộc.");
10 |
11 | RuleFor(x => x.TenGiamGia)
12 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.");
13 |
14 | RuleFor(x => x.GiaTriGiam)
15 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
16 |
17 | RuleFor(x => x.NgayBatDau)
18 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
19 |
20 | RuleFor(x => x.NgayKetThuc)
21 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
22 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
23 |
24 | RuleFor(x => x.MoTa)
25 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
26 | }
27 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienSuaNoiQuyDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienSuaNoiQuyDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienSuaNoiQuyDTOValidator()
7 | {
8 | RuleFor(x => x.TenNoiQuy)
9 | .NotEmpty().WithMessage("Tên nội quy là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên nội quy tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.MoTa)
13 | .NotEmpty().WithMessage("Mô tả là bắt buộc.")
14 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
15 |
16 | RuleFor(x => x.NgayCapNhat)
17 | .NotEmpty().WithMessage("Ngày cập nhật là bắt buộc.");
18 | }
19 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienSuaRoleDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienSuaRoleDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienSuaRoleDTOValidator()
7 | {
8 | RuleFor(x => x.VaiTroMoi)
9 | .NotEmpty().WithMessage("Vai trò mới là bắt buộc.");
10 | }
11 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThem1DichVuDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThem1DichVuDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThem1DichVuDTOValidator()
7 | {
8 | RuleFor(x => x.TenDichVu)
9 | .NotEmpty().WithMessage("Tên dịch vụ là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên dịch vụ tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.DonGia)
13 | .GreaterThanOrEqualTo(0).WithMessage("Đơn giá phải lớn hơn hoặc bằng 0.");
14 |
15 | RuleFor(x => x.MoTaDichVu)
16 | .NotEmpty().WithMessage("Mô tả dịch vụ là bắt buộc.");
17 |
18 | RuleFor(x => x.SoLuong)
19 | .GreaterThanOrEqualTo(0).WithMessage("Số lượng phải lớn hơn hoặc bằng 0.");
20 |
21 | RuleFor(x => x.LoaiDichVu)
22 | .NotEmpty().WithMessage("Loại dịch vụ là bắt buộc.")
23 | .MaximumLength(50).WithMessage("Loại dịch vụ tối đa 50 ký tự.");
24 |
25 | RuleFor(x => x.DonViTinh)
26 | .NotEmpty().WithMessage("Đơn vị tính là bắt buộc.")
27 | .MaximumLength(50).WithMessage("Đơn vị tính tối đa 50 ký tự.");
28 | }
29 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThem1NoiQuyDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThem1NoiQuyDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThem1NoiQuyDTOValidator()
7 | {
8 | RuleFor(x => x.TenNoiQuy)
9 | .NotEmpty().WithMessage("Tên nội quy là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên nội quy tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.MoTa)
13 | .NotEmpty().WithMessage("Mô tả là bắt buộc.")
14 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
15 |
16 | RuleFor(x => x.NgayTao)
17 | .NotEmpty().WithMessage("Ngày tạo là bắt buộc.");
18 |
19 | RuleFor(x => x.NgayCapNhat)
20 | .NotEmpty().WithMessage("Ngày cập nhật là bắt buộc.");
21 | }
22 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThem1PhongDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThem1PhongDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThem1PhongDTOValidator()
7 | {
8 | RuleFor(x => x.LoaiPhong)
9 | .NotEmpty().WithMessage("Loại phòng là bắt buộc.");
10 |
11 | RuleFor(x => x.GiaPhong)
12 | .GreaterThanOrEqualTo(0).WithMessage("Giá phòng phải lớn hơn hoặc bằng 0.");
13 |
14 |
15 |
16 |
17 |
18 | RuleFor(x => x.Tang)
19 | .GreaterThanOrEqualTo(0).WithMessage("Tầng phải lớn hơn hoặc bằng 0.");
20 |
21 | RuleFor(x => x.KieuGiuong)
22 | .NotEmpty().WithMessage("Kiểu giường là bắt buộc.");
23 |
24 | RuleFor(x => x.MoTa)
25 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
26 |
27 | RuleFor(x => x.SucChua)
28 | .GreaterThanOrEqualTo(1).WithMessage("Sức chứa phải lớn hơn hoặc bằng 1.");
29 |
30 | RuleFor(x => x.SoGiuong)
31 | .GreaterThanOrEqualTo(1).WithMessage("Số giường phải lớn hơn hoặc bằng 1.");
32 | }
33 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThem1TienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThem1TienNghiDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThem1TienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.TenTienNghi)
9 | .NotEmpty().WithMessage("Tên tiện nghi là bắt buộc.")
10 | .MaximumLength(100).WithMessage("Tên tiện nghi tối đa 100 ký tự.");
11 |
12 | RuleFor(x => x.MoTa)
13 | .MaximumLength(500).WithMessage("Mô tả tối đa 500 ký tự.");
14 | }
15 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThemAnhDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThemAnhDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThemAnhDTOValidator()
7 | {
8 | RuleFor(x => x.MaPhong)
9 | .NotEmpty().WithMessage("Mã phòng là bắt buộc.");
10 | }
11 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThemGiamGiaDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThemGiamGiaDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThemGiamGiaDTOValidator()
7 | {
8 | RuleFor(x => x.TenGiamGia)
9 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.");
10 |
11 | RuleFor(x => x.GiaTriGiam)
12 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
13 |
14 | RuleFor(x => x.NgayBatDau)
15 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
16 |
17 | RuleFor(x => x.NgayKetThuc)
18 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
19 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
20 |
21 | RuleFor(x => x.MoTa)
22 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
23 | }
24 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThemMaGiamGiaDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThemMaGiamGiaDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThemMaGiamGiaDTOValidator()
7 | {
8 | RuleFor(x => x.TenGiamGia)
9 | .NotEmpty().WithMessage("Tên giảm giá là bắt buộc.")
10 | .MaximumLength(50).WithMessage("Tên giảm giá tối đa 50 ký tự.");
11 |
12 | RuleFor(x => x.LoaiGiamGia)
13 | .NotEmpty().WithMessage("Loại giảm giá là bắt buộc.")
14 | .Length(6).WithMessage("Loại giảm giá phải đúng 6 ký tự.");
15 |
16 | RuleFor(x => x.GiaTriGiam)
17 | .GreaterThanOrEqualTo(0).WithMessage("Giá trị giảm phải lớn hơn hoặc bằng 0.");
18 |
19 | RuleFor(x => x.NgayBatDau)
20 | .NotEmpty().WithMessage("Ngày bắt đầu là bắt buộc.");
21 |
22 | RuleFor(x => x.NgayKetThuc)
23 | .NotEmpty().WithMessage("Ngày kết thúc là bắt buộc.")
24 | .GreaterThanOrEqualTo(x => x.NgayBatDau).WithMessage("Ngày kết thúc phải lớn hơn hoặc bằng ngày bắt đầu.");
25 |
26 | RuleFor(x => x.MoTa)
27 | .MaximumLength(255).WithMessage("Mô tả tối đa 255 ký tự.");
28 | }
29 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThemNhieuDichVuvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThemNhieuDichVuDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThemNhieuDichVuDTOValidator()
7 | {
8 | RuleFor(x => x.DanhSachDichVu)
9 | .NotNull().WithMessage("Danh sách dịch vụ là bắt buộc.")
10 | .Must(list => list.Count > 0).WithMessage("Danh sách dịch vụ không được để trống.")
11 | .ForEach(dv => dv.SetValidator(new QuanTriVienThem1DichVuDTOValidator()));
12 | }
13 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienThemNhieuTienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienThemNhieuTienNghiDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienThemNhieuTienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.DanhSachTienNghi)
9 | .NotNull().WithMessage("Danh sách tiện nghi là bắt buộc.")
10 | .Must(list => list.Count > 0).WithMessage("Danh sách tiện nghi không được để trống.")
11 | .ForEach(tn => tn.SetValidator(new QuanTriVienThem1TienNghiDTOValidator()));
12 | }
13 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienXoa1Phongvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienXoa1PhongDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienXoa1PhongDTOValidator()
7 | {
8 | RuleFor(x => x.MaPhong)
9 | .NotEmpty().WithMessage("Mã phòng là bắt buộc.");
10 | }
11 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienXoa1TienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienXoa1TienNghiDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienXoa1TienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.MaTienNghi)
9 | .NotEmpty().WithMessage("Mã tiện nghi là bắt buộc.");
10 | }
11 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienXoaNhieuTienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienXoaNhieuTienNghiDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienXoaNhieuTienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.DanhSachMaTienNghi)
9 | .NotNull().WithMessage("Danh sách mã tiện nghi là bắt buộc.")
10 | .Must(list => list.Count > 0).WithMessage("Danh sách mã tiện nghi không được để trống.");
11 | }
12 | }
--------------------------------------------------------------------------------
/Validators/QuanTriVienXoaNoiQuyDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.QuanTriVien;
3 |
4 | public class QuanTriVienXoaNoiQuyDTOValidator : AbstractValidator
5 | {
6 | public QuanTriVienXoaNoiQuyDTOValidator()
7 | {
8 | RuleFor(x => x.Id)
9 | .GreaterThan(0).WithMessage("Id phải lớn hơn 0.");
10 | }
11 | }
--------------------------------------------------------------------------------
/Validators/ResetPasswordDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class ResetPasswordDTOValidator : AbstractValidator
5 | {
6 | public ResetPasswordDTOValidator()
7 | {
8 | RuleFor(x => x.Email)
9 | .NotEmpty().WithMessage("Email là bắt buộc.")
10 | .EmailAddress().WithMessage("Email không hợp lệ.");
11 |
12 | RuleFor(x => x.NewPassword)
13 | .NotEmpty().WithMessage("Mật khẩu mới là bắt buộc.")
14 | .MaximumLength(100).WithMessage("Mật khẩu không được vượt quá 100 ký tự.");
15 | }
16 | }
--------------------------------------------------------------------------------
/Validators/TaoHoaDonRequestDTOvalidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.KhachHang;
3 |
4 | public class TaoHoaDonRequestDTOValidator : AbstractValidator
5 | {
6 | public TaoHoaDonRequestDTOValidator()
7 | {
8 | RuleFor(x => x.MaDatPhong)
9 | .NotEmpty().WithMessage("Mã đặt phòng là bắt buộc.");
10 |
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/Validators/TatCaBaiVietDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class TatCaBaiVietDTOValidator : AbstractValidator
5 | {
6 | public TatCaBaiVietDTOValidator()
7 | {
8 | RuleFor(x => x.MaBaiViet)
9 | .NotEmpty().WithMessage("Mã bài viết là bắt buộc.");
10 |
11 | RuleFor(x => x.MaNguoiDung)
12 | .NotEmpty().WithMessage("Mã người dùng là bắt buộc.");
13 |
14 | RuleFor(x => x.TieuDe)
15 | .NotEmpty().WithMessage("Tiêu đề là bắt buộc.")
16 | .MaximumLength(200).WithMessage("Tiêu đề tối đa 200 ký tự.");
17 |
18 | RuleFor(x => x.NoiDung)
19 | .NotEmpty().WithMessage("Nội dung là bắt buộc.");
20 |
21 | // NgayDang, HinhAnhUrl, TrangThai là optional, không cần rule bắt buộc
22 | }
23 | }
--------------------------------------------------------------------------------
/Validators/ThanhToanDTOValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs.KhachHang;
3 |
4 | public class ThanhToanDTOValidator : AbstractValidator
5 | {
6 | public ThanhToanDTOValidator()
7 | {
8 |
9 |
10 | RuleFor(x => x.MaHoaDon)
11 | .NotEmpty().WithMessage("Mã hóa đơn là bắt buộc.")
12 | .Length(5).WithMessage("Mã hóa đơn phải đúng 6 ký tự.");
13 |
14 | RuleFor(x => x.SoTienThanhToan)
15 | .GreaterThanOrEqualTo(0).WithMessage("Số tiền thanh toán phải lớn hơn hoặc bằng 0.");
16 |
17 |
18 | }
19 | }
--------------------------------------------------------------------------------
/Validators/TienNghiDTOvalidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using HotelManagementAPI.DTOs;
3 |
4 | public class TienNghiDTOValidator : AbstractValidator
5 | {
6 | public TienNghiDTOValidator()
7 | {
8 | RuleFor(x => x.MaTienNghi)
9 | .NotEmpty().WithMessage("Mã tiện nghi là bắt buộc.")
10 | .Length(6).WithMessage("Mã tiện nghi phải đúng 6 ký tự.");
11 |
12 | RuleFor(x => x.TenTienNghi)
13 | .NotEmpty().WithMessage("Tên tiện nghi là bắt buộc.")
14 | .MaximumLength(100).WithMessage("Tên tiện nghi tối đa 100 ký tự.");
15 |
16 | // MoTa là optional, không cần rule bắt buộc
17 | }
18 | }
--------------------------------------------------------------------------------
/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "SentimentModelPath": "TrainMl/sentimentModel.zip",
3 | "Logging": {
4 | "LogLevel": {
5 | "Default": "Information",
6 | "Microsoft.AspNetCore": "Warning"
7 | }
8 | },
9 | "Vnpay": {
10 | "TmnCode": "BVKD7H69",
11 | "HashSecret": "FF2HI5VQCGPDE9CHSSH537KXNEZ71NV3",
12 | "BaseUrl": "https://sandbox.vnpayment.vn/paymentv2/vpcpay.html",
13 | "ReturnUrl": "https://nhom2webkhachsan.runasp.net/api/Vnpay/Callback"
14 | },
15 | "Jwt": {
16 | "SecretKey": "your_super_secret_key_1234567890",
17 | "Issuer": "your-issuer",
18 | "Audience": "your-audience"
19 | },
20 | "Swagger": {
21 | "Enable": true
22 | },
23 | "UseAuthentication": true,
24 | "ConnectionStrings": {
25 | "DefaultConnection": "Server=118.69.126.49;Database=data_QLKS_115_Nhom2;User Id=user_115_nhom2;Password=123456789;TrustServerCertificate=True;"
26 | },
27 | "CloudinarySettings": {
28 | "CloudName": "dplymhdgi",
29 | "ApiKey": "476929846242123",
30 | "ApiSecret": "8oMP6HQ6PpA7UEJu0XDOGob5ppk"
31 | },
32 | "AllowedHosts": "*"
33 | }
34 |
--------------------------------------------------------------------------------
/note.txt:
--------------------------------------------------------------------------------
1 | - Tìm hiểu controllers dapper dto
2 | - Program
3 | - TÌm hiểu Packages
4 | - TÌm hiểu Models
5 | <<<<<<< HEAD
6 | - ghi chú Sql
7 | -huy
8 | cài các gói thư viện
9 | sửa file đặt phòng
10 | sửa hóa đơn Phòng
11 | sửa hóa đơn khách hàng DV ()
12 | Xóa Quản trị viên QTV ko cần thêm sửa xóa :v
13 | Người dùng khi đăng nhập vào thì auto làm khách hàng
14 |
15 |
16 |
17 |
18 |
19 |
20 | Huy làm Phòng và ng dùng , khách hàng
21 | Khiêm làm QTV và dịch vụ , nhân viên
22 |
23 | ng dung them dc
24 | k dang nhap dang ky dc
25 | chua phan quyen dc
26 | //////////////// bao cao tuan 2 ////////////////////////////////
27 |
28 | <<<<<<< HEAD
29 | làm phan quyen + JWT
30 | phong
31 | dich vu
32 | hoa don
33 | ---huy
34 |
35 |
36 | {
37 | "VaiTro":"KhachHang",
38 | "MaNguoiDung":"ND201",
39 | "Email": "khachhang@example.com",
40 | "TenTaiKhoan": "khachhang01",
41 | "MatKhau": "password123",
42 | "HoTen": "Nguyen Van A",
43 | "CanCuocCongDan": "123456789012",
44 | "SoDienThoai": "0123456789",
45 | "DiaChi": "123 Nguyen Trai, Ha Noi",
46 | "NgaySinh": "1990-01-01",
47 | "GioiTinh": "Nam",
48 | "HinhAnhUrl": "https://example.com/avatar.jpg"
49 | }
50 |
51 |
52 | {
53 | "tenTaiKhoan": "admin",
54 | "matKhau": "matkhau_ma_hoa"
55 | }
56 | {
57 | "tenTaiKhoan": "khachhang01",
58 | "matKhau": "password123"
59 | }
60 |
61 | nhiem vu :
62 | sửa nội dung này
63 | 📘 **Đề tài:** Xây dựng hệ thống quản lý khách sạn hiện đại phục vụ cho việc đặt phòng, quản lý người dùng, hóa đơn, dịch vụ và phản hồi khách hàng.
64 |
65 | 🔧 **Công nghệ sử dụng:**
66 | - ASP.NET Core Web API
67 | - SQL Server
68 | - Entity Framework/Dapper
69 | - JWT Authentication
70 | - Swagger UI
71 | - (Tuỳ chọn: React/Vue cho frontend, nếu có)
72 |
73 | 🎯 **Chức năng chính:**
74 | - Đăng ký người dùng
75 | - Quản lý phòng: thêm, sửa, xoá, xem trạng thái
76 | - Đặt phòng, thanh toán, và xuất hoá đơn
77 | - Quản lý dịch vụ đi kèm
78 | - Phản hồi từ khách hàng (feedback)
79 | - Phân quyền người dùng (admin, lễ tân, khách hàng)
80 |
81 | 🔗 **GitHub Repository:** [https://github.com/Persinus/HotelManagementAPI](https://github.com/Persinus/HotelManagementAPI)
82 | "
83 |
84 | sử dụng using System.ComponentModel.DataAnnotations;
85 | và requie vào các dto tự sinh bỏ qua
86 |
87 | về phần aloww anynumous
88 | Login thì những người đăng nhập dc thì code trong đấy
89 | Phòng cũng v
90 |
91 | Authorize
92 | Ai có quyền mới vào dc (ví dụ logout profile bản thân)
93 |
94 | có 3 quyền thì code 3 file Khachhangcontroller tuân thủ theo middleware
95 | //
96 | // Phân quyền dựa trên đường dẫn
97 | if (context.Request.Path.StartsWithSegments("/api/quantrivien") && userRole != "QuanTriVien")
98 | {
99 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
100 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
101 | return;
102 | }
103 | else if (context.Request.Path.StartsWithSegments("/api/nhanvien") && userRole != "NhanVien" && userRole != "QuanTriVien")
104 | {
105 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
106 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
107 | return;
108 | }
109 | else if (context.Request.Path.StartsWithSegments("/api/khachhang") && userRole != "KhachHang" && userRole != "NhanVien" && userRole != "QuanTriVien")
110 | {
111 | context.Response.StatusCode = StatusCodes.Status403Forbidden;
112 | await context.Response.WriteAsync("Bạn không có quyền truy cập vào tài nguyên này.");
113 | return;
114 | }
115 |
116 |
117 |
118 | sinh lỗi cụ thể --- Email ko dc trùng , sdt (nếu ko log lỗi thì 500 error )
119 |
120 |
121 | Code thêm Sumary vào từng đoạn code hướng dẫn ng dùng swagger thêm,sửa xoa1 dữ liệu ....
122 |
123 | - thêm 1 số khách hàng vào database = swagger
124 |
125 |
126 | Task 1 : Sửa tiêu đề swagger //ok
127 | Task2 : thêm tatt61 cả DTO vào bài //ok
128 | Task 3: sửa Using (sử dụng using System.ComponentModel.DataAnnotations;
129 | )//ok
130 | Task 4: Thêm Sumany của từng controller (test Oke thì làm )
131 | Task 5: add thêm dữ liệu Khách hàng (Post API swagger)
132 |
133 |
134 | =======
135 | - ghi chú Sql
136 | >>>>>>> baf6ee7 (them_note.txt)
137 | =======
138 | làm phan quyen + JWT
139 | phong
140 | dich vu
141 | hoa don
142 |
143 |
144 | >>>>>>> 8e2fcb0 (lambai)
145 |
--------------------------------------------------------------------------------