---
# System prepended metadata

title: Mutual Fund System

---

# Mutual Fund System

## Sequence Diagram

```sequence
title: Mutual Fund System
User->Bank: 1. create user
Bank->User Management: 1.1 create user
User Management-->Bank: 1.2 return result
Bank->Account Management: 1.4 create account
Account Management-->Bank: 1.5 return result
Bank-->User: 1.6 return result


User->Bank: 2. sign agreement
Bank->Agreement Management: 2.1 check agreement status
Agreement Management-->Bank: 2.2 return agreement detail
Bank-->User: 2.3 display agreement detail
User->Bank: 2.4 confirm for signing
Bank->Agreement Management: 2.5 update agreement status
Agreement Management-->Bank: 2.6 return result
Bank-->User: 2.7 return result

User->Bank: 3. user login
Bank->User Management: 3.1 check login info
User Management-->Bank: 3.2 return result
Bank-->User: 3.3 return result

User->Bank: 4 request funds avaliable
Bank->Agreement Management: 4.1 check agreement
Agreement Management-->Bank: 4.2 return result
note right of Bank: has agreement ?
Bank->Fund Management: 4.3 look up for the funds avaliable
Fund Management-->Bank: 4.4 return data
Bank-->User: 4.5 display the fund list

User->Bank: 5. select the target fund and amount of money
Bank->Fund Management: 5.1 check fund detail
Fund Management-->Bank: 5.2 return fund detail
Bank-->User: 5.3 display the fund detail

User->Bank: 6. confirm for purchase
Bank->Account Management: 6.1 check account balance
Account Management-->Bank: 6.2 return account balance
note right of Bank: balance not enough ?
Bank->Notification: 6.3 send warning
Notification-->>User: 6.4 A warning message sent to user
Bank->Fund Management: 6.5 get the detail of the fund
Fund Management-->Bank: 6.6 return fund detail
Bank->Order Management: 6.7 create and record order
Order Management-->Bank: 6.8 return result
note right of Bank: closing hours passed ?
Bank->Notification: 6.9 send message to user
Notification-->User: 6.10 notify the result of transaction
Bank-->User: 6.11 return result with extra info
note right of Bank: is trading date ?
Bank->Account Management: 6.12 check account balance and debit
Account Management-->Bank: 6.13 return account detail
note right of Bank: balance not enough ?
Bank->Notification: 6.14 send warning
Notification-->>User: 6.15 A warning message sent to user
note right of Bank: last check before closing hours
Bank->Order Management: 6.16 get order detail
Order Management-->Bank: 6.17 return order detail
Bank->Fund Management: 6.18 update fund detail
Fund Management-->Bank: 6.19 return result
Bank->Account Management: 6.20 update user account
Account Management-->Bank: 6.21 return result
Bank->Notification: 6.22 send message
Notification --> User: 6.23 notify the result of the transaction
```

---

## APIs

* POST /users: Create user
* POST /users/login: Login
* POST /agreements: Sign agreement
* GET /funds: View list of available funds to purchase
* GET /funds/{id}: View details of a specific fund
* POST /funds/{id}/purchase: Confirm purchase of a fund
* GET /accounts/{id}: View account details
* POST /accounts/{id}/deposit: Deposit
* POST /accounts/{id}/withdraw: Withdraw
* GET /transactions/{id}: View details of a specific transaction
* GET /orders/{id}: View details of a specific order

---

### Create User

* URL: /users
* Method: POST
* Request Body:

```
{
    "username": "JohnDoe",
    "email": "johndoe@example.com",
    "password": "abc123456",
    "phone": "886912345678"
}
```

* Response:
    * Success (201):
    ```
    {
        "success": true,
        "id": 12345,
        "accountId": "acc0000000001"
    }

    ```
    * Failure (400):
    ```
    {
        "error": "user already existed."
    }
    ```
---

### Login

* URL: /users/login
* Method: POST
* Request Body:
```
{
    "username": "JohnDoe",
    "email": "johndoe@example.com",
    "password": "abc123456"
}
```
* Response:
    * Success (200):
    ```
    {
        "token": "jwt_token"
    }
    ```
    * Failure (401):
    ```
    {
        "error": "Invalid email or password."
    }
    ``` 
---

### Sign Agreement

* URL: /agreements
* Method: POST
* Request Body:
```
{
    "user_id": "12345",
    "agreement_id": "67890",
}
```
* Response:
    * Success (200):
    ```
    {
        "id": "67890",
        "user_id": "12345",
        "status": "signed"
    }

    ```
    * Failure (404):
    ```
    {
        "error": "User not found."
    }
    ```
    * Failure (400):
    ```
    {
        "error": "Agreement has already been signed."
    }

    ```

---

### View list of available funds to purchase

* URL: /funds
* Method: GET
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Response:
    * Success (200):
    ```
    {
        "funds": [
            {
                "id": "123456",
                "name": "ABC Fund",
                "type": "A",
                "currency": "USD",
                "nav": 34.62,
                "fee": 1.5
            },
            {
                "id": "234567",
                "name": "DEF Fund",
                "type": "B",
                "currency": "EUR",
                "nav": 56.78,
                "fee": 2.0
            }
        ]
    }
    ```
    * Failure (401):
    ```
    {
        "error": "Unauthorized"
    }
    ```
