Completed
Push — master ( c43b12...16faec )
by Emil
03:31
created

models/orders.js   A

Complexity

Total Complexity 34
Complexity/F 1.89

Size

Lines of Code 279
Function Count 18

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 86.21%

Importance

Changes 5
Bugs 1 Features 1
Metric Value
cc 0
eloc 197
c 5
b 1
f 1
nc 1
dl 0
loc 279
ccs 50
cts 58
cp 0.8621
crap 0
rs 9.68
wmc 34
mnd 3
bc 40
fnc 18
bpm 2.2222
cpm 1.8888
noi 10

7 Functions

Rating   Name   Duplication   Size   Complexity  
B orders.getOrder 0 55 2
A orders.searchOrder 0 39 1
A orders.addOrder 0 25 1
A orders.getAllOrders 0 31 1
A orders.updateOrder 0 37 2
A orders.getOrderItems 0 27 1
A orders.deleteOrder 0 43 2
1 1
const db = require("../db/database.js");
2
3 1
const orders = {
4
    dataFields: "o.ROWID as id, customerName as name," +
5
        " customerAddress as address," +
6
        " customerZip as zip, customerCity as city," +
7
        " customerCountry as country, s.status, s.id as status_id",
8
9
    orderItemsDataFields: "oi.productId as product_id, oi.amount," +
10
        " p.articleNumber as article_number, p.productName as name," +
11
        " p.productDescription as description, p.productSpecifiers as specifiers," +
12
        " p.stock, p.location, (p.price/100) as price",
13
14
    getAllOrders: function(res, apiKey, status=200) {
15 4
        let returnedOrders = { data: []};
16
17 4
        db.all("SELECT " + orders.dataFields +
18
            " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
19
            " WHERE o.apiKey = ?",
20
        apiKey, (err, orderRows) => {
21 4
            if (err) {
22
                return res.status(500).json({
23
                    errors: {
24
                        status: 500,
25
                        source: "/orders",
26
                        title: "Database error",
27
                        detail: err.message
28
                    }
29
                });
30
            }
31
32 4
            if (orderRows.length === 0) {
33 2
                return res.status(status).json(returnedOrders);
34
            }
35
36 2
            return orders.getOrderItems(
37
                res,
38
                orderRows,
39
                apiKey,
40
                status,
41
                returnedOrders
42
            );
43
        });
44
    },
45
46
    getOrderItems: function(res, orderRows, apiKey, status, returnedOrders) {
47 3
        orderRows.forEach(function(order) {
48 6
            db.all("SELECT " + orders.orderItemsDataFields + " FROM order_items oi " +
49
                "INNER JOIN products p ON oi.productId=p.ROWID AND oi.apiKey=p.apiKey" +
50
                " WHERE oi.apiKey = ? AND oi.orderId = ?",
51
            apiKey,
52
            order.id, (err, orderItemRows) => {
53 6
                if (err) {
54
                    return res.status(500).json({
55
                        errors: {
56
                            status: 500,
57
                            source: "/orders order_items",
58
                            title: "Database error",
59
                            detail: err.message
60
                        }
61
                    });
62
                }
63
64 6
                order.order_items = orderItemRows;
65 6
                returnedOrders.data.push(order);
66
67 6
                if (returnedOrders.data.length === orderRows.length) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if returnedOrders.data.length === orderRows.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
68 3
                    return res.status(status).json(returnedOrders);
69
                }
70
            });
71
        });
72
    },
73
74
    getOrder: function(res, apiKey, orderId, status=200) {
75 10
        if (Number.isInteger(parseInt(orderId))) {
76 9
            db.get("SELECT " + orders.dataFields +
77
                " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
78
                " WHERE o.apiKey = ? AND o.ROWID = ?",
79
            apiKey,
80
            orderId, (err, order) => {
81 9
                if (err) {
82
                    return res.status(500).json({
83
                        errors: {
84
                            status: 500,
85
                            source: "/order/" + orderId,
86
                            title: "Database error",
87
                            detail: err.message
88
                        }
89
                    });
90
                }
91
92 9
                if (order === undefined) {
93 1
                    return res.status(status).json({ data: {} });
94
                }
95
96 8
                order.order_items = [];
97 8
                db.each("SELECT " + orders.orderItemsDataFields + " FROM order_items oi " +
98
                    " INNER JOIN products p ON oi.productId=p.ROWID" +
99
                    " AND oi.apiKey=p.apiKey" +
100
                    " WHERE oi.apiKey = ? AND oi.orderId = ?",
101
                apiKey,
102
                order.id, (err, orderItemRow) => {
103 2
                    if (err) {
104
                        return res.status(500).json({
105
                            errors: {
106
                                status: 500,
107
                                source: "/order/" + orderId + " order_items",
108
                                title: "Database error",
109
                                detail: err.message
110
                            }
111
                        });
112
                    }
113
114 2
                    order.order_items.push(orderItemRow);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
115
                }, function () {
116 8
                    return res.status(status).json({ data: order });
117
                });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
118
            });
119
        } else {
120 1
            res.status(400).json({
121
                errors: {
122
                    status: 400,
123
                    detail: "Required attribute order id " +
124
                        " is not an integer."
125
                }
126
            });
127
        }
128
    },
