iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0
Modern Web

Node JS-Back end見聞錄系列 第 23

Node.js-Backend見聞錄(22):實作-商品系統(五)-修改訂單部分(一)

Node.js-Backend見聞錄(22):實作-商品系統(五)-修改訂單部分(一)

前言

接續實作-商品系統(四)-訂單列表及訂購商品部分(二),我們將繼續完成訂單列表及訂購商品部分的開發。

修改訂單部分需求

  • 取得訂單資料(GET)
  • 修改訂單(PUT)
  • 刪除訂單(DELETE)
  • 新增單筆訂單資料(POST)

資料結構

新增的部分:

  • models
    • order
      • one_order_model.js
      • update_model.js
.
├── app.js
├── bin
│   └── www
├── config
│   └── development_config.js
├── controllers
│   ├── member
│   │    └── modify_controller.js
│   ├── order
│   │    ├── get_controller.js
│   │    └── modify_controller.js
│   ├── product
│   │    └── get_controller.js
├── models
│   ├── member
│   │    ├── encryption_model.js
│   │    ├── login_model.js
│   │    ├── register_model.js
│   │    ├── update_model.js
│   │    └── verifyication_model.js
│   ├── order
│   │    ├── all_order_model.js
│   │    ├── one_order_model.js
│   │    ├── order_all_product_model.js
│   │    └── update_model.js
│   ├── product
│   │    └── all_product.js
│   └── connection_db.js
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── member.js
│   ├── order.js
│   └── product.js
├── sevice
│   └── member_check.js
├── views
    ├── error.ejs
    └── index.ejs
├── .env
└── .gitignore

開始實作

從圖中可發現,在進行修改、刪除、新增單筆商品動作前都需要先使用取得訂單資料這支。所以這部分的實作我們就依照上面需求部分所提的API順序來進行開發。

取得訂單資料(GET)

我們在實作-商品系統(四)-訂單列表及訂購商品部分(二)一文中,只實作取得訂單列表(GET)的API,而這邊我們還要另外做個能夠提取特定會員的訂單資料。

首先,我們先到models > order資料夾中的one_order_model.js檔案中寫入:

const db = require('../connection_db');

module.exports = function getOneOrderData(memberID) {
    let result = {};
    return new Promise((resolve, reject) => {
        db.query('SELECT * FROM order_list WHERE member_id = ?', memberID, function (err, rows) {
            // 若資料庫部分出現問題,則回傳「伺服器錯誤,請稍後再試!」的結果。
            if (err) {
                console.log(err);
                result.status = "取得全部訂單資料失敗。"
                result.err = "伺服器錯誤,請稍後在試!"
                reject(result);
                return;
            }
            // 若資料庫部分沒問題,則回傳特定顧客的訂單資料。
            resolve(rows);
        })
    })
}

再來,我們將該model匯入到controllers > order資料夾的get_controller.js檔案中。並新增一個叫做getOneOrder的function:

// 取得單筆產品資料
getOneOrder(req, res, next) {
    const token = req.headers['token'];
    //確定token是否有輸入
    if (check.checkNull(token) === true) {
        res.json({
            err: "請輸入token!"
        })
    } else if (check.checkNull(token) === false) {
        verify(token).then(tokenResult => {
            if (tokenResult === false) {
                res.json({
                    result: {
                        status: "token錯誤。",
                        err: "請重新登入。"
                    }
                })
            } else {
                const memberID = tokenResult;

                orderOneData(memberID).then(result => {
                    res.json({
                        result: result
                    })
                }, (err) => {
                    res.json({
                        result: err
                    })
                })
            }
        })
    }
}

最後,給予這個API一個URL。至routes資料夾的order.js檔案中寫入:

var express = require('express');
var router = express.Router();

const OrderGetMethod = require('../controllers/order/get_controller');
const OrderModifyMethod = require('../controllers/order/modify_controller');

orderGetMethod = new OrderGetMethod();
orderModifyMethod = new OrderModifyMethod();

// 取得全部訂單資料
router.get('/order', orderGetMethod.getAllOrder);

// 取得單一顧客的訂單資料
router.get('/order/member', orderGetMethod.getOneOrder);

// 訂整筆訂單
router.post('/order', orderModifyMethod.postOrderAllProduct);

module.exports = router;

測試

這部分我們透過Postman來進行測試:

  • HTTP method: GET

  • HTTP url : localhost:3000/order/member

  • headers

    • token: 會員經登入後所取得的token值

其結果:

修改訂單(PUT)

筆者將這支API預設為client端需要輸入的資料為:

  • headers
    • token: 會員經登入後所取得的token值
  • body
    • orderID: 1
    • productID: 1
    • quantity: 4

也就是指定特定訂單編號,並指定某樣想修改的商品編號,最後再輸入欲修改的商品數量。

為了做到這個方式,首先我們先處理models > order資料夾的update_model.js檔案:

但在實作前我們必須先做到三件事情:

  1. 找不找得到該筆訂單。
  2. 該筆訂單是否完成,若完成我們就不能讓它能進行修改訂單的功能。
  3. 提取商品價格。這部分也會像在實作-商品系統(四)-訂單列表及訂購商品部分(二)文章中一樣,會再額外去product的table中提取該筆商品的價格。

判斷該筆訂單是否存在

這部分我們會額外寫個function來進行判定。

const checkOrderData = function (orderID, memberID, productID) {
    return new Promise((resolve, reject) => {
        db.query('SELECT * FROM order_list WHERE order_id = ? AND member_id = ? AND product_id = ?', [orderID, memberID, productID], function (err, rows) {
            if (rows[0] === undefined) {
                resolve(false);
            } else {
                resolve(true);
            }
        })
    })
}

判斷該筆訂單是否已完成

這部分我們也是會額外寫個function來處理:

const checkOrderComplete = function (orderID, memberID, productID) {
    return new Promise((resolve, reject) => {
        db.query('SELECT * FROM order_list WHERE order_id = ? AND member_id = ? AND product_id = ? AND is_complete = 0', [orderID, memberID, productID], function (err, rows) {
            if (rows[0] === undefined) {
                resolve(false);
            } else {
                resolve(true);
            }
        })
    })
}

提取商品價格

依舊額外寫個function來處理:

const getProductPrice = (productID) => {
    return new Promise((resolve, reject) => {
        db.query('SELECT price FROM product WHERE id = ?', productID, function (err, rows) {
            if (err) {
                console.log(err);
                reject(err);
                return;
            }
            resolve(rows[0].price);
        })
    })
}

將資料寫入資料庫進行修改

最後該功能的樣貌就會長得像是:

const db = require('../connection_db');

module.exports = function orderEdit(updateList) {
    let result = {};
    return new Promise(async (resolve, reject) => {

        // 判斷有沒有該筆訂單資料
        const hasData = await checkOrderData(updateList.orderID, updateList.memberID, updateList.productID);

        // 判斷該筆訂單資料是否已完成交易
        const hasComplete = await checkOrderComplete(updateList.orderID, updateList.memberID, updateList.productID);

        if (hasData === false) {
            result.status = "更新訂單資料失敗。"
            result.err = "沒有該筆資料!"
            reject(result);
        } else if (hasComplete === false) {
            result.status = "更新訂單資料失敗。"
            result.err = "該筆資料已完成。"
            reject(result);
        } else if (hasData === true && hasComplete === true) {
            // 取得商品價錢
            const price = await getProductPrice(updateList.productID);

            // 計算商品總價格
            const orderPrice = updateList.quantity * price;

            // 更新該筆訂單資料(資料庫)
            await db.query('UPDATE order_list SET order_quantity = ?, order_price = ?, update_date = ? WHERE order_id = ? AND member_id = ? AND product_id = ?', [updateList.quantity, orderPrice, updateList.updateDate, updateList.orderID, updateList.memberID, updateList.productID], function (err, rows) {
                if (err) {
                    console.log(err);
                    result.status = "更新訂單資料失敗。"
                    result.err = "伺服器錯誤,請稍後在試!"
                    reject(result);
                    return;
                }
                result.status = "更新訂單資料成功。"
                result.updateList = updateList
                resolve(result)
            })
        }
    })
}

測試

這部分我們透過Postman來進行測試:

  • HTTP method: PUT

  • HTTP url : localhost:3000/order

  • Body中選擇x-www-form-urlencoded

  • headers

    • Content-Type: application/x-www-form-urlencoded
    • token: 會員經登入後所取得的token值
  • body

    • orderID: 1
    • productID: 1
    • quantity: 4

其結果:

再到MySQL那邊去做確認:

小結

在這階段我們已經完成取得訂單資料(GET)修改訂單(PUT)的API,而下個章節將接續開發刪除訂單(DELETE)新增單筆訂單資料(POST)部分。

功能延伸

其實在取得訂單資料(GET)部分,讀者可試著做延伸,其延伸方式為:

  • 訂單未完成情況下,其特定顧客的訂單資料。
  • 訂單已完成情況下,其特定顧客的訂單資料。

這兩個API的值只要判斷is_complete的值,若為0則訂單未完成,若為1則訂單已完成。


上一篇
Node.js-Backend見聞錄(21):實作-商品系統(四)-訂單列表及訂購商品部分(二)
下一篇
Node.js-Backend見聞錄(23):實作-商品系統(六)-修改訂單部分(二)
系列文
Node JS-Back end見聞錄31

尚未有邦友留言

立即登入留言