---
# System prepended metadata

title: CRM Batubara Niaga
tags: [CRM BBN]

---

---
title: CRM Batubara Niaga

---

CRM Batubara Niaga - _Contract API BBN_
--- 



## Base Response
### GET LIST DATA

```http=
GET /v1/{resource}
Authorization: Bearer <Token>
Accept: application/json
```

__Params__
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for |
| sort | {field_name}+{ASC/DESC} | sort by |

> Example: `page=1&limit=10&size=10&search=a&sort=created_at+desc`

__respons__
```json=
{
    "data": [
        {
            "key1": "value1",
            "key2": "value2"
        },
        {
            "key1": "value1",
            "key2": "value2"
        }
    ],
    "metadata" : {
        "total_data" : 8,
        "total_page" : 4,
        "page" : 0,
        "limit" : 4
    }
}
```

### ERROR RESPONSE
```json=
{
  "type": "https://httpstatuses.io/400",
  "title": "Bad Request",
  "status": 400,
  "detail": "Key: 'RegisterRequest.Phone' Error:Field validation for 'Phone' failed on the 'required' tag",
  "instance": "/v1/people",
  "errors": [
    {
      "field": "Phone",
      "message": "Key: 'RegisterRequest.Phone' Error:Field validation for 'Phone' failed on the 'required' tag",
      "constraint": "required",
      "value": ""
    }
  ],
  "time": "2025-05-07T09:00:39.491699+07:00"
}
```

## Module Pengaturan

| Module | Feature | Description |
| ------ | ------ |  ------ |
| Pengaturan | Pengguna |  |
| Pengaturan | Role & Access |  |

### Enum Group
| Name | Label |
| ------ | ------ |
| internal | internal |
| supplier | Sumber Tambang |
| trader | Trader |
| transporter | Transpotir |
| cbf | Partner CBF |
| isp | Partner ISP |

### Privilege
#### Resource & Group Privilege

| Group           | Resource                 | Privilege                       |
|-----------------|--------------------------|---------------------------------|
| Pengaturan      | role-access              | create, read, update, delete    |
| Pengaturan      | users                    | create, read, update, activation|
| Master Data     | customer                 | create, read, update, delete    |
| Master Data     | partner                  | create, read, update, delete    |
| Master Data     | location                 | create, read, update, delete    |
| Master Data     | power-plant              | create, read, update, delete    |
| Master Data     | transportation-mode      | create, read, update, delete    |
| Master Data     | vessel                   | create, read, update, delete    |
| Referensi Data  | exchange-rate            | create, read, update            |
| Referensi Data  | fuel-price               | create, read, update            |
| Kontrak | pjbb-customers | create, read, update, delete, review-1, review-2 |
| Kontrak| pjbb-partners | create, read, update, delete, review-1, review-2 |
| Kontrak | pjab-partners | create, read, update, delete, review-1, review-2 |
| Kontrak | cbf-partners | create, read, update, delete, review-1, review-2 |
| Kontrak | isp-partners | create, read, update, delete, review-1, review-2 |
| Perencanaan Pengiriman | shipping-order |create, read, update, delete, review-1, review-2 |
| Operasi Pengiriman | shipping-operation |create, read, update, delete, review-1, review-2, review-3 |


__Seed Data Resource__
```sql=
--seed data resource
INSERT INTO public.resources ("group", "name", description)
VALUES
('Pengaturan', 'role-access', 'Peran dan Hak Akses'),
('Pengaturan', 'users', 'Pengguna'),
('Master Data', 'customer', 'Pelanggan'),
('Master Data', 'partner', 'Mitra'),
('Master Data', 'location', 'Lokasi'),
('Master Data', 'power-plant', 'Pembangkit'),
('Master Data', 'transportation-mode', 'Moda'),
('Master Data', 'vessel', 'Kapal / Vessel'),
('Referensi Data', 'exchange-rate', 'Exchange Rate'),
('Referensi Data', 'fuel-price', 'Harga BBM')
```

__Seed Data Privileges__
```sql=
--seed data privileges
WITH allowed_actions AS (
    -- Define resources and allowed actions
    SELECT 'users' AS resource_name, unnest(ARRAY['create', 'update', 'read', 'activation']) AS action_name
    UNION ALL
    SELECT 'role-access', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'customer', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'partner', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'location', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'power-plant', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'transportation-mode', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'vessel', unnest(ARRAY['create', 'update', 'read', 'delete'])
    UNION ALL
    SELECT 'exchange-rate', unnest(ARRAY['create', 'update', 'read'])
    UNION ALL
    SELECT 'fuel-price', unnest(ARRAY['create', 'update', 'read'])
    UNION ALL
)
INSERT INTO public."privileges" (resource_id, "name", description)
SELECT
    r.id AS resource_id,
    action.name AS action_name,
    action.description_prefix || COALESCE(r.description, '') AS description
FROM
    public.resources r
JOIN allowed_actions aa
    ON r.name = aa.resource_name
JOIN (
    VALUES
        ('Akses membuat data ', 'create'),
        ('Akses mengubah data ', 'update'),
        ('Akses melihat data ', 'read'),
        ('Akses menghapus data ', 'delete'),
        ('Akses mengaktifkan dan menonaktifkan data ', 'activation'),
        ('Akses review tahap 1 data ', 'review-1'),
        ('Akses review tahap 2 data ', 'review-2'),
        ('Akses review tahap 3 data ', 'review-3')
) AS action(description_prefix, name)
    ON aa.action_name = action.name;
```
 

#### Enum Privilage
| Name |
| ------ |
| create |
| update |
| delete |
| read |
| activation |
| review-1 |
| review-2 |
| review-3 |

#### GET Privilege
```http=
GET /v1/auth/privileges/{resource-id}
Authorization: Bearer <Token>
Accept: application/json
```
__response__
```json=
{
  "group" : "Master Data",
  "resource" : "Mitra",
  "description" : "Manajemen Mitra"
  "privileges" : [
    {
      "name" : "create",
      "description" : "Membuat Kontrak Baru"
    },
    {
      "name" : "review-1",
      "description" : "Review Draf Kontrak"
    }
  ]
}
```

#### GET ALL Privilege
```http=
GET /v1/auth/privileges?page=0&limit=4&sort-by={field-name}&sort-direction={ASC|DESC}
Authorization: Bearer <Token>
Accept: application/json
```
__response__
```json=
{
  "data" : [
    {
      "id" : "resource-id-1", 
      "group" : "Master Data",
      "resource" : "Mitra",
      "description" : "Manajemen Mitra",
      "privileges" : [
        {
          "name" : "create",
          "description" : "Membuat Kontrak Baru"
        },
        {
          "name" : "review-1",
          "description" : "Review Draf Kontrak"
        }
      ]
    },
    {
      "id" : "resource-id-2",
      "group" : "Master Data",
      "resource" : "Kapal",
      "description" : "Manajemen Kapal",
      "privileges" : [
        {
          "name" : "create",
          "description" : "Membuat Kontrak Baru"
        },
        {
          "name" : "review-1",
          "description" : "Review Draf Kontrak"
        }
      ]
    },
    {
      "id" : "resource-id-3",
      "group" : "Kontrak",
      "resource" : "contract-management",
      "description" : "Manajemen Kontrak"
      "privileges" : [
        {
          "name" : "create",
          "description" : "Membuat Kontrak Baru"
        },
        {
          "name" : "review-1",
          "description" : "Review Draf Kontrak"
        }
      ]
    },
    {
      "id" : "resource-id-4",
      "group" : "Kontrak",
      "resource" : "xxx-management",
      "description" : "Manage ",
      "privileges" : [
        {
          "name" : "create",
          "description" : "Membuat Kontrak Baru"
        },
        {
          "name" : "review-1",
          "description" : "Review Draf Kontrak"
        }
      ]
    }
  ],
  "metadata" : {
    "total_data" : 8,
    "total_page" : 4,
    "page" : 0,
    "limit" : 4
  }
}

```

### Pengguna / Users

#### CREATE New User
> Business Rule:
> - Generate default password for user created __BBN2025__
> - Validation choosen role only valid if the role associate with group (check role)
> - Validation choosen partner_id only valid if the partner associate with group
> - user email are unique
> - partner_id mandatory when group is not __internal__
> - field group using enum group

```http=
POST /v1/auth/users
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{	
    "name" : "Hendro Susilo",
    "email" : "alohdr@example.com",
    "phone" : "628123456789",
    "group" : "internal",
    "partnerId" : "partnerId",
    "roleId" : "roleId", 
}
```

#### Update User
```http=
PUT /v1/auth/users/{resource_id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{	
    "name" : "Hendro Susilo",
    "email" : "alohdr@example.com",
    "phone" : "628123456789",
    "group" : "transporter",
    "partnerId" : "partnerId", // mandatory when group != internal
    "roleId" : "roleId", 
}
```

#### GET ALL User
```http=
GET /v1/auth/users
Authorization: Bearer <Token>
Accept: application/json
```
__Params__
Table params
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for |
| sort | {field_name}+{ASC/DESC} | sort by |
| group | varchar | filter for group |
| status | true / false | filter for status (active / inactive) |

 __response__
```json=
{
    {
      "id" : "user-id",
      "name" : "Hendro Susila",
      "email" : "alohdr@example.com",
      "phone" : "628123456789",
      "active" : true, //user status
      "group" : "transporter",
      "partner" : {
        "id": "partner-id",
        "name": "Pelayaran Bahtera Adiguna"
      },
      "roles" : [
        {
          "id" : "role-id",
          "name" : "VP_TEST",
          "formalName" : "Vice President Test",
          "start_date" : "2024-01-01",
          "validUntil" : null,
          "temporary" : false
        },
        {
          "id" : "role-id",
          "name" : "VP_DEVELOPMENT",
          "formalName" : "Vice President Development",
          "startDate" : "2024-01-01",
          "validUntil" : "2024-05-30",
          "temporary" : true
        }
      ]
    },
    "metadata" : {
    "total_data" : 8,
    "total_page" : 4,
    "page" : 0,
    "limit" : 4
  }
}
```

```java=
public static void main(String[] args) {
    
}
```

```go=
import "fmt"

// ini comment
func main() {
    fmt.Println("Test")
}
```

#### GET User
```http=
GET /v1/auth/users/{user-id}
Authorization: Bearer <Token>
Accept: application/json
```
__response__
```json=
{
  "id" : "user-id",
  "name" : "Hendro Susila",
  "email" : "alohdr@example.com",
  "phone" : "628123456789",
  "active" : true,
  "group" : "transporter",
  "partner" : {
    "id": "partner-id",
    "name": "Pelayaran Bahtera Adiguna"
  },
  "roles" : [
    {
      "id" : "role-id",
      "name" : "VP_TEST",
      "formalName" : "Vice President Test",
      "startDate" : "2024-01-01",
      "validUntil" : null,
      "temporary" : false
    },
    {
      "id" : "role-id",
      "name" : "VP_DEVELOPMENT",
      "formalName" : "Vice President Development",
      "startDate" : "2024-01-01",
      "validUntil" : "2024-05-30",
      "temporary" : true
    }
  ]
}
```

#### Assign Additional Role
```http=
PATCH /v1/users/{user-id}/roles
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
    "name" : "DIRECTOR_OF_FINANCE",
    "startDate" : "2025-06-18",
    "validUntil" : "2025-09-17"
}
```
#### Activate/Deactivate User
```http
POST /v1/users/{user-id}/status
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
    "active" : true
}
```

### Role Management
#### CREATE new Role
> Business Rule:
> Validation unique combination for name and group

```http=
POST /api/v1/auth/roles
Authorization: Bearer <Token>
Content-Type: application/json
```

```json=
{
  "name" : "DIRECTOR_OF_FINANCE",
  "group" : "bbn",
  "formalName" : "Direktur Finance",
  "permissions" : [
    {
      "resource": "mitra",
      "group" : "Master Data",
      "privileges" : {
        "create" : true,
        "update" : true,
        "delete" : false,
        "approval" : false
      }
    }
  ]
}
```
#### GET Roles
```http=
GET /api/v1/auth/roles?page={page-number}&limit={limit-number}&sort-by={field-name}&sort-dir={ASC|DESC}
Authorization: Bearer <Token>
Accept: application/json
```

__Params__
params header
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for |
| sort | {field_name}+{ASC/DESC} | sort by |
| group | varchar | filter for group |

__response__
```json=
{
"data": [
      {
        "id": "role-id",
        "name" : "DIRECTOR_OF_FINANCE",
        "formal_name" : "Direktur Finance",
        "group" : {
          "id": "group-id",
          "name" : "BAG",
          "isInternal" : true
        },
        "partner" : {
          "id": "partner-id",
          "name" : "partner Name"
        },
        "permissions" : [{
          "resource": "mitra",
          "group" : "Master Data",
          "privileges" : {
            "create" : true,
            "update" : true,
            "delete" : false,
            "approval" : false
          }
        }]
      }
    ],
    "metadata" : {
        "total_data" : 8,
        "total_page" : 4,
        "page" : 0,
        "limit" : 4
    }
}
```

#### GET Role

```http
GET /api/v1/auth/roles/{role-id}
Authorization: Bearer <Token>
Accept: application/json
```
__response__
```json=
{
  "id": "role-id",
  "name" : "DIRECTOR_OF_FINANCE",
  "formalName" : "Direktur Finance",
  "group" : "transporter",
  "partner" : {
    "id": "partner-id",
    "name" : "partner Name"
  },
  "permissions" : [{
    "resource": "mitra",
    "group" : "Master Data",
    "privileges" : {
      "create" : true,
      "update" : true,
      "delete" : false,
      "approval" : false
    }
  }]
}
```

#### UPDATE Role

```http=
PUT /v1/auth/roles
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=
{
  "name" : "DIRECTOR_OF_FINANCE",
  "group" : "bbn",
  "formal_name" : "Direktur Finance",
  "permissions" : [
    {
      "resource": "mitra",
      "group" : "Master Data",
      "privileges" : {
        "create" : true,
        "update" : true,
        "delete" : false,
        "approval" : false
      }
    }
  ]
}
```

#### DELETE Roles
> Business Rule:
> Validation attempt to delete role that already assign will be failed

```http=
DELETE /api/v1/auth/roles/{role-id}
Authorization: Bearer <Token>
```

### Profile Management
#### Retrieve User Profile (Me Endpoint)
> Retrieve current active logged-in user

```http=
GET /v1/profiles/me
Authorization: Bearer <Token>
Accept: application/json
```
__response__
```json=
{
  "id" : "user-id",
  "name" : "Hendro Susila",
  "email" : "alohdr@example.com",
  "phone" : "628123456789",
  "group" : "bbn",
  "partner" : {
    "id": "partner-ID",
    "name": "Pelayaran Bahtera Adiguna"
  },
  "assigned_roles" : [
    {
      "id" : "role-id-0",
      "name" : "VP_TEST",
      "formalName" : "Vice President Test",
      "startDate" : "2024-01-01",
      "validUntil" : null,
      "temporary" : false,
      "permissions" : [{
        "resource": "mitra",
        "group" : "Master Data",
        "privileges" : {
          "create" : true,
          "update" : true,
          "delete" : false,
          "approval" : false
        }
      }]
    },
    {
      "id" : "role-id-1",
      "name" : "VP_DEVELOPMENT",
      "formalName" : "Vice President Development",
      "startDate" : "2024-01-01",
      "validUntil" : "2024-05-30",
      "temporary" : false,
      "permissions" : [{
        "resource": "mitra",
        "group" : "Master Data",
        "privileges" : {
          "create" : true,
          "update" : true,
          "delete" : false,
          "approval" : false
        }
      }]
    }
  ],
  "active_role" : {
    "id" : "role-id-1",
    "name" : "VP_DEVELOPMENT",
    "formalName" : "Vice President Development",
    "startDate" : "2024-01-01",
    "validUntil" : "2024-05-30",
    "temporary" : false,
    "permissions" : [{
      "resource": "mitra",
      "group" : "Master Data",
      "privileges" : {
        "create" : true,
        "update" : true,
        "delete" : false,
        "approval" : false
      }
    }]
  }
}
```

#### Change Active Role (For current logged-in user)
> A user can only have on active role for an unique session. This endpoint used to select active role for current user (a user can have multiple roles, example : additional temporary/PLT roles).

```http=
PUT /api/v1/profiles/me/roles
Authorization: Bearer <Token>
Content-Type: application/json
```

```json=
{
    "roleId" : "{role-id}"
}
```

#### Update Profile
```http=
PUT /v1/profiles/me
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
    "name" : "Hendro Gelo",
    "phone" : "6281234567890"
}
```

