# EPowerMap API Document

**Base URL:** `http://{host}:{port}/EPowerMap`

## Authentication

All endpoints require the `appId` query parameter instead of a Bearer token.

| Parameter | Type   | Required | Value |
|-----------|--------|----------|-------|
| `appId`   | string | Yes      | `3ea29c51ff5688c12d2b4bce16a9146be460f130` |

**Example:** `GET /EPowerMap/Accessory?appId=3ea29c51ff5688c12d2b4bce16a9146be460f130`

If `appId` is missing or invalid, the API returns `400` with `"Invalid or missing appId."`.

---

## Pagination & Search

All **GetAll** endpoints support the following query parameters:

| Parameter  | Type   | Default | Description                          |
|------------|--------|---------|--------------------------------------|
| `page`     | int    | 1       | Page number (1-based)                |
| `pageSize` | int    | 10      | Items per page (max 100)             |
| `filter`   | string | null    | Search keyword (name, note, code)    |

**Paginated Response Format:**

```json
{
  "items": [],
  "totalCount": 100,
  "page": 1,
  "pageSize": 10,
  "totalPages": 10,
  "hasPreviousPage": false,
  "hasNextPage": true
}
```

---

## Error Response Format

All errors return HTTP `400` with:

```json
{
  "error": "Error message here",
  "type": "System.Exception",
  "stack": "..."
}
```

---

## 1. Accessory

### GET /EPowerMap/Accessory

Get all accessories with pagination and search.

```
GET /EPowerMap/Accessory?appId={appId}&page=1&pageSize=10&filter=Insulator
```

**Response:**

```json
{
  "items": [
    {
      "accessoryId": 5,
      "accessoryName": "Insulator",
      "note": "Insulator",
      "iconHref": "",
      "iconScale": 1.0,
      "altitude": 0.0,
      "isActive": true
    }
  ],
  "totalCount": 11,
  "page": 1,
  "pageSize": 10,
  "totalPages": 2,
  "hasPreviousPage": false,
  "hasNextPage": true
}
```

### GET /EPowerMap/Accessory/{id}

Get a single accessory by ID.

```
GET /EPowerMap/Accessory/5?appId={appId}
```

**Response:**

```json
{
  "accessoryId": 5,
  "accessoryName": "Insulator",
  "note": "Insulator",
  "iconHref": "",
  "iconScale": 1.0,
  "altitude": 0.0,
  "isActive": true
}
```

### POST /EPowerMap/Accessory

Create a new accessory.

```
POST /EPowerMap/Accessory?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "accessoryName": "New Accessory",
  "note": "Description",
  "iconHref": "/icons/new.png",
  "iconScale": 1.0,
  "altitude": 0.0,
  "isActive": true
}
```

**Response:** Returns the created accessory object.

### PUT /EPowerMap/Accessory

Update an existing accessory.

```
PUT /EPowerMap/Accessory?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "accessoryId": 5,
  "accessoryName": "Updated Name",
  "note": "Updated note",
  "iconHref": "/icons/updated.png",
  "iconScale": 1.5,
  "altitude": 0.0,
  "isActive": true
}
```

**Response:** Returns the updated accessory object.

### DELETE /EPowerMap/Accessory

Delete one or multiple accessories.

```
DELETE /EPowerMap/Accessory?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "ids": [5, 6, 7]
}
```

**Response:** `true`

---

## 2. Package

### GET /EPowerMap/Package

Get all packages with pagination.

```
GET /EPowerMap/Package?appId={appId}&page=1&pageSize=10
```

**Response:**

```json
{
  "items": [
    {
      "packageId": 1,
      "packageName": "3-Phase MV Transformer Package",
      "isActive": true,
      "details": []
    }
  ],
  "totalCount": 2,
  "page": 1,
  "pageSize": 10,
  "totalPages": 1,
  "hasPreviousPage": false,
  "hasNextPage": false
}
```

### GET /EPowerMap/Package/{id}

Get a single package with its detail items (accessories + quantities).

```
GET /EPowerMap/Package/1?appId={appId}
```

**Response:**

```json
{
  "packageId": 1,
  "packageName": "3-Phase MV Transformer Package",
  "isActive": true,
  "details": [
    {
      "packageDetailId": 1,
      "packageId": 1,
      "accessoryId": 2,
      "accessoryName": "Terminal lug",
      "qty": 40,
      "isActive": true
    },
    {
      "packageDetailId": 2,
      "packageId": 1,
      "accessoryId": 6,
      "accessoryName": "Fuse Cutout",
      "qty": 3,
      "isActive": true
    }
  ]
}
```

### POST /EPowerMap/Package

Create a new package with details.

```
POST /EPowerMap/Package?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "packageName": "New Package",
  "isActive": true,
  "details": [
    { "accessoryId": 2, "qty": 10, "isActive": true },
    { "accessoryId": 5, "qty": 6, "isActive": true }
  ]
}
```

**Response:** Returns the created package with details (including generated IDs and accessory names).

### PUT /EPowerMap/Package

Update a package. **Replaces all details** with the provided list.

```
PUT /EPowerMap/Package?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "packageId": 1,
  "packageName": "Updated Package Name",
  "isActive": true,
  "details": [
    { "accessoryId": 2, "qty": 20, "isActive": true },
    { "accessoryId": 6, "qty": 5, "isActive": true },
    { "accessoryId": 14, "qty": 3, "isActive": true }
  ]
}
```

**Response:** Returns the updated package with details.

### DELETE /EPowerMap/Package

Delete one or multiple packages (also removes their details).

```
DELETE /EPowerMap/Package?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "ids": [1, 2]
}
```

**Response:** `true`

---

## 3. Place

### GET /EPowerMap/Place

Get all places with pagination. Includes joined area code, pole code, and style name.

```
GET /EPowerMap/Place?appId={appId}&page=1&pageSize=10&filter=A01
```

**Response:**

```json
{
  "items": [
    {
      "placeId": 1,
      "refId": 1,
      "objectId": 1,
      "styleId": 1,
      "styleName": "9m Pole",
      "areaCode": "A01",
      "poleCode": "A001",
      "latitude": 11.576178,
      "longitude": 104.920272,
      "isActive": true,
      "isOwn": true,
      "rowDate": "2026-04-08T00:00:00",
      "details": null
    }
  ],
  "totalCount": 1015,
  "page": 1,
  "pageSize": 10,
  "totalPages": 102,
  "hasPreviousPage": false,
  "hasNextPage": true
}
```

### GET /EPowerMap/Place/{id}

Get a single place with its accessories (place details).

```
GET /EPowerMap/Place/2?appId={appId}
```

**Response:**

```json
{
  "placeId": 2,
  "refId": 2,
  "objectId": 2,
  "styleId": 3,
  "styleName": "14m Pole",
  "areaCode": "A01",
  "poleCode": "A002",
  "latitude": 11.575653,
  "longitude": 104.920259,
  "isActive": true,
  "isOwn": true,
  "rowDate": "2026-04-08T00:00:00",
  "details": [
    {
      "placeDetailId": 1,
      "placeId": 2,
      "accessoryId": 5,
      "accessoryName": "Insulator",
      "qty": 2,
      "isActive": true,
      "rowDate": "2026-04-08T00:00:00"
    }
  ]
}
```

### POST /EPowerMap/Place

Create a new place.

```
POST /EPowerMap/Place?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "refId": 1,
  "objectId": 100,
  "styleId": 1,
  "latitude": 11.570000,
  "longitude": 104.920000,
  "isActive": true,
  "isOwn": true
}
```

**Response:** Returns the created place with joined area/pole/style info.

### PUT /EPowerMap/Place

Update an existing place.

```
PUT /EPowerMap/Place?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "placeId": 2,
  "refId": 1,
  "objectId": 2,
  "styleId": 3,
  "latitude": 11.575700,
  "longitude": 104.920300,
  "isActive": true,
  "isOwn": false
}
```

**Response:** Returns the updated place.

### DELETE /EPowerMap/Place

Delete one or multiple places (also removes their place details).

```
DELETE /EPowerMap/Place?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "ids": [1, 2, 3]
}
```

**Response:** `true`

---

## 4. Style (Pole Style)

### GET /EPowerMap/Style

Get all styles with pagination.

```
GET /EPowerMap/Style?appId={appId}&page=1&pageSize=10&filter=Pole
```

**Response:**

```json
{
  "items": [
    {
      "styleId": 1,
      "styleName": "9m Pole",
      "lineColor": "#FF0000",
      "lineWidth": 2.0,
      "iconHref": "/icons/pole9m.png",
      "iconScale": 1.0,
      "altitude": 0.0,
      "isActive": true,
      "labelColor": "#000000",
      "labelScale": 1.0,
      "labelOpacity": 100,
      "note": "9m Pole"
    }
  ],
  "totalCount": 5,
  "page": 1,
  "pageSize": 10,
  "totalPages": 1,
  "hasPreviousPage": false,
  "hasNextPage": false
}
```

### GET /EPowerMap/Style/{id}

```
GET /EPowerMap/Style/1?appId={appId}
```

**Response:** Single style object (same fields as above).

### POST /EPowerMap/Style

```
POST /EPowerMap/Style?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "styleName": "New Style",
  "lineColor": "#00FF00",
  "lineWidth": 1.5,
  "iconHref": "/icons/new.png",
  "iconScale": 1.0,
  "altitude": 0.0,
  "isActive": true,
  "labelColor": "#000000",
  "labelScale": 1.0,
  "labelOpacity": 100,
  "note": "Description"
}
```

**Response:** Returns the created style.

### PUT /EPowerMap/Style

```
PUT /EPowerMap/Style?appId={appId}
Content-Type: application/json
```

**Request Body:** Same as POST but include `styleId`.

### DELETE /EPowerMap/Style

```
DELETE /EPowerMap/Style?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "ids": [1, 2]
}
```

**Response:** `true`

---

## 5. Transformer

> Note: Transformer has no **Add (POST)** endpoint.

### GET /EPowerMap/Transformer

Get all transformers with pagination. Includes joined brand name and pole code.

```
GET /EPowerMap/Transformer?appId={appId}&page=1&pageSize=10&filter=400kVA
```

**Response:**

```json
{
  "items": [
    {
      "transformerId": 1,
      "transformerCode": "TR-001",
      "isActive": true,
      "capacityId": 3,
      "startDate": "2024-01-01T00:00:00",
      "endDate": "2030-12-31T00:00:00",
      "isInused": true,
      "phaseId": 1,
      "note": "Full Light, 400kVA, 3P",
      "highVoltageId": 1,
      "lowVoltageId": 1,
      "transformerPositionId": 1,
      "transformerTypeId": 1,
      "isProperty": true,
      "transformerBrandId": 1,
      "transformerBrandName": "ABB",
      "poleId": 2,
      "poleCode": "A002",
      "rowDate": "2026-04-08T00:00:00"
    }
  ],
  "totalCount": 88,
  "page": 1,
  "pageSize": 10,
  "totalPages": 9,
  "hasPreviousPage": false,
  "hasNextPage": true
}
```

### GET /EPowerMap/Transformer/{id}

```
GET /EPowerMap/Transformer/1?appId={appId}
```

**Response:** Single transformer object (same fields as above).

### PUT /EPowerMap/Transformer

```
PUT /EPowerMap/Transformer?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "transformerId": 1,
  "transformerCode": "TR-001",
  "isActive": true,
  "capacityId": 3,
  "startDate": "2024-01-01T00:00:00",
  "endDate": "2030-12-31T00:00:00",
  "isInused": true,
  "phaseId": 1,
  "note": "Updated note",
  "highVoltageId": 1,
  "lowVoltageId": 1,
  "transformerPositionId": 1,
  "transformerTypeId": 1,
  "isProperty": true,
  "transformerBrandId": 1,
  "poleId": 2
}
```

**Response:** Returns the updated transformer.

### DELETE /EPowerMap/Transformer