___

### View details of a specific fund

* URL: /funds/{id}
* Method: GET
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body: N/A
```
```
* Response
    * Success (200):
    ```
    {
        "id": "12345",
        "name": "ABC Mutual Fund",
        "net_assets_value": 100.0,
        "currency": "USD",
        "fund_type": "Stocks",
        "fee_schedule": "1.5%",
        "prospectus": "https://example.com/prospectus"
    }
    ```
    * Failure (404):
    ```
    {
        "error": "Fund not found."
    }
    ```
---

### Confirm purchase of a fund

* URL: /funds/{id}/purchase
* Method: POST
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body:
```
{
    "amount": 100,
    "tradingFee": 1.5,
    "tradingType": "prepay"
}
```
* Response:
    * Success (201):
    ```
    {
        "id": "12345",
        "fundId": "abc123",
        "amount": 100,
        "tradingFee": 1.5,
        "tradingType": "prepay",
        "status": "pending",
        "createdAt": "2022-12-10T15:30:00Z"
    }
    ```
    * Failure (400):
    ```
    {
        "error": "Invalid trading type."
    }
    ```
---

### View account details


* URL: /accounts/{id}
* Method: GET
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body: N/A
```
```
* Response:
    * Success (200):
    ```
    {
        "id": "12345",
        "balance": 1000.00,
        "orders": [
            {
                "id": "1",
                "fund_id": "ABC",
                "quantity": 100,
                "price": 34.62,
                "date": "2022-12-10"
            },
            {
                "id": "2",
                "fund_id": "XYZ",
                "quantity": 50,
                "price": 20.34,
                "date": "2022-12-09"
            }
        ],
        "transactions": [
            {
                "id": "1",
                "type": "DEPOSIT",
                "amount": 500.00,
                "date": "2022-12-09"
            },
            {
                "id": "2",
                "type": "WITHDRAW",
                "amount": 100.00,
                "date": "2022-12-08"
            }
        ]
    }
    ```
    * Failure (404):
    ```
    {
        "error": "Account not found."
    }
    ```    
---

### Deposit

* URL: /accounts/{id}/deposit
* Method: POST
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body:
```
{
    "amount": 1000
}
```
* Response:
    * Success (200):
    ```
    {
        "id": "12345",
        "balance": 1000
    }
    ```
    
    * Failure (400):
    ```
    {
        "error": "Invalid amount"
    }
    // or
    {
        "error": "Account not found"
    }
    ```
---

### Withdraw
* URL: /accounts/{id}/withdraw
* Method: POST
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body:
```
{
    "amount": 1000
}
```

* Response:
    * Success (200):
    ```
    {
        "id": "12345",
        "username": "JohnDoe",
        "email": "johndoe@example.com",
        "balance": 10000
    }
    ```
    * Failure (400):
    ```
    {
        "error": "Insufficient balance."
    }
    ```
---

### View details of a specific transaction

* URL: /transactions/{id}
* Method: GET
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body: N/A
```
```
* Response:
    * Success (200):
    ```
    {
        "id": "12345",
        "type": "deposit",
        "amount": 100,
        "date": "2022-10-10"
    }
    ```
    
    * Failure (404):
    ```
    {
        "error": "Transaction not found."
    }
    ```
---

### View details of a specific order

* URL: /orders/{id}
* Method: GET
* Request Headers:
```
Authorization: Bearer <JWT token>
```
* Request Body: N/A
```
```
* Response:
    * Success (200):
    ```
    {
        "id": "12345",
        "fund_id": "67890",
        "fund_name": "ABC Fund",
        "amount": 10000,
        "price": 100.50,
        "status": "pending",
        "created_at": "2022-12-10T12:00:00Z"
    }
    ```
    * Failure (404):
    ```
    {
        "error": "Order not found."
    }
    ```
    
---

## Table Schema

### users
```sql!
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(255) NOT NULL UNIQUE,
    email VARCHAR(255) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    phone VARCHAR(255) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME
);

```

### agreements

```sql!
CREATE TABLE agreements (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    user_id INTEGER NOT NULL,
    signed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME    
);

```

### funds
```sql!
CREATE TABLE funds (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    nav DECIMAL(10, 4) NOT NULL,
    fee DECIMAL(10, 4) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME  
);
```

### orders
```sql!
CREATE TABLE orders (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    user_id INTEGER NOT NULL,
    fund_id INTEGER NOT NULL,
    amount DECIMAL(10, 4) NOT NULL,
    status ENUM('pending', 'completed', 'failed', 'cancelled') NOT NULL DEFAULT 'pending',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME
);
```

### accounts

```sql!
CREATE TABLE accounts (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    user_id INTEGER NOT NULL,
    balance DECIMAL(10,4) NOT NULL DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME
)

```

### user_funds
```sql!
CREATE TABLE user_funds (
    user_id INTEGER NOT NULL,
    fund_id INTEGER NOT NULL,
    units DECIMAL(10,4) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at DATETIME
)
```

### transaction

```sql!
CREATE TABLE transactions (
    id INTEGER PRIMARY KEY AUTO_INCREMENT,
    user_id INTEGER NOT NULL,
    type ENUM('deposit', 'withdraw') NOT NULL,
    amount DECIMAL(10,4) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)

```