#### Change Password
> Validate request payload, check whether passwordConfirm equals to newPassword, newPassword doesn’t equal to currentPassword, enforce password policy (Password rules).
> Verify given current password match with stored encrypted user password. If it doesn’t match return bad request.
> Create a new password change request record in persistence store (database)

```
POST /v1/profiles/me/credentials
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
    "currentPassword" : "old.password",
    "newPassword" : "new.password",
    "passwordConfirm" : "new.password"
}
```



## Module Master Data

| Module | Feature | Description |
| ------ | ------ |  ------ |
| Master Data | Pelanggan |  |
| Master Data | Mitra |  |
| Master Data | Lokasi |  |
| Master Data | Pembangkit |  |
| Master Data | Moda Transportasi |  |
| Master Data | Kapal / Vessel|  |

### Pelanggan / Customers

#### CREATE Pelanggan / Customers
> Business Rule:
> - Validation unique name
> - Validation unique Initial name
> - Validation companyNpwp 16 digit
> - companyNpwp and email non-mandatory

```http=
POST /v1/customers
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=
{
    "companyName" : "PT PLN Energi Primer Indonesia",
    "companyPhone": "string",
    "companyMail": "", // non-mandatory
    "companyAddress": "string",
    "companyNpwp": "", //non-mandatory
    "initial": "PLN EPI"
}
```

#### GET Pelanggan / Customers
```http=
GET /v1/customers/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```

```json=
{
    "id" : "string",
    "companyName" : "PT PLN Energi Primer Indonesia",
    "companyPhone": "string",
    "companyMail": "", // non-mandatory
    "companyAddress": "string",
    "companyNpwp": "", //non-mandatory
    "initial": "PLN EPI"
}
```

#### GET ALL Pelanggan / Customers
```http=
GET /v1/customers
Authorization: Bearer <Token>
Content-Type: application/json
```

__Params__

params header

| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for name|
| *sort*| *{fieldName}+{ASC/DESC}* | *sort by* |

__response__
```json=
{
"data": [
        {
        "id" : "string",
        "companyName" : "PT PLN Energi Primer Indonesia",
        "companyPhone": "string",
        "companyMail": "", // non-mandatory
        "companyAddress": "string",
        "companyNpwp": "", //non-mandatory
        "initial": "PLN EPI"
        },
        {
        "id" : "string",
        "companyName" : "PT PLN Energi Primer Indonesia",
        "companyPhone": "string",
        "companyMail": "", // non-mandatory
        "companyAddress": "string",
        "companyNpwp": "", //non-mandatory
        "initial": "PLN EPI"
        }
    ],
    "metadata" : {
        "total_data" : 8,
        "total_page" : 4,
        "page" : 0,
        "limit" : 4
    }
}
```

#### UPDATE Pelanggan / Customers
```http=
PUT /v1/customers/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=
{
    "id" : "string",
    "companyName" : "PT PLN Energi Primer Indonesia",
    "companyPhone": "string",
    "companyMail": "", // non-mandatory
    "companyAddress": "string",
    "companyNpwp": "", //non-mandatory
    "initial": "PLN EPI"
}
```

#### DELETE Pelanggan / Customers
> Business Rule:
> - Validation attempt to delete customers that already assign / as foreign key will be failed

```http=
DELETE /v1/customers/{resource-id}
Authorization: Bearer <Token>
```

### Mitra / Partners

#### Enum Group
| Name | Label |
| ------ | ------ |
| internal | internal |
| supplier | Sumber Tambang |
| trader | Trader |
| transporter | Transporter |
| cbf | Partner CBF |
| isp | Partner ISP |

#### CREATE Mitra / Partners
> Business Rule:
> - Validation unique name
> - Field companyGroup using enum group exclude __internal__
> - Validation companyNpwp 16 digit
> - businessLicense mandatory for companyGroup __supplier & trader__
> - maximum limit for initial = 8 char, using trim symbol only for `-`

```http=
POST /v1/partners
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
    "group": "supplier",
    "companyName" : "PT Pelayaran Bahtera Adhiguna",
    "companyPhone": "string",
    "companyMail": "string",
    "companyNpwp": "string",
    "businessLicense": "123/asd12eas/123",
    "initial": "PLN-BAG"
}
```

#### GET Mitra / Partners
```http=
GET /v1/partners/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```

```json=
{
    "id": "string",
    "group": "supplier",
    "companyName" : "PT Pelayaran Bahtera Adhiguna",
    "companyPhone": "string",
    "companyMail": "string",
    "companyNpwp": "string",
    "businessLicense": "123/asd12eas/123",
    "initial": "PLN-BAG"
}
```

#### GET ALL Mitra / Partners
```http=
GET /v1/partners
Authorization: Bearer <Token>
Content-Type: application/json
```

__Params__

params header
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for name |
| sort | {fieldName}+{ASC/DESC} | sort by |
| group | varchar | filter for group |


__respons__
```json=
{
"data": [
        {
            "id": "string",
            "group": "supplier",
            "companyName" : "PT Pelayaran Bahtera Adhiguna",
            "companyPhone": "string",
            "companyMail": "string",
            "companyNpwp": "string",
            "businessLicense": "123/asd12eas/123",
            "initial": "PLN-BAG"
        },
        {
            "id": "string",
            "group": "supplier",
            "companyName" : "PT Pelayaran Bahtera Adhiguna",
            "companyPhone": "string",
            "companyMail": "string",
            "companyNpwp": "string",
            "businessLicense": "123/asd12eas/123",
            "initial": "PLN-BAG"
        }
    ],
    "metadata" : {
        "total_data" : 8,
        "total_page" : 4,
        "page" : 0,
        "limit" : 4
    }
}
```

#### UPDATE Mitra / Customers
```http=
PUT /v1/partners/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=
{
    "group": "supplier",
    "companyName" : "PT Pelayaran Bahtera Adhiguna",
    "companyPhone": "string",
    "companyMail": "string",
    "companyNpwp": "string",
    "businessLicense": "123/asd12eas/123",
    "initial": "PLN-BAG"
}
```

#### DELETE Mitra / Partners
> Business Rule:
> - Validation attempt to delete partners that already assign / as foreign key will be failed

```http=
DELETE /v1/partners/{resource-id}
Authorization: Bearer <Token>
```

### Location
#### Enum Areas
| Name | Label |
| ------ | ------ |
| area1 | Wilayah 1 |
| area2 | Wilayah 2 |
| area3 | Wilayah 3 |
| area4 | Wilayah 4 |

#### Enum Function of Location
| Name | Label |
| ------ | ------ |
| loadingPoint| Lokasi Jetty Muat |
| anchorage | Lokasi Anchorage |
| unloadingPoint | Lokasi Bongkar |
| cbfPoint| Lokasi Blending |
| ispPoint| Lokasi Stockpile |


#### CREATE Location
>Business Rule:
>- Required: name, type, area, latitude, longitude
>- Validation unique name
>- Field area using enum Areas
>- Field type using enum function of Location
>- Latitude & Longitude on Indonesia's Area
>- Area will be disable when the type = `unloadingPoint` or `ispPoint`
>- Authorization: ResourceGroup Master, Resource Location, privilege Create

```http=
POST /v1/locations
Authorization: Bearer <Token>
Accept: application/json
```
__payload__
```json=
{
    "name": "Location Name",
    "area" : "area1",
    "type": "loadingPoint",
    "longitude" : 2.32343,
    "latitude" : 3.34343
}
```

#### GET Location
```http=
GET /v1/locations/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "id": "string",
    "name": "Location Name",
    "area" : "area1",
    "type": "loadingPoint",
    "longitude" : 2.32343,
    "latitude" : 3.34343,
    "timezone" : "Asia/Jakarta"
}
```

#### GET ALL Location
```http=
GET /v1/locations/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for name |
| sort | {field_name}+{ASC/DESC} | sort by |
| type | enum | filter for types of location |
| area | enum | filter for area |

__response__
```json=
{
"data": [
    {
        "id": "string",
        "name": "Location Name",
        "area" : "area1",
        "type": "loadingPoint",
        "longitude" : 2.32343,
        "latitude" : 3.34343
    },
    {
        "id": "string",
        "name": "Location Name",
        "area" : "area2",
        "type": "unloadingPoint",
        "longitude" : 2.32345,
        "latitude" : 3.34349
    },
    ],
    "metadata" : {
        "total_data" : 8,
        "total_page" : 4,
        "page" : 0,
        "limit" : 4
    }
}
```

#### UPDATE Location
>Business Rule:
>- Required: name, fuctionLocation, area, latitude, longitude
>- Validation unique name
>- Field Area using enum areas
>- Field functionLocation using enum functionLocation
>- Latitude & Longitude on Indonesia's Area
>- Authorization: ResourceGroup Master, Resource Location, privilege Update
```http=
PUT /v1/locations/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=
{
    "name": "Location Name",
    "area" : "area1",
    "type": "loadingPoint",
    "longitude" : 2.32343,
    "latitude" : 3.34343
}
```

#### DELETE Location
> Business Rule:
> - Validation attempt to delete locations that already assign / as foreign key will be failed

```http=
DELETE /v1/locations/{resource-id}
Authorization: Bearer <Token>
```
### Power Plant

#### Enum Power Plant Group

| Name | Label |
| ---- | ---- |
|plnGroup | PLN Group |
|ipp| IPP |
|nonElectrical| Non-Ketenagalistrikan |

<!-- #### Enum Areas
| Name | Label |
| ------ | ------ |
| area1 | Wilayah 1 |
| area2 | Wilayah 2 |
| area3 | Wilayah 3 |
| area4 | Wilayah 4 |
-->
#### CREATE Power Plant
> Business Rule:
> - Validation unique name
> - field customerId using GET /v1/customers/{resource-id} 
> - field customerGroup using enum Power Plant Group
> - Latitude & Longitude on Indonesia's Area
> - unloadingLocationId using GET /v1/locations/{resource-id} with params / filter __functionLocation__ = __unloadingFunction__
> - Authorization: ResourceGroup Master, Resource Power Plant, privilege Create

```http=
POST /v1/powerplants
Authorization: Bearer <Token>
Accept: application/json
```
__payload__
```json=
{
    "name": "PLTU 2 Jawa Tengah Adipala",
    "ownerId" : "ID pemilik pembangkit 1 ", //GET /v1/customers/{resource-id} owner = customer
    "ownerGroup": "plnGroup",
    "latitude" : 2.2415,
    "longitude" : 4.2325,
    "unloadingLocationId" : "ID lokasi bongkar-1"
}
```


#### GET Power Plant

```http=
GET /v1/powerplants/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "id": "string",
    "name": "PLTU 2 Jawa Tengah Adipala",
    "owner": {
      "id" : "string",
      "companyName" : "PT PLN Indonesia Power"
    }, 
    "ownerGroup": "plnGroup",
    "latitude" : 2.32343,
    "longitude" : 3.34343,
    "unloadingLocation" : {
        "id": "string",
        "name": "Location Name",
        "type": "unloadingpoint",
        "longitude" : 2.32345,
        "latitude" : 3.34349,
        "timezone" : "Asia/Jakarta"
    }
},
```


#### GET ALL Power Plant
```http=
GET /v1/powerplants/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header
| key | value | Description |
| ------ | ------ |  ------ |
| page | int | page |
| limit | int | limit |
| size | int | size of page |
| search | varchar | filter for name |
| sort | {field_name}+{ASC/DESC} | sort by |
| powerPlantOwnerId | powerPlantOwnerId| filter using GET /v1/customers/{resource-id} |
| powerPlantGroup | enum | filter for power plant group |

__response__
```json=
{
"data": [
    {
    "id": "string",
    "name": "PLTU 2 Jawa Tengah Adipala",
    "owner": {
      "id" : "string",
      "companyName" : "PT PLN Indonesia Power"
    }, 
    "ownerGroup": "plnGroup",
    "latitude" : 2.32343,
    "longitude" : 3.34343,
    "unloadingLocation" : {
        "id": "string",
        "name": "Location Name",
        "type": "unloadingpoint",
        "longitude" : 2.32345,
        "latitude" : 3.34349,
        "timezone" : "Asia/Jakarta"
    }},
    {
    "id": "string",
    "name": "PLTU Jawa-7",
    "owner": {
      "id" : "string",
      "companyName" : "PT Shenhua Guohua Pembangkitan Jawa Bali"
    }, 
    "ownerGroup": "Ipp",
    "area" : "area1",
    "latitude" : 2.32343,
    "longitude" : 3.34343,
    "unloadingLocation" : {
        "id": "string",
        "name": "Location Name",
        "type": "unloadingpoint",
        "longitude" : 2.32345,
        "latitude" : 3.34349,
        "timezone" : "Asia/Jakarta"
    }},
    ],
  "metadata" : {
      "total_data" : 8,
      "total_page" : 4,
      "page" : 0,
      "limit" : 4
    }
}
```

#### UPDATE Power Plant
> Business Rule:
> - Validation unique name
> - field powerPlantOwner using GET /v1/customers/{resource-id} 
> - field powerPlantGroup using enum Power Plant Group
> - field area using enum Areas
> - Latitude & Longitude on Indonesia's Area
> - unloadingLocationId using GET /v1/locations/{resource-id} with filter __type__ = __unloadingFunction__
> - Authorization: ResourceGroup Master, Resource Power Plant, privilege Update


```http=
PUT /v1/powerplants/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=

{
    "name": "PLTU 2 Jawa Tengah Adipala",
    "owner" : "plnIp",
    "ownerGroup": "plnGroup",
    "latitude" : 2.32343,
    "longitude" : 3.34343,
    "unloadingLocationId" : "ID lokasi bongkar-1"
}

```

#### DELETE Power Plant
> Business Rule:
> - Validation attempt to delete locations that already assign / as foreign key will be failed

```http=
DELETE /v1/powerplants/{resource-id}
Authorization: Bearer <Token>
```

### Transportation Mode

#### Enum Classification Mode
| Name   | Label |
| ----   |---- |
| vessel | Vessel | 
| barge  | Barge | 
| truck  | Trucking |

#### CREATE Transportation Mode 
> Business Rule:
> - Validation unique name
> - field classificationMode using enum Classification Mode
> - Authorization: ResourceGroup Master, Resource Transportation Mode, privilege Create

```http=
POST /v1/transportationModes
Authorization: Bearer <Token>
Accept: application/json
```
__payload__
```json=
{
    "name": "vessel 33k",
    "classificationMode": "vessel",
    "volumeMax": 10000, //in metrik ton,
    "volume Min": 1000 //in metrik ton
}
```

#### GET Transportation Mode

```http=
GET /v1/transportationModes/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "id": "string",
    "name": "vessel 33k",
    "classificationMode": "vessel",
    "volumeMax": 10000,//in metrik ton,
    "volume Min": 1000 //in metrik ton
},
```

#### GET ALL Transportation Mode
```http=
GET /v1/transportationModes/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header
| key    | value  | Description |
| ------ | ------ |  ------ |
| page   | int | page |
| limit  | int | limit |
| size   | int | size of page |
| search | varchar | filter for name |
| sort   | {field_name}+{ASC/DESC} | sort by |
| classificationMode | enum | filter for classificationMode|
| isVessel | boolean | filter for vessel & barge |


__response__
```json=
{
"data": [
    {
    "id": "string",
    "name": "vessel 33k",
    "classificationMode": "vessel",
    "volumeMax": 10000,//in metrik ton,
    "volume Min": 1000 //in metrik ton
    } ,

    {
    "id": "string",
    "name": "310 ft",
    "classificationMode": "barge",
    "volumeMax": 50000,//in metrik ton,
    "volume Min": 1000 //in metrik ton
    },
    ],
  "metadata" : {
      "total_data" : 8,
      "total_page" : 4,
      "page" : 0,
      "limit" : 4
    }
}

```
#### UPDATE Transportation Mode
> Business Rule:
> - Validation unique name
> - field classificationMode using enum Classification Mode
> - Authorization: ResourceGroup Master, Resource Transportation Mode, privilege Update


```
PUT /v1/transportationModes/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
```json=

{
  "name": "vessel 33k",
  "classificationMode": "vessel",
  "volumeMax": 10000,//in metrik ton,
  "volume Min": 1000 //in metrik ton
  }


```

#### DELETE Transportation Mode
> Business Rule:
> - Validation attempt to delete locations that already assign / as foreign key will be failed

```
DELETE /v1/transportationModes/{resource-id}
Authorization: Bearer <Token>
```

### Vessel

#### Enum Vessel Type
| Name   | Label |
| ----   |---- |
| vessel | Vessel | 
| barge  | Barge | 
| tugboat | Tug Boat |


#### CREATE Vessel
> Business Rule:
> - Validation unique imoId
> - Validation unique mmsiNo
> - Validation unique name
> - Vessel type using enum vessel type
> - Authorization: ResourceGroup Master, Resource Transportation Mode, privilege Create