```
DELETE /EPowerMap/Transformer?appId={appId}
Content-Type: application/json
```

**Request Body:**

```json
{
  "ids": [1, 2]
}
```

**Response:** `true`

---

## 6. SyncEPowerMap

Bulk sync all map data between the mobile app and the server.

### POST /EPowerMap/Sync?type=export

Export all data from the database.

```
POST /EPowerMap/Sync?appId={appId}&type=export
Content-Type: application/json

{}
```

**Response:**

```json
{
  "style": [
    { "id": 1, "name": "9m Pole", "note": "9m Pole" }
  ],
  "accessory": [
    { "id": 1, "name": "Aluminium Pin Connector", "note": "Aluminium Pin Connector", "is_active": true, "is_new": false }
  ],
  "package": [
    { "id": 1, "name": "3-Phase MV Transformer Package", "is_active": true, "is_new": false }
  ],
  "packageDetail": [
    { "id": 1, "package_id": 1, "accessory_id": 2, "qty": 40.0, "is_active": true }
  ],
  "place": [
    { "id": 1, "ref_id": 1, "object_id": 1, "style_id": 1, "area": "A01", "pole": "A001", "latitude": 11.576178, "longitude": 104.920272, "is_own": true, "collected_date": null, "is_collected": false }
  ],
  "placeDetail": [
    { "id": 1, "place_id": 2, "accessory_id": 5, "qty": 2.0, "is_active": true }
  ],
  "transformer": [
    { "id": 1, "place_id": 2, "name": "Transformer 1", "note": "Full Light, 400kVA, 3P", "is_active": true, "is_new": false }
  ]
}
```

### POST /EPowerMap/Sync?type=import

Import data into the database. Upserts all records (inserts new, updates existing by ID).

```
POST /EPowerMap/Sync?appId={appId}&type=import
Content-Type: application/json
```

**Request Body:** Same structure as the export response above.

```json
{
  "style": [
    { "id": 1, "name": "9m Pole", "note": "9m Pole" }
  ],
  "accessory": [
    { "id": 1, "name": "Aluminium Pin Connector", "note": "", "is_active": true, "is_new": false }
  ],
  "package": [],
  "packageDetail": [],
  "place": [
    { "id": 1, "ref_id": 1, "object_id": 1, "style_id": 1, "area": "A01", "pole": "A001", "latitude": 11.576178, "longitude": 104.920272, "is_own": true, "collected_date": null, "is_collected": false }
  ],
  "placeDetail": [
    { "id": 1, "place_id": 2, "accessory_id": 5, "qty": 2.0, "is_active": true }
  ],
  "transformer": [
    { "id": 1, "place_id": 2, "name": "Transformer 1", "note": "Full Light, 400kVA, 3P", "is_active": true, "is_new": false }
  ]
}
```

**Response:** Returns the same model back after successful import.

---

## Quick Reference

| Entity      | GET All              | GET by ID                  | POST (Add)           | PUT (Update)         | DELETE               |
|-------------|----------------------|----------------------------|----------------------|----------------------|----------------------|
| Accessory   | `GET /Accessory`     | `GET /Accessory/{id}`      | `POST /Accessory`    | `PUT /Accessory`     | `DELETE /Accessory`  |
| Package     | `GET /Package`       | `GET /Package/{id}`        | `POST /Package`      | `PUT /Package`       | `DELETE /Package`    |
| Place       | `GET /Place`         | `GET /Place/{id}`          | `POST /Place`        | `PUT /Place`         | `DELETE /Place`      |
| Style       | `GET /Style`         | `GET /Style/{id}`          | `POST /Style`        | `PUT /Style`         | `DELETE /Style`      |
| Transformer | `GET /Transformer`   | `GET /Transformer/{id}`    | -                    | `PUT /Transformer`   | `DELETE /Transformer`|
| Sync        | -                    | -                          | `POST /Sync?type=export` | - | `POST /Sync?type=import` |

All endpoints are prefixed with `/EPowerMap` and require `?appId={appId}` in the query string.
