• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atlp-rwanda / e-commerce-ones-and-zeroes-bn / 678f9ce7-19a3-4f73-9aea-6daaaf86263c

24 Jul 2024 03:39PM UTC coverage: 91.324% (-0.5%) from 91.819%
678f9ce7-19a3-4f73-9aea-6daaaf86263c

Pull #70

circleci

venuste-20002
Merge pull request #63 from atlp-rwanda/ft-buyer-track-order

[ Finishes #187355122 ] Buyer should be able to track their order status
Pull Request #70: [Finishes #187355114]fixing get product for seller and updateProduct

298 of 354 branches covered (84.18%)

Branch coverage included in aggregate %.

110 of 128 new or added lines in 3 files covered. (85.94%)

4 existing lines in 2 files now uncovered.

1102 of 1179 relevant lines covered (93.47%)

3.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.32
/src/controllers/orderController.ts
1
import { Request, Response } from 'express';
2
import { db } from '../database/models';
2✔
3
import { v4 as uuidv4 } from 'uuid';
2✔
4
import stripe from '../helps/stripeConfig';
2✔
5
import { createNotification } from '../helps/notificationHelper';
2✔
6

7
class OrderController {
8
  static async createOrder(req: Request, res: Response) {
9
    try {
7✔
10
      let expectedDeliveryDate;
11
      const { productId, quantity, addressId } = req.body;
7✔
12
      if (!productId || !quantity || quantity <= 0 || !addressId) {
7✔
13
        return res
1✔
14
          .status(400)
15
          .json({ message: 'Missing or Invalid product information' });
16
      }
17
      const address = await db.Address.findByPk(addressId);
6✔
18
      if (!address) {
6✔
19
        return res.status(404).json({ message: 'No such address found' });
1✔
20
      }
21
      const product = await db.Product.findByPk(productId);
5✔
22
      if (!product) {
5✔
23
        return res.status(404).json({ message: 'No such product found' });
1✔
24
      }
25
      if (product.dataValues.quantity < quantity) {
4✔
26
        return res
1✔
27
          .status(403)
28
          .json({ message: 'Insufficient quantity in stock' });
29
      }
30

31
      const paymentIntent = await stripe.paymentIntents.create({
3✔
32
        amount: product.dataValues.price * quantity,
33
        currency: 'rwf',
34
      });
35

36
      if (req.body.expectedDeliveryDate) {
1!
NEW
37
        expectedDeliveryDate = new Date(req.body.expectedDeliveryDate);
×
38
      } else {
39
        expectedDeliveryDate = new Date();
1✔
40
        expectedDeliveryDate.setDate(expectedDeliveryDate.getDate() + 3);
1✔
41
      }
42

43
      const order = await db.Order.create({
1✔
44
        orderId: uuidv4(),
45
        userId: (req as any).user.userId,
46
        cartId: null,
47
        addressId: address.dataValues.addressId,
48
        paymentIntentId: paymentIntent.id,
49
        expectedDeliveryDate: expectedDeliveryDate,
50
      });
51

52
      const orderProduct = await db.OrderProduct.create({
1✔
53
        orderProductId: uuidv4(),
54
        orderId: order.dataValues.orderId,
55
        productId: product.dataValues.productId,
56
        quantity: quantity,
57
      });
58

59
      return res.status(200).json({ order, paymentIntent, orderProduct });
1✔
60
    } catch (error: any) {
61
      return res.status(500).json({ message: 'Failed to create order' });
2✔
62
    }
63
  }
64

65
  static async getOrder(req: Request, res: Response) {
66
    try {
3✔
67
      const { orderId } = req.params;
3✔
68
      const order: any = await db.Order.findOne({
3✔
69
        where: {
70
          orderId: orderId,
71
        },
72
        include: [
73
          {
74
            model: db.Product,
75
            through: {
76
              model: db.OrderProduct,
77
              attributes: ['quantity'],
78
            },
79
          },
80
        ],
81
      });
82
      if (!order) {
2✔
83
        return res.status(404).json({ message: 'No such order found' });
1✔
84
      }
85
      return res.status(200).json({ order });
1✔
86
    } catch (error: any) {
87
      return res.status(500).json({ message: 'Failed to get orders' });
1✔
88
    }
89
  }
90

91
  static async getAllUserOrders(req: Request, res: Response) {
92
    try {
3✔
93
      const { id } = req.params;
3✔
94
      const page = parseInt(req.query.page as string) || 1;
3!
95
      const pageSize = parseInt(req.query.pageSize as string) || 10; // Get pageSize from query params or default to 10
3!
96
      const offset = (page - 1) * pageSize;
3✔
97

98
      const user = await db.User.findOne({
3✔
99
        where: {
100
          userId: id,
101
        },
102
      });
103

104
      if (!user) {
3✔
105
        return res.status(404).json({ message: 'No such user found' });
1✔
106
      }
107

108
      const orders = await db.Order.findAll({
2✔
109
        where: {
110
          userId: user.userId,
111
        },
112
        offset: offset,
113
        limit: pageSize,
114
        include: [
115
          {
116
            model: db.Product,
117
            through: {
118
              model: db.OrderProduct,
119
              attributes: ['quantity'],
120
            },
121
          },
122
        ],
123
      });
124

125
      const totalOrders = await db.Order.count({
1✔
126
        where: {
127
          userId: id,
128
        },
129
      });
130

131
      const totalPages = Math.ceil(totalOrders / pageSize);
1✔
132

133
      res.status(200).json({
1✔
134
        orders,
135
        pagination: {
136
          currentPage: page,
137
          pageSize: pageSize,
138
          totalPages: totalPages,
139
          totalOrders: totalOrders,
140
        },
141
      });
142
    } catch (err: any) {
143
      return res.status(500).json({ message: 'Failed to get all user orders' });
1✔
144
    }
145
  }
146

147
  static async getAllOrders(req: Request, res: Response) {
148
    try {
2✔
149
      const page = parseInt(req.query.page as string) || 1;
2!
150
      const pageSize = parseInt(req.query.pageSize as string) || 10;
2!
151
      const offset = (page - 1) * pageSize;
2✔
152
      const orders = await db.Order.findAll({
2✔
153
        offset: offset,
154
        limit: pageSize,
155
      });
156
      const totalOrders: number = await db.Order.count();
1✔
157
      res.status(200).json({
1✔
158
        orders,
159
        pagination: {
160
          currentPage: page,
161
          pageSize: pageSize,
162
          totalPages: Math.ceil(totalOrders / pageSize),
163
          totalOrders: totalOrders,
164
        },
165
      });
166
    } catch (err: any) {
167
      return res.status(500).json({ message: 'Failed to get all orders' });
1✔
168
    }
169
  }
170

171
  static async confirmOrderPayment(req: Request, res: Response) {
172
    try {
4✔
173
      const { orderId } = req.params;
4✔
174
      const order: any = await db.Order.findOne({
4✔
175
        where: {
176
          orderId: orderId,
177
        },
178
        include: [
179
          {
180
            model: db.Product,
181
            through: {
182
              model: db.OrderProduct,
183
              attributes: ['quantity'],
184
            },
185
          },
186
        ],
187
      });
188
      if (!order) {
3✔
189
        return res.status(404).json({ message: 'No such order found' });
1✔
190
      }
191
      const paymentIntent = await stripe.paymentIntents.retrieve(
2✔
192
        order.dataValues.paymentIntentId,
193
      );
194
      if (!paymentIntent) {
2✔
195
        return res.status(404).json({ message: 'No such paymentIntent found' });
1✔
196
      }
197
      if (paymentIntent.status !== 'succeeded') {
1!
UNCOV
198
        return res.status(403).json({ message: 'Order was not paid for' });
×
199
      }
200

201
      //check if order is associated with a cart
202
      if (order.dataValues.cartId) {
1✔
203
        //clear the cart after checkout
204
        const cart = await db.Cart.findByPk(order.dataValues.cartId);
1✔
205
        if (!cart) {
1!
UNCOV
206
          return res.status(404).json({ message: 'No such cart found' });
×
207
        }
208
        await db.CartProduct.destroy({
1✔
209
          where: {
210
            cartId: cart.dataValues.cartId,
211
          },
212
        });
213
      }
214
      //update product quantity
215
      order.dataValues.Products.forEach((product: any) => {
1✔
216
        product.decrement('quantity', {
1✔
217
          by: product.dataValues.OrderProduct.dataValues.quantity,
218
        });
219
      });
220
      //change order payment status
221
      order.update({ paid: true }, { status: 'processing' });
1✔
222
      await createNotification(
1✔
223
        order.userId,
224
        'Order Payment Confirmed',
225
        `Your order payment has been confirmed and is now processing.`,
226
      );
227
      return res.status(200).json({ message: 'Order was successfully paid' });
1✔
228
    } catch (error: any) {
229
      return res.status(500).json({ message: 'Failed to confirm payment' });
1✔
230
    }
231
  }
232
  static async getOrderStatus(req: Request, res: Response) {
233
    try {
3✔
234
      const { orderId } = req.params;
3✔
235
      const order = await db.Order.findByPk(orderId);
3✔
236
      if (!order) {
2✔
237
        return res.status(404).json({ message: 'No such order found' });
1✔
238
      }
239
      return res.status(200).json({
1✔
240
        status: order.status,
241
        expectedDeliveryDate: order.expectedDeliveryDate,
242
      });
243
    } catch (error: any) {
244
      console.log(error);
1✔
245
      return res.status(500).json({ message: 'Failed to get order status' });
1✔
246
    }
247
  }
248

249
  static async deliverOrder(req: Request, res: Response) {
250
    try {
3✔
251
      const { orderId } = req.params;
3✔
252
      const order = await db.Order.findByPk(orderId);
3✔
253
      if (!order) {
2✔
254
        return res.status(404).json({ message: 'No such order found' });
1✔
255
      }
256
      await order.update({ status: 'delivered' });
1✔
257
      // creating a notification
258
      await createNotification(
1✔
259
        order.userId,
260
        'Order Delivered',
261
        'Your order has been delivered.',
262
      );
263
      return res.status(200).json({ message: 'Order delivered successfully' });
1✔
264
    } catch (error: any) {
265
      console.log(error);
1✔
266
      return res.status(500).json({ message: 'Failed to deliver order' });
1✔
267
    }
268
  }
269

270
  static async cancelOrder(req: Request, res: Response) {
271
    try {
3✔
272
      const { orderId } = req.params;
3✔
273
      const order = await db.Order.findByPk(orderId);
3✔
274
      if (!order) {
2✔
275
        return res.status(404).json({ message: 'No such order found' });
1✔
276
      }
277
      await order.update({ status: 'cancelled' });
1✔
278
      await createNotification(
1✔
279
        order.userId,
280
        'Order Cancelled',
281
        `Your order has been cancelled.`,
282
      );
283
      return res.status(200).json({ message: 'Order cancelled successfully' });
1✔
284
    } catch (error: any) {
285
      console.log(error);
1✔
286
      return res.status(500).json({ message: 'Failed to cancel order' });
1✔
287
    }
288
  }
289

290
  static async updateOrderStatus(req: Request, res: Response) {
291
    try {
3✔
292
      const { orderId } = req.params;
3✔
293
      const { status, expectedDeliveryDate } = req.body;
3✔
294
      const order = await db.Order.findByPk(orderId);
3✔
295
      if (!order) {
2✔
296
        return res.status(404).json({ message: 'No such order found' });
1✔
297
      }
298
      await order.update({ status, expectedDeliveryDate });
1✔
299
      // creating a notification
300
      await createNotification(
1✔
301
        order.userId,
302
        'Order Status Updated',
303
        `Your order status has been updated to ${status}.`,
304
      );
305
      return res.status(200).json({
1✔
306
        status: order.status,
307
        expectedDeliveryDate: order.expectedDeliveryDate,
308
      });
309
    } catch (error: any) {
310
      console.log(error);
1✔
311
      return res.status(500).json({ message: 'Failed to update order status' });
1✔
312
    }
313
  }
314

315
  static async failOrder(req: Request, res: Response) {
316
    try {
3✔
317
      const { orderId } = req.params;
3✔
318
      const order = await db.Order.findByPk(orderId);
3✔
319
      if (!order) {
2✔
320
        return res.status(404).json({ message: 'No such order found' });
1✔
321
      }
322
      await order.update({ status: 'failed' });
1✔
323
      await createNotification(
1✔
324
        order.userId,
325
        'Order Failed',
326
        `Your order has failed.`,
327
      );
328
      return res.status(200).json({ message: 'Order marked as failed' });
1✔
329
    } catch (error: any) {
330
      console.log(error);
1✔
331
      return res
1✔
332
        .status(500)
333
        .json({ message: 'Failed to mark order as failed' });
334
    }
335
  }
336

337
  static async refundOrder(req: Request, res: Response) {
338
    try {
3✔
339
      const { orderId } = req.params;
3✔
340
      const order = await db.Order.findByPk(orderId);
3✔
341
      if (!order) {
2✔
342
        return res.status(404).json({ message: 'No such order found' });
1✔
343
      }
344
      await order.update({ status: 'refunded' });
1✔
345
      await createNotification(
1✔
346
        order.userId,
347
        'Order Refunded',
348
        `Your order has been refunded.`,
349
      );
350
      return res.status(200).json({ message: 'Order refunded successfully' });
1✔
351
    } catch (error: any) {
352
      console.log(error);
1✔
353
      return res.status(500).json({ message: 'Failed to refund order' });
1✔
354
    }
355
  }
356

357
  static async returnOrder(req: Request, res: Response) {
358
    try {
3✔
359
      const { orderId } = req.params;
3✔
360
      const order = await db.Order.findByPk(orderId);
3✔
361
      if (!order) {
2✔
362
        return res.status(404).json({ message: 'No such order found' });
1✔
363
      }
364
      await order.update({ status: 'returned' });
1✔
365
      await createNotification(
1✔
366
        order.userId,
367
        'Order Returned',
368
        `Your order has been returned.`,
369
      );
370
      return res.status(200).json({ message: 'Order returned successfully' });
1✔
371
    } catch (error: any) {
372
      console.log(error);
1✔
373
      return res.status(500).json({ message: 'Failed to return order' });
1✔
374
    }
375
  }
376
}
377

378
export default OrderController;
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc