├── .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 | .vs/ 49 | /obj/ 50 | /bin/ 51 | bin/ 52 | obj/ 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 | --------------------------------------------------------------------------------