129
130
    searchOrder: function(res, apiKey, query, status=200) {
131 2
        const searchQuery = "%" + query + "%";
132 2
        let returnedOrders = { data: []};
133
134 2
        db.all("SELECT " + orders.dataFields +
135
            " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
136
            " WHERE o.apiKey = ? AND" +
137
            "(customerName LIKE ? OR customerAddress LIKE ? OR customerZip LIKE ?" +
138
            " OR customerCity LIKE ? OR customerCountry LIKE ?)",
139
        apiKey,
140
        searchQuery,
141
        searchQuery,
142
        searchQuery,
143
        searchQuery,
144
        searchQuery, (err, orderRows) => {
145 2
            if (err) {
146
                return res.status(500).json({
147
                    errors: {
148
                        status: 500,
149
                        source: "/order/search/" + query,
150
                        title: "Database error",
151
                        detail: err.message
152
                    }
153
                });
154
            }
155
156 2
            if (orderRows.length === 0) {
157 1
                return res.status(status).json(returnedOrders);
158
            }
159
160 1
            return orders.getOrderItems(
161
                res,
162
                orderRows,
163
                apiKey,
164
                status,
165
                returnedOrders
166
            );
167
        });
168
    },
169
170
    addOrder: function(res, body) {
171 4
        db.run("INSERT INTO orders (customerName, customerAddress, customerZip," +
172
            " customerCity, customerCountry, statusId, apiKey) VALUES (?, ?, ?, ?, ?, ?, ?)",
173
        body.name,
174
        body.address,
175
        body.zip,
176
        body.city,
177
        body.country,
178
        body.status_id || 100,
179
        body.api_key,
180
        function(err) {
181 4
            if (err) {
182 1
                return res.status(500).json({
183
                    errors: {
184
                        status: 500,
185
                        source: "POST /order",
186
                        title: "Database error",
187
                        detail: err.message
188
                    }
189
                });
190
            }
191
192 3
            orders.getOrder(res, body.api_key, this.lastID, 201);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
193
        });
194
    },
195
196
    updateOrder: function(res, body) {
197 2
        if (Number.isInteger(parseInt(body.id))) {
198 1
            db.run("UPDATE orders SET customerName = ?," +
199
                " customerAddress = ?, customerZip = ?," +
200
                " customerCity = ?, customerCountry = ?, statusId = ?" +
201
                " WHERE apiKey = ? AND ROWID = ?",
202
            body.name,
203
            body.address,
204
            body.zip,
205
            body.city,
206
            body.country,
207
            body.status_id || 100,
208
            body.api_key,
209
            body.id, (err) => {
210 2
                if (err) {
211
                    return res.status(500).json({
212
                        errors: {
213
                            status: 500,
214
                            source: "PUT /order",
215
                            title: "Database error",
216
                            detail: err.message
217
                        }
218
                    });
219
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
220 1
                    res.status(204).send();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
221
                }
222
            });
223
        } else {
224 1
            res.status(400).json({
225
                errors: {
226
                    status: 400,
227
                    detail: "Required attribute order id (id) " +
228
                        " was not included in the request."
229
                }
230
            });
231
        }
232
    },
233
234
    deleteOrder: function(res, body) {
235 2
        if (Number.isInteger(parseInt(body.id))) {
236 1
            db.run("DELETE FROM orders WHERE apiKey = ? AND ROWID = ?",
237
                body.api_key,
238
                body.id, (err) => {
239 2
                    if (err) {
240
                        return res.status(500).json({
241
                            errors: {
242
                                status: 500,
243
                                source: "DELETE /order",
244
                                title: "Database error",
245
                                detail: err.message
246
                            }
247
                        });
248
                    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
249 1
                        db.run("DELETE FROM order_items WHERE apiKey = ? AND orderId = ?",
250
                            body.api_key,
251
                            body.id, (err) => {
252 2
                                if (err) {
253
                                    return res.status(500).json({
254
                                        errors: {
255
                                            status: 500,
256
                                            source: "DELETE /order order_items",
257
                                            title: "Database error",
258
                                            detail: err.message
259
                                        }
260
                                    });
261
                                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
262 1
                                    res.status(204).send();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
263
                                }
264
                            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
265
                    }
266
                });
267
        } else {
268 1
            res.status(400).json({
269
                errors: {
270
                    status: 400,
271
                    detail: "Required attribute order id (id) " +
272
                        " was not included in the request."
273
                }
274
            });
275
        }
276
    }
277
};
278
279
module.exports = orders;
280