# API Documentation - Quản Lý Mặt Bằng Bưu Cục (Premise)

## Mục lục
1. [Tiêu chí chấm điểm (Quản lý cấu hình)](#1-tiêu-chí-chấm-điểm-quản-lý-cấu-hình)
2. [Quản lý mặt bằng (Nhân viên khảo sát)](#2-quản-lý-mặt-bằng-nhân-viên-khảo-sát)
3. [Duyệt & Đàm phán (Quản lý)](#3-duyệt--đàm-phán-quản-lý)

> [!IMPORTANT]
> **Luồng công việc tổng quan:**
> 1. **Quản lý** cấu hình tiêu chí chấm điểm (Section 1)
> 2. **Nhân viên** tạo mặt bằng mới, nhập liên hệ, chấm điểm → trạng thái `Surveying` (Section 2)
> 3. **Nhân viên** hoàn thành khảo sát → chuyển trạng thái `Evaluating`
> 4. **Quản lý** xem xét, duyệt → chuyển trạng thái `Negotiating` hoặc `Rejected`
> 5. **Quản lý** cập nhật thông tin tài chính (đàm phán giá) → chuyển `Approved` → `Rented`

> [!NOTE]
> **Enums tham chiếu:**
> - `PremiseStatus`: 1=Surveying, 2=Evaluating, 3=Negotiating, 4=Approved, 5=Rented, 6=Rejected, 7=Closed
> - `ScoringCriteriaType`: 1=Option (chọn từ danh sách), 2=Range (khoảng giá trị)
> - `PremiseContactRole`: 1=Landlord (Chủ nhà), 2=Broker (Môi giới), 3=AuthorizedPerson (Người được ủy quyền)
> - `PremiseMediaType`: 1=FrontageImage (Ảnh mặt tiền), 2=InsideImage (Ảnh bên trong), 3=StreetImage (Ảnh đường), 4=Video, 5=LegalDocument (Giấy tờ pháp lý)

---

## 1. Tiêu chí chấm điểm (Quản lý cấu hình)

> [!TIP]
> **Phải cấu hình tiêu chí TRƯỚC khi nhân viên tạo mặt bằng.** Front-end cần gọi `GetAllActiveCriteria` để lấy danh sách tiêu chí hiển thị form chấm điểm.

### 1.1. Tìm kiếm tiêu chí

- **Endpoint**: `POST /api/PremiseScoring/SearchCriteria`
- **Authorization**: Bearer Token

**Request Body:**
```json
{
  "Pagination": {
    "PageIndex": 1,
    "PageSize": 15
  },
  "Search": {
    "PredicateObject": {
      "Keyword": "vị trí"
    }
  },
  "Sort": {
    "Predicate": "DisplayOrder",
    "Reverse": false
  }
}
```

**Response:**
```json
{
  "TotalRecord": 5,
  "Data": [
    {
      "Id": 1,
      "Name": "Vị trí mặt bằng",
      "Description": "Đánh giá vị trí địa lý",
      "CriteriaType": 1,
      "DisplayOrder": 1,
      "IsActive": true,
      "Options": [
        { "Id": 1, "Label": "Mặt tiền đường lớn", "MinValue": null, "MaxValue": null, "Score": 10, "DisplayOrder": 1 },
        { "Id": 2, "Label": "Hẻm xe hơi", "MinValue": null, "MaxValue": null, "Score": 5, "DisplayOrder": 2 }
      ]
    },
    {
      "Id": 2,
      "Name": "Giá thuê",
      "Description": "Khoảng giá thuê hàng tháng (triệu VNĐ)",
      "CriteriaType": 2,
      "DisplayOrder": 2,
      "IsActive": true,
      "Options": [
        { "Id": 3, "Label": "Dưới 5 triệu", "MinValue": 0, "MaxValue": 5, "Score": 10, "DisplayOrder": 1 },
        { "Id": 4, "Label": "5-8 triệu", "MinValue": 5, "MaxValue": 8, "Score": 7, "DisplayOrder": 2 }
      ]
    }
  ]
}
```

### 1.2. Lấy chi tiết tiêu chí theo ID

- **Endpoint**: `GET /api/PremiseScoring/GetCriteriaById/{id}`
- **Authorization**: Bearer Token

**Request Parameters:**
- `id` (int, path): ID tiêu chí

**Response:**
```json
{
  "Id": 1,
  "Name": "Vị trí mặt bằng",
  "Description": "Đánh giá vị trí địa lý",
  "CriteriaType": 1,
  "DisplayOrder": 1,
  "IsActive": true,
  "Options": [
    { "Id": 1, "Label": "Mặt tiền đường lớn", "MinValue": null, "MaxValue": null, "Score": 10, "DisplayOrder": 1 },
    { "Id": 2, "Label": "Hẻm xe hơi", "MinValue": null, "MaxValue": null, "Score": 5, "DisplayOrder": 2 }
  ]
}
```

### 1.3. Tạo mới / cập nhật tiêu chí

- **Endpoint**: `POST /api/PremiseScoring/CreateOrUpdateCriteria`
- **Authorization**: Bearer Token

> [!IMPORTANT]
> - `Id = 0`: **Tạo mới**. `Id > 0`: **Cập nhật**.
> - `CriteriaType = 1` (Option): Options chỉ cần `Label` + `Score`.
> - `CriteriaType = 2` (Range): Options cần `MinValue`, `MaxValue`, `Score`.
> - Options có `Id = 0` sẽ được tạo mới. Options có `Id > 0` sẽ được cập nhật. Options cũ không có trong danh sách sẽ bị soft delete.

**Request Body (Tạo mới loại Option):**
```json
{
  "Id": 0,
  "Name": "Loại mặt bằng",
  "Description": "Đánh giá loại hình mặt bằng",
  "CriteriaType": 1,
  "DisplayOrder": 3,
  "IsActive": true,
  "Options": [
    { "Id": 0, "Label": "Nhà mặt tiền", "Score": 10, "DisplayOrder": 1 },
    { "Id": 0, "Label": "Nhà trong hẻm", "Score": 5, "DisplayOrder": 2 },
    { "Id": 0, "Label": "Khu dân cư", "Score": 3, "DisplayOrder": 3 }
  ],
  "UpdatedBy": 1,
  "UpdatedByUserName": "admin"
}
```

**Request Body (Tạo mới loại Range - Giá thuê):**
```json
{
  "Id": 0,
  "Name": "Giá thuê",
  "Description": "Khoảng giá thuê (triệu/tháng)",
  "CriteriaType": 2,
  "DisplayOrder": 4,
  "IsActive": true,
  "Options": [
    { "Id": 0, "Label": "Dưới 5 triệu", "MinValue": 0, "MaxValue": 5, "Score": 10, "DisplayOrder": 1 },
    { "Id": 0, "Label": "5-8 triệu", "MinValue": 5, "MaxValue": 8, "Score": 7, "DisplayOrder": 2 },
    { "Id": 0, "Label": "8-10 triệu", "MinValue": 8, "MaxValue": 10, "Score": 6, "DisplayOrder": 3 },
    { "Id": 0, "Label": "10-12 triệu", "MinValue": 10, "MaxValue": 12, "Score": 5, "DisplayOrder": 4 },
    { "Id": 0, "Label": "12-15 triệu", "MinValue": 12, "MaxValue": 15, "Score": 3, "DisplayOrder": 5 },
    { "Id": 0, "Label": "15-20 triệu", "MinValue": 15, "MaxValue": 20, "Score": 1, "DisplayOrder": 6 }
  ],
  "UpdatedBy": 1,
  "UpdatedByUserName": "admin"
}
```

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

### 1.4. Xóa tiêu chí

- **Endpoint**: `DELETE /api/PremiseScoring/DeleteCriteria/{id}`
- **Authorization**: Bearer Token

**Request Parameters:**
- `id` (int, path): ID tiêu chí cần xóa

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

### 1.5. Lấy tất cả tiêu chí đang active

- **Endpoint**: `GET /api/PremiseScoring/GetAllActiveCriteria`
- **Authorization**: Bearer Token

> [!TIP]
> **Dùng API này khi mở form tạo/chỉnh sửa mặt bằng.** Response trả về tất cả tiêu chí active kèm options để Front-end render form chấm điểm.

**Response:**
```json
[
  {
    "Id": 1,
    "Name": "Vị trí mặt bằng",
    "Description": "Đánh giá vị trí địa lý",
    "CriteriaType": 1,
    "DisplayOrder": 1,
    "IsActive": true,
    "Options": [
      { "Id": 1, "Label": "Mặt tiền đường lớn", "Score": 10, "DisplayOrder": 1 },
      { "Id": 2, "Label": "Hẻm xe hơi", "Score": 5, "DisplayOrder": 2 }
    ]
  },
  {
    "Id": 2,
    "Name": "Giá thuê",
    "CriteriaType": 2,
    "DisplayOrder": 2,
    "IsActive": true,
    "Options": [
      { "Id": 3, "Label": "Dưới 5 triệu", "MinValue": 0, "MaxValue": 5, "Score": 10, "DisplayOrder": 1 },
      { "Id": 4, "Label": "5-8 triệu", "MinValue": 5, "MaxValue": 8, "Score": 7, "DisplayOrder": 2 }
    ]
  }
]
```

---

## 2. Quản lý mặt bằng (Nhân viên khảo sát)

> [!IMPORTANT]
> **Luồng nhân viên:**
> 1. Gọi `GetAllActiveCriteria` để lấy tiêu chí → render form chấm điểm
> 2. Gọi `CreateOrUpdate` (Id=0) để tạo mặt bằng mới kèm liên hệ + điểm chấm
> 3. Hệ thống tự tính `TotalScore` từ điểm của từng tiêu chí
> 4. Khi khảo sát xong → gọi `ChangeStatus` chuyển sang `Evaluating`

### 2.1. Tìm kiếm mặt bằng

- **Endpoint**: `POST /api/Premise/Search`
- **Authorization**: Bearer Token

**Request Body:**
```json
{
  "Pagination": {
    "PageIndex": 1,
    "PageSize": 15
  },
  "Search": {
    "PredicateObject": {
      "Keyword": "HCM"
    }
  },
  "Sort": {
    "Predicate": "CreatedTime",
    "Reverse": true
  }
}
```

**Request Parameters:**
- `Keyword` (string): Tìm theo mã mặt bằng (`Code`) hoặc địa chỉ (`AddressDetail`)

**Response:**
```json
{
  "TotalRecord": 2,
  "Data": [
    {
      "Id": 1,
      "Code": "MB-HCM-001",
      "Status": 1,
      "StatusName": "Surveying",
      "AddressDetail": "123 Nguyễn Trãi, Q.1, HCM",
      "AgencyId": 5,
      "AgencyName": "Bưu cục Quận 1",
      "CityId": 24,
      "CityName": "TP. Hồ Chí Minh",
      "DistrictId": 100,
      "DistrictName": "Quận 1",
      "WardId": 1000,
      "WardName": "Phường Bến Nghé",
      "TotalScore": 42,
      "Description": "Mặt bằng mặt tiền đường lớn",
      "CreatedByUserName": "nhanvien01",
      "CreatedTime": "2026-03-01T06:00:00+07:00"
    }
  ]
}
```

### 2.2. Lấy chi tiết mặt bằng theo ID

- **Endpoint**: `GET /api/Premise/GetById/{id}`
- **Authorization**: Bearer Token

**Request Parameters:**
- `id` (int, path): ID mặt bằng

**Response:**
```json
{
  "Result": 1,
  "Message": "",
  "Id": 1,
  "Code": "MB-HCM-001",
  "Status": 1,
  "AgencyId": 5,
  "AgencyName": "Bưu cục Quận 1",
  "CityId": 24,
  "CityName": "TP. Hồ Chí Minh",
  "DistrictId": 100,
  "DistrictName": "Quận 1",
  "WardId": 1000,
  "WardName": "Phường Bến Nghé",
  "AddressDetail": "123 Nguyễn Trãi, Q.1, HCM",
  "Latitude": 10.762622,
  "Longitude": 106.660172,
  "GoogleMapUrl": "https://maps.google.com/...",
  "TotalScore": 42,
  "Description": "Mặt bằng mặt tiền đường lớn",
  "CreatedByUserName": "nhanvien01",
  "CreatedTime": "2026-03-01T06:00:00+07:00",
  "Financial": {
    "Id": 1,
    "AskingRent": 8000000,
    "NegotiatedRent": 7000000,
    "DepositMonths": 3,
    "PaymentPeriodMonths": 6,
    "FreeFitOutDays": 30,
    "AvailableFromDate": "2026-04-01",
    "CanProvideVatInvoice": true,
    "LegalNote": "Hợp đồng 3 năm"
  },
  "Contacts": [
    {
      "Id": 1,
      "FullName": "Nguyễn Văn A",
      "PhoneNumber": "0901234567",
      "Role": 1,
      "Note": "Chủ nhà chính"
    }
  ],
  "Scores": [
    {
      "Id": 1,
      "CriteriaId": 1,
      "CriteriaName": "Vị trí mặt bằng",
      "CriteriaType": 1,
      "SelectedOptionId": 1,
      "SelectedOptionLabel": "Mặt tiền đường lớn",
      "TextValue": null,
      "NumericValue": null,
      "Score": 10,
      "Note": null
    },
    {
      "Id": 2,
      "CriteriaId": 2,
      "CriteriaName": "Giá thuê",
      "CriteriaType": 2,
      "SelectedOptionId": 4,
      "SelectedOptionLabel": "5-8 triệu",
      "TextValue": null,
      "NumericValue": 7.5,
      "Score": 7,
      "Note": "Giá hợp lý cho khu vực"
    }
  ],
  "Medias": [
    {
      "Id": 1,
      "MediaId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "MediaType": 1,
      "Url": "https://media.example.com/images/Premise/2026/3/1/front.jpg",
      "DisplayOrder": 1
    },
    {
      "Id": 2,
      "MediaId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "MediaType": 2,
      "Url": "https://media.example.com/images/Premise/2026/3/1/inside.jpg",
      "DisplayOrder": 2
    }
  ]
}
```

### 2.3. Tạo mới / cập nhật mặt bằng

- **Endpoint**: `POST /api/Premise/CreateOrUpdate`
- **Authorization**: Bearer Token

> [!IMPORTANT]
> - `Id = 0`: **Tạo mới** (Status tự động = `Surveying`). `Id > 0`: **Cập nhật**.
> - `CityId`, `DistrictId`, `WardId`: FK tới bảng Location theo cấp Tỉnh/Quận/Phường.
> - `Contacts`: Danh sách liên hệ. `Id = 0` tạo mới, `Id > 0` cập nhật. Liên hệ cũ không có trong danh sách sẽ bị soft delete.
> - `Scores`: Chấm điểm theo tiêu chí. Hệ thống tự tính điểm:
>   - `CriteriaType = 1` (Option): Gửi `SelectedOptionId`, hệ thống lấy điểm từ option.
>   - `CriteriaType = 2` (Range): Gửi `NumericValue`, hệ thống tự match khoảng giá trị và tính điểm.
> - `TotalScore` được tự động tính = tổng điểm tất cả tiêu chí.
> - `Financial` (optional): Thông tin tài chính. Nếu gửi kèm sẽ tự tạo mới hoặc cập nhật financial cho mặt bằng.
> - Upload ảnh: Sử dụng `multipart/form-data`. Điền danh sách file vào `NewMediaFiles` và loại ảnh tương ứng vào `NewMediaTypes`. Để xóa ảnh cũ khi update, truyền danh sách `DeleteMediaIds`.

**Request Format:** `multipart/form-data`

**Form Data Fields (Tạo mới):**
```
Id: 0
Code: MB-HCM-001
AgencyId: 5
CityId: 24
DistrictId: 100
WardId: 1000
AddressDetail: 123 Nguyễn Trãi, Q.1, HCM
Latitude: 10.762622
Longitude: 106.660172
GoogleMapUrl: https://maps.google.com/...
Description: Mặt bằng mặt tiền đường lớn

# Liên hệ
Contacts[0].Id: 0
Contacts[0].FullName: Nguyễn Văn A
Contacts[0].PhoneNumber: 0901234567
Contacts[0].Role: 1
Contacts[0].Note: Chủ nhà chính

Contacts[1].Id: 0
Contacts[1].FullName: Trần Thị B
Contacts[1].PhoneNumber: 0912345678
Contacts[1].Role: 2
Contacts[1].Note: Môi giới

# Điểm chấm
Scores[0].CriteriaId: 1
Scores[0].SelectedOptionId: 1
Scores[0].Note: Vị trí rất tốt

Scores[1].CriteriaId: 2
Scores[1].NumericValue: 7.5
Scores[1].Note: Giá hợp lý

# Thông tin tài chính (optional)
Financial.AskingRent: 8000000
Financial.NegotiatedRent: 7000000
Financial.DepositMonths: 3
Financial.PaymentPeriodMonths: 6
Financial.FreeFitOutDays: 30
Financial.AvailableFromDate: 2026-04-01
Financial.CanProvideVatInvoice: true
Financial.LegalNote: Hợp đồng 3 năm

# Ảnh mặt bằng (Upload)
NewMediaFiles: (binary data)
NewMediaTypes: 1
NewMediaFiles: (binary data)
NewMediaTypes: 2

# Trạng thái
UpdatedBy: 10
UpdatedByUserName: nhanvien01
```

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

### 2.4. Xóa mặt bằng

- **Endpoint**: `DELETE /api/Premise/Delete/{id}`
- **Authorization**: Bearer Token

**Request Parameters:**
- `id` (int, path): ID mặt bằng cần xóa

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

### 2.5. Xóa ảnh mặt bằng

- **Endpoint**: `DELETE /api/Premise/DeleteMedia/{id}`
- **Authorization**: Bearer Token

**Request Parameters:**
- `id` (int, path): ID của PremiseMedia cần xóa (Lấy từ `Medias[].Id` trong danh sách trả về của API GetById)

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

### 2.6. Chuyển trạng thái mặt bằng

- **Endpoint**: `POST /api/Premise/ChangeStatus`
- **Authorization**: Bearer Token

> [!IMPORTANT]
> **Luồng trạng thái hợp lệ:**
> ```
> Surveying(1) → Evaluating(2) → Negotiating(3) → Approved(4) → Rented(5)
>                                    ↘ Rejected(6)
>                                         ↘ Closed(7)
> ```

**Request Body:**
```json
{
  "Id": 1,
  "Status": 2,
  "UpdatedBy": 10,
  "UpdatedByUserName": "nhanvien01"
}
```

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```

---

## 3. Duyệt & Đàm phán (Quản lý)

> [!NOTE]
> **Luồng quản lý:**
> 1. Xem danh sách mặt bằng (`Search`) → lọc theo trạng thái `Evaluating`
> 2. Xem chi tiết (`GetById`) → kiểm tra thông tin, điểm chấm
> 3. Duyệt (`ChangeStatus` → `Negotiating`) hoặc từ chối (`ChangeStatus` → `Rejected`)
> 4. Cập nhật thông tin tài chính qua `CreateOrUpdate` (truyền kèm `Financial`) hoặc `UpdateFinancial` riêng lẻ
> 5. Hoàn tất (`ChangeStatus` → `Approved` → `Rented`)

### 3.1. Cập nhật thông tin tài chính

- **Endpoint**: `POST /api/Premise/UpdateFinancial`
- **Authorization**: Bearer Token

> [!NOTE]
> API này tạo mới hoặc cập nhật thông tin tài chính cho mặt bằng.
> Nếu mặt bằng chưa có Financial → tạo mới. Nếu đã có → cập nhật.

**Request Body:**
```json
{
  "Id": 0,
  "PremiseId": 1,
  "AskingRent": 8000000,
  "NegotiatedRent": 7000000,
  "DepositMonths": 3,
  "PaymentPeriodMonths": 6,
  "FreeFitOutDays": 30,
  "AvailableFromDate": "2026-04-01",
  "CanProvideVatInvoice": true,
  "LegalNote": "Hợp đồng 3 năm, gia hạn tự động",
  "UpdatedBy": 1,
  "UpdatedByUserName": "admin"
}
```

**Request Parameters:**
- `PremiseId` (int, required): ID mặt bằng
- `AskingRent` (decimal?): Giá thuê yêu cầu
- `NegotiatedRent` (decimal?): Giá thuê thỏa thuận
- `DepositMonths` (int?): Số tháng đặt cọc
- `PaymentPeriodMonths` (int?): Kỳ thanh toán (tháng)
- `FreeFitOutDays` (int?): Số ngày miễn phí setup
- `AvailableFromDate` (datetime?): Ngày có thể nhận mặt bằng
- `CanProvideVatInvoice` (bool): Có xuất hóa đơn VAT không
- `LegalNote` (string?): Ghi chú pháp lý

**Response:**
```json
{
  "Result": 1,
  "Message": ""
}
```