```http=
POST /v1/vessels
Authorization: Bearer <Token>
Accept: application/json
```
__payload__
```json=
{
    "name": "TB Queen 05/BG Bulesko V",
    "initial": "QBV",
    "portOfRegister": "Senyiur",
    "imoId":1231521, //must be 7 number
    "mmsiNo":525123456, //must 9 number
    "vesselType": "tugboat", // **Before this one is transportationModeId
    "speed":12, //in unit of kn (knot)
    "capacity": 1000, //in unit of ton
    "productionYear": 2008,
    "pic":"string",
    "picContact":'082334568923'

}
```

#### GET Vessel
```http=
GET /v1/vessels/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "id":"string",
    "name": "TB Queen 05/BG Bulesko V",
    "initial": "QBV",
    "portOfRegister": "Senyiur",
    "imoId":1231521, //must be 7 number
    "mmsiNo":525123456, //must 9 number
    "vesselType": "tugboat",
    "speed":12, //in unit of kn (knot)
    "capacity": 1000, //in unit of ton
    "productionYear": 2008,
    "pic":"string",
    "picContact":'082334568923'
}
```

#### GET ALL Vessel
```http=
GET /v1/vessels/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header

| key    | value  | Description |
| ----| ----|  ---- |
| page   | int | page |
| limit  | int | limit |
| size   | int | size of page |
| search | varchar | filter for name |
| sort   | {field_name}+{ASC/DESC} | sort by |
| type | enum vessel type | filter for vessel type|


__response__
```json=
{
"data": [
    {
    "id":"string",
    "name": "TB Queen 05/BG Bulesko V",
    "initial": "QBV",
    "portOfRegister": "Senyiur",
    "imoId":1231521, //must be 7 number
    "mmsiNo":525123456, //must 9 number
    "vesselType": "tugboat",
    "speed":12, //in unit of kn (knot)
    "capacity": 1000, //in unit of ton
    "productionYear": 2008,
    "pic":"string",
    "picContact":'082334568923'
    } ,

    {
   "id":"string",
    "name": "TB Queen 05/BG Bulesko V",
    "initial": "QBV",
    "portOfRegister": "Senyiur",
    "imoId":1231521, //must be 7 number
    "mmsiNo":525123456, //must 9 number
    "vesselType": "tugboat",
    "speed":12, //in unit of kn (knot)
    "capacity": 1000, //in unit of ton
    "productionYear": 2008,
    "pic":"string",
    "picContact":'082334568923'
    },
    ],
  "metadata" : {
      "total_data" : 8,
      "total_page" : 4,
      "page" : 0,
      "limit" : 4
    }
}

```

#### UPDATE Vessel
> Business Rule:
> - Validation unique imoId
> - Validation unique mmsiNo
> - Validation unique name
> - *vesselTypeId* using GET /v1/transportationmodes/{resource-id} 
> - Authorization: ResourceGroup Master, Resource Transportation Mode, privilege Update

```http=
PUT /v1/transportationModes/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__payload__
```json=
{
   "name":"TB Queen 05/BG Bulesko V",
   "initial":"QBV",
   "portOfRegister":"Senyiur",
   "imoId":1231521, //must be 7 number
   "mmsiNo":525123456, //must 9 number
   "vesselType": "tugboat",
   "speed":12,
   "capacity":1000,
   "productionYear":2008,
   "pic":"string",
   "picContact":"082334568923"
}
```
__response__
```json=

{
    "id":"string",
    "name": "TB Queen 05/BG Bulesko V",
    "initial": "QBV",
    "portOfRegister": "Senyiur",
    "imoId":1231521, //must be 7 number
    "mmsiNo":525123456, //must 9 number
    "vesselType":"tugboat",
    "speed":12, //in unit of kn (knot)
    "capacity": 1000, //in unit of ton
    "productionYear": 2008,
    "pic":"string",
    "picContact":'082334568923'
}
```

#### DELETE Vessel
> Business Rule:
> - Validation attempt to delete locations that already assign / as foreign key will be failed

```http=
DELETE /v1/vessels/{resource-id}
Authorization: Bearer <Token>
```

## Module Referensi Data

| Module | Feature | Description |
| ------ | ------ |  ------ |
| Referensi Data | Exchange Rate |  |
| Referensi Data | Fuel Price |  |

### Exchange Rate Reference

#### Enum Exchange Reference

| Name | Label |
| ---- | ---- |
| jisdor | Exchange Rate untuk JISDOR |
| biRate | Exchange Rate untuk BI Rate |

#### CREATE Exchange Rate Reference
> Business Rule:
> - field exchangeReference using enum Exchange Reference
> - field monthPeriod fill with month
> - field yearPeriod fill with year 
> - Validation unique combination for period and exchangeReference
> - field __averageRate__ is a system-generated field, calculated as the mean of all daily __midRate values within the period__ for __exchangeReference = biRate__ *or* __rate values within the period__ for __exchangeReference = jisdor__
> - Validation unique date in exchangeRate record
> - field exchangeRate must be greater than or equal to zero ( >= 0 )
> - Authorization: ResourceGroup Reference, Resource Exchange Rate, privilege Create

```http=
POST /v1/exchangeRateReferences
Authorization: Bearer <Token>
Accept: application/json
```

__payload__
```json=
{
    "monthPeriod": 1,
    "yearPeriod": 2025,
    "exchangeReference": "",
    "dailyRates":[
      {
          "date": "", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       },
      {
          "date": "string", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       },
      {
          "date": "string", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       }, //till the end of the month
    ]
}
```

#### GET Exchange Rate Reference
```http=
GET /v1/exchangeRateReferences/{yyyy-mm-exchangeReference}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "monthPeriod": 1,
    "yearPeriod": 2025,
    "exchangeReference": "",
    "periodAverageRate": 0,
    "dailyRates": [
        {
            "id": "string",
            "date": "string", // YYYY-MM-DD
            "exchangeRate": 0, // float
        },
        {
            "id": "string",
            "date": "string", // YYYY-MM-DD
            "exchangeRate": 0, // float
        },
    ]
}
```

#### GET ALL Exchange Rate Reference
```http=
GET /v1/exchangeRateReferences/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header

| key    | value  | Description |
| ----| ----|  ---- |
| page   | int | page |
| limit  | int | limit |
| size   | int | size of page |
| month  | int | filter for month |
| year   | int | filter for year |
| exchangeReference | enum (BI Rate or JISDOR) | filter for exchange reference |
| sort   | {field_name}+{ASC/DESC} | sort by |


__response__
```json=
{
"data": [
    {
    "id":"string",
    "monthPeriod": 1,
    "yearPeriod": 2025,
    "exchangeReference": "",
    "periodAverage": 0,
    } ,
    {
   "id":"string",
    "monthPeriod": 1,
    "yearPeriod": 2025,
    "exchangeReference": "",
    "periodAverage": 0,
    },
    ],
  "metadata" : {
      "total_data" : 8,
      "total_page" : 4,
      "page" : 0,
      "limit" : 4
    }
}

```

#### UPDATE Exchange Rate Reference
> Business Rule:
> - field exchangeReference using enum Exchange Reference
> - field monthPeriod fill with month
> - field yearPeriod fill with year 
> - Validation unique combination for period and exchangeReference
> - field __averageRate__ is a system-generated field, calculated as the mean of all daily __midRate values within the period__ for __exchangeReference = biRate__ *or* __rate values within the period__ for __exchangeReference = jisdor__
> - Authorization: ResourceGroup Reference, Resource Exchange Rate, privilege Update

```http=
PUT /v1/exchangeRateReferences/{yyyy-mm-exchangeReference}
Authorization: Bearer <Token>
Content-Type: application/json
```

__response__
```json=

{
    "monthPeriod": 1,
    "yearPeriod": 2025,
    "exchangeReference": "",
    "dailyRates":[
      {
          "date": "", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       },
      {
          "date": "string", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       },
      {
          "date": "string", // YYYY-MM-DD
          "exchangeRate": 16235.00, // float
       }, //till the end of the month
    ]
}
```

### Fuel Price Reference

#### Fuel Price Period

| Value | Description |
| ---- |  ---- |
|1 | Harga pada periode 1 (tanggal 1 - 14) |
|2| Harga pada periode 2 (tanggal 15 - sampai akhir bulan)|

#### CREATE Fuel Price Reference
> Business Rule:
> - Validation unique combination for period, month and year
> - field period using enum Fuel Price Period
> - Validation period only 1 or 2
> - Validation fuel price size must be equals to 3 (three)
> - Authorization: ResourceGroup Reference, Resource Fuel Price, privilege Create

```http=
POST /v1/fuelPriceReferences
Authorization: Bearer <Token>
Accept: application/json
```

__payload__
```json=
{
    "period": 1 ,
    "month": 02,
    "year": 2025,
    "fuelPrice": [
      {
        "fuelType": "hsd",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      },
      {
       "fuelType": "lsfo",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      },
      {
        "fuelType": "hsfo",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      }

    ]
      
}

```

#### GET Fuel Price Reference
```http=
GET /v1/fuelPriceReferences/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```
__response__
```json=
{
    "id":"string",
    "period": 1 ,
    "month": 02,
    "year": 2025 ,
    "fuelPrice": [
        {
            "id": "string",
            "fuelType": "hsd",
            "area1": 0,
            "area2": 0,
            "area3": 0,
            "area4": 0
        },
        {
            "id": "string",
            "fuelType": "lsfo",
            "area1": 0,
            "area2": 0,
            "area3": 0,
            "area4": 0
        },
        {
            "id": "string",
            "fuelType": "hsfo",
            "area1": 0,
            "area2": 0,
            "area3": 0,
            "area4": 0
        }
    ]
}
```
#### GET ALL Fuel Price Reference
```http=
GET /v1/fuelPriceReferences/
Authorization: Bearer <Token>
Content-Type: application/json
```
__Params__

params header

| key    | value  | Description |
| ----| ----|  ---- |
| page   | int | page |
| limit  | int | limit |
| size   | int | size of page |
| sort   | {field_name}+{ASC/DESC} | sort by |
| period | 1 or 2 | filter for period |
| month  | int | filter for month |
| year   | int | filter for year |

__response__
```json=
{
"data": [
      {
        "id":"string",
        "period": 1 ,
        "month": 02,
        "year": 2025  
      }
    ],
  "metadata" : {
      "total_data" : 8,
      "total_page" : 4,
      "page" : 0,
      "limit" : 4
    }
}

```

#### UPDATE Fuel Price Reference
> Business Rule:
> - Validation unique combination for period, month and year
> - field period using enum Fuel Price Period
> - Authorization: ResourceGroup Reference, Resource Fuel Price, privilege Update

```http=
PUT /v1/fuelPriceReferences/{resource-id}
Authorization: Bearer <Token>
Content-Type: application/json
```

__response__
```json=
{
    "period": 1 ,
    "month": 02,
    "year": 2025,
    "fuelPrice": [
      {
        "fuelType": "hsd",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      },
      {
       "fuelType": "lsfo",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      },
      {
        "fuelType": "hsfo",
        "area1": 0,
        "area2": 0,
        "area3": 0,
        "area4": 0,
      }

    ]
      
}

