---
# System prepended metadata

title: wallet_backend_design

---

# wallet_backend_design

express.js + mysql



## DATABASE:

#### 資料型態:

Primary Key: varchar或是int
(用int可以使用自動遞增，缺點是debug不方便)
整數：int
字串：varchar
時間：datetime
非必填的欄位設為可NULL
created_time跟updated_time自動生成）(不確定mysql是否可以)

#### TABLE:

    user
        id,channel,channel_id,email,username,nick_name,created_time,updated_time

    wallet
        id,user_id,selected,name,total,title,desc,created_time,updated_time

    wallet_record
        id,wallet_id,wallet_record_tag_id,ordinary,name,description,amount,type(吃/交通..),date,created_time,updated_time

    wallet_record_tag_id
        id,wallet_id,ordinary,name,type(支出/收入),created_time,updated_time

---

## API:

#### 目錄：

    Ａ.使用者登入登出系統
        一. google登入
        二. 註冊(需經過google登入後判斷未註冊回到註冊頁)
        三. google登入成功且已註冊

    B.wallet
        一. 使用者選擇超出buffer的月份時，拿該月+-6個月的資料
        二. wallet： 
            二-a.讀取
            二-b.新增
            二-c.修改
            二-d.刪除
        三. wallet紀錄： 
            三-a.讀取
            三-b.新增
            三-c.修改
            三-d.刪除
        四. 標籤： 
            四-a.讀取
            四-b.新增
            四-c.修改
            四-d.刪除
        五. 報表
            四-a.讀取
        六. 使用者設定
            六-a.修改暱稱

### Ａ.使用者登入登出系統

#### [一. google登入]：
    request:
        HTTP: GET 
        url: "/user/login/google"
    
    SERVER內流程：
        1.轉至google登入介面，使用者填google帳密後按確認：
        1-a.google登入成功：
            使用Google回來的資料查詢資料庫是否已有該使用者紀錄：
                使用該使用者email帳號加密後產生使用者id(sha-256固定產生32位元的字串)
                用該使用者id判斷是否已存在在資料庫裡
                    SELECT EXIST(*)
                    FROM user
                    WHERE user_id=?
                若有： 
                    製作該用戶token跟jwt(驗證使用者使否過期用)
                    redirect回前端並用url將token傳給前端登入待轉頁(前端收到token後再發一次request拿取該使用者全部資料)
                
                若無：
                    製作該用戶token 
                    redirect回前端並用url將token傳給前端註冊頁

        1-b.google登入失敗：
            redirect回前端登入頁

    response:
        直接redirect

#### [二. 註冊]:

    request: 
        url: "user/signup"
        HTTP: POST
        header:
            jwt(json web token字串)
            content-type: "application/json utf-8"
        body:
            {
                user_token:  // [一.google登入]會給token
                nick_name:

            }

    SERVER端驗證:
        驗證jwt是否過期
        驗證session是否有該使用者紀錄

    SERVER內流程：
        使用使用者email帳號加密後產生使用者id(sha-256固定產生32位元的字串)
        利用session取得該使用者的channel跟channel_id
        寫入資料庫：
            INSERT INTO user
            values(user_id=?,nick_name=?,channel=?,channel_id=?,created_time=?)
            
            //幫該使用者新增一個預設錢包
            
            //幫該使用者的預設錢包新增多個預設標籤(吃/交通/...)
            

    response:
        {
            status:"error"/"success"
            message:"註冊成功/失敗"
            data:{
                //無
            }
        }

#### [三. google登入成功且已註冊，在重新倒回到前端後再發一次request取得完整資料]:
    request: 
        POST
        url: "user/data/get"

    SERVER端驗證:
        驗證jwt是否過期
        驗證session是否有該使用者紀錄

    SERVER內流程：
        從資料庫取得該使用者資料
        SELECT ＊
        FROM user
        JOIN wallet
        ON wallet.user_id=user.id
        JOIN wallet_record
        ON wallet_record.wallet_id=wallet.id
        
        將取出的資料轉成以下格式
        
    response:
    {
        status:"error"/"success"
        message:""
        data:{
            user_id:
            user_name:
            user_nick_name:
            selected_wallet_id:"a",
            wallets:[
                "wallet-a":{
                    wallet_id,
                    wallet_name:
                    selected: //true/false
                    records:[
                        {
                            record_id:"wallet-a-record-1"
                            wallet_record_tag_id:
                            record_ordinary:
                            record_name:
                            record_description:
                            record_amount:
                            record_type:
                            record_date:
                            record_created_time:
                        },
                        {
                            record_id:"wallet-a-record-2"
                            wallet_record_tag_id:
                            record_ordinary:
                            record_name:
                            record_description:
                            record_amount:
                            record_type:
                            record_date:
                            record_created_time:
                        },
                    ]
                },
                "wallet-b":{
                    wallet_id,
                    wallet_name:
                    selected: //若selected==false則records為空陣列
                    records:[
                    ]
                }
            ]
        }
    }

### B.wallet

#### [一.取得給定錢包給定月份+-6個月的record]:
    reuqest:
    
    SERVER端驗證:
        驗證jwt是否過期
        驗證session是否有該使用者紀錄

    SERVER內流程：
        從資料庫取得該使用者資料
    
    response:
    


### SERVER規則：

    1.response status code:
        200: GET 成功
        201: POST 成功
        400: 網路問題
        500: SERVER問題

    2.登入成功只會回傳selected錢包的所有資料
    3.一個錢包只會包含 當月+-6個月的資料
    4.除了google登入外的API 都有以下規則：

        1.使用cookie跟session驗證該使用者的瀏覽器先前曾經google登入成功過，並利用cookie會過期的特性，驗證使用者是否過期

        若要再更安全：
        2.使用json web token驗證使用者是否過期
        (
        登入成功後將會發送一個jwt給前端，存在local storage或vues內
        (放在Local Storage的好處：若關掉再重開瀏覽器則不需要再重新登入 且該字串為加密字串毋須擔心資訊安全問題)
        每次request的時候將該token字串放到header內
        給後端驗證使用者是否過期
        )
    5.若使用google登入跟使用FB登入的email是同一個，則視為同一個帳戶(我們使用加密後的email作為Primary Key)
    6.每次增刪改紀錄後會需要重新拿該月+-6個月的資料（在同一個requset/response)
    7.使用url傳遞變數時一率採用後端加密前端解密
    
    
### 檔案結構：

-model
    -user
    -user_service
    -wallet
    -wallet_service
    -wallet_record
    -wallet_record_service
-controller
    -user
    -wallet
    -wallet_record
-route
    -user
    -wallet
    -wallet_record
-middleware
index.js

    
### model結構: