1
00:00:02,190 --> 00:00:05,000
Now outputting orders is not everything

2
00:00:05,000 --> 00:00:06,290
that I added though.

3
00:00:06,290 --> 00:00:08,300
For one, I fixed a tiny issue

4
00:00:08,300 --> 00:00:10,724
in the card controller JS file.

5
00:00:10,724 --> 00:00:15,100
I added a + here in front of rec.body.quantity

6
00:00:15,100 --> 00:00:18,500
to ensure that the quantity we update an item with

7
00:00:18,500 --> 00:00:20,790
is always a number.

8
00:00:20,790 --> 00:00:23,060
Otherwise it would be treated as a string

9
00:00:23,060 --> 00:00:27,460
and this could lead to incorrectly output values here.

10
00:00:27,460 --> 00:00:29,370
For example, on the cart badge,

11
00:00:29,370 --> 00:00:31,540
if you update your card items,

12
00:00:31,540 --> 00:00:34,310
because a string would be concatenated with a number

13
00:00:34,310 --> 00:00:37,320
and you would get a string as a result instead of a number,

14
00:00:37,320 --> 00:00:38,740
we need a number here though.

15
00:00:38,740 --> 00:00:41,788
And therefore always forcing a conversion to a number

16
00:00:41,788 --> 00:00:44,190
before we update an item with a given quantity

17
00:00:44,190 --> 00:00:48,690
is a tiny fix I wanted to implement here,

18
00:00:48,690 --> 00:00:50,578
but that's not the main thing I added.

19
00:00:50,578 --> 00:00:52,777
The main thing is a different thing.

20
00:00:52,777 --> 00:00:56,970
Assume that you are a user logged in or not, doesn't matter

21
00:00:56,970 --> 00:00:58,924
and you add items to your cart.

22
00:00:58,924 --> 00:01:01,253
Now we have the keyboard in the card here.

23
00:01:02,190 --> 00:01:04,900
Now, what if that price of that keyboard changes

24
00:01:04,900 --> 00:01:09,901
whilst we have the item in the cart, but before we check out

25
00:01:11,010 --> 00:01:13,823
or what if the product is removed altogether,

26
00:01:14,860 --> 00:01:17,590
then we could theoretically buy a product

27
00:01:17,590 --> 00:01:21,580
at a incorrect price, or we buy a product

28
00:01:21,580 --> 00:01:24,800
that's actually not in the store anymore.

29
00:01:24,800 --> 00:01:28,973
Both scenarios are scenarios I'd like to avoid here.

30
00:01:30,320 --> 00:01:34,270
And for this I added a brand new method to the cart model,

31
00:01:34,270 --> 00:01:39,213
and that is the update prices method here.

32
00:01:40,420 --> 00:01:42,330
Now it is a rather large method,

33
00:01:42,330 --> 00:01:43,793
but it's not a difficult one.

34
00:01:44,740 --> 00:01:47,790
I start by finding my product IDs.

35
00:01:47,790 --> 00:01:51,720
So an array of the IDs of products that I have

36
00:01:51,720 --> 00:01:52,980
in this cart.

37
00:01:52,980 --> 00:01:54,740
For this I go through all the items

38
00:01:54,740 --> 00:01:58,070
and then with that map method, which we saw before

39
00:01:58,070 --> 00:01:59,710
in the course already,

40
00:01:59,710 --> 00:02:01,260
we pass a function to map,

41
00:02:01,260 --> 00:02:04,830
which is executed for every item and which has to return

42
00:02:04,830 --> 00:02:08,470
the trends from the value that you want to use instead

43
00:02:08,470 --> 00:02:11,009
in the newly generated array.

44
00:02:11,009 --> 00:02:12,630
And for did we get that item

45
00:02:12,630 --> 00:02:15,054
as a parameter value automatically,

46
00:02:15,054 --> 00:02:19,810
and then I simply return the ID of that item product.

47
00:02:19,810 --> 00:02:22,647
So off the product that belongs to the card item.

48
00:02:22,647 --> 00:02:25,370
And this gives me an array of product IDs and yet

49
00:02:26,540 --> 00:02:29,060
then I code the find multiple method

50
00:02:29,060 --> 00:02:33,280
on the product model to which I pass my product IDs.

51
00:02:33,280 --> 00:02:35,560
This is also a new method, which I added

52
00:02:35,560 --> 00:02:37,800
in the new product model JS file,

53
00:02:37,800 --> 00:02:40,800
which you of course find attached just as you find

54
00:02:40,800 --> 00:02:43,960
the cart model file and other files attached.

55
00:02:43,960 --> 00:02:47,168
And in the product model JS file find multiple,

56
00:02:47,168 --> 00:02:51,000
again, transforms all these IDs to convert them to

57
00:02:51,000 --> 00:02:53,670
mongodb.objectid instances.

58
00:02:53,670 --> 00:02:56,675
So I transformed this array of string IDs into

59
00:02:56,675 --> 00:03:00,710
an array of MongoDB.objectid objects.

60
00:03:00,710 --> 00:03:05,710
And then I run a query and I use the special dollar sign

61
00:03:06,740 --> 00:03:10,743
in query operator that is supported by mongodb.

62
00:03:11,840 --> 00:03:14,208
This is official mongodb query syntax

63
00:03:14,208 --> 00:03:17,237
and what I'm saying here in this line is

64
00:03:17,237 --> 00:03:21,097
I want to find all the products where the product ID

65
00:03:21,097 --> 00:03:25,763
is one of the IDs specified in a given array.

66
00:03:26,604 --> 00:03:30,950
Productids is an array of objectids of productids

67
00:03:30,950 --> 00:03:33,333
converted to objectids in the end.

68
00:03:34,330 --> 00:03:37,560
So I looked through that array and all product ids

69
00:03:37,560 --> 00:03:40,680
that are part of this array will be fetched

70
00:03:40,680 --> 00:03:42,770
or all the products that belong

71
00:03:42,770 --> 00:03:45,630
to those productids to be precise.

72
00:03:45,630 --> 00:03:48,795
And then I just convert my array of product documents

73
00:03:48,795 --> 00:03:51,170
into an array of product objects

74
00:03:51,170 --> 00:03:54,830
based on my product blueprint, that's all I'm doing here.

75
00:03:54,830 --> 00:03:57,020
So that's what find multiple does.

76
00:03:57,020 --> 00:04:00,030
And in cart model, I get a list of products

77
00:04:00,030 --> 00:04:02,440
with help of find multiple.

78
00:04:02,440 --> 00:04:06,780
Then I create a deletableCartItemProductIds helper array

79
00:04:06,780 --> 00:04:09,000
which will become important in a second.

80
00:04:09,000 --> 00:04:12,780
And then I loop through all the cart items here.

81
00:04:12,780 --> 00:04:16,700
I go through all the cart items and for every card item,

82
00:04:16,700 --> 00:04:19,899
I then find the matching product that I just fetched

83
00:04:19,899 --> 00:04:21,839
from the database again.

84
00:04:21,839 --> 00:04:25,150
So here I find a product in this product array,

85
00:04:25,150 --> 00:04:29,290
which we fetched here by using the built in find method,

86
00:04:29,290 --> 00:04:31,030
which works a bit like map,

87
00:04:31,030 --> 00:04:33,304
but which is not there to transform values,

88
00:04:33,304 --> 00:04:36,780
but to find a value in an array.

89
00:04:36,780 --> 00:04:40,344
And find takes a function which will be executed for us

90
00:04:40,344 --> 00:04:43,220
and it will be executed for every product

91
00:04:43,220 --> 00:04:45,150
in this products array.

92
00:04:45,150 --> 00:04:48,150
Hence we get the product as a parameter value

93
00:04:48,150 --> 00:04:51,160
automatically by JavaScript in that function,

94
00:04:51,160 --> 00:04:54,030
because JavaScript will call that function for us,

95
00:04:54,030 --> 00:04:56,370
for every product in the array.

96
00:04:56,370 --> 00:05:00,080
And then we have to return true or false to tell JavaScript

97
00:05:00,080 --> 00:05:03,410
if this is one of the items we wanted to find,

98
00:05:03,410 --> 00:05:07,560
and I return through here, if the ID of the product

99
00:05:07,560 --> 00:05:10,339
at which I'm currently looking at in my products array here

100
00:05:10,339 --> 00:05:14,810
is equal off the ID of the product in my cart item

101
00:05:14,810 --> 00:05:16,960
at which I'm currently looking.

102
00:05:16,960 --> 00:05:19,650
So I'm finding the updated product data

103
00:05:19,650 --> 00:05:22,870
for the card item I'm currently looking at.

104
00:05:22,870 --> 00:05:26,100
Now, of course the product data is stored in my card item,

105
00:05:26,100 --> 00:05:29,760
but the idea here is that I want to get the latest data.

106
00:05:29,760 --> 00:05:33,030
Hence I simply find the latest product data

107
00:05:33,030 --> 00:05:35,495
for the product that belongs to this card item

108
00:05:35,495 --> 00:05:38,433
from my products collection in the end.

109
00:05:39,750 --> 00:05:41,680
Now, once I identified the product

110
00:05:41,680 --> 00:05:44,795
that belongs to this card item, I continue.

111
00:05:44,795 --> 00:05:48,681
If I did not find a product, that means that

112
00:05:48,681 --> 00:05:51,330
I have a product in the card item,

113
00:05:51,330 --> 00:05:53,120
but I was not able to find it

114
00:05:53,120 --> 00:05:55,130
in the products collection anymore.

115
00:05:55,130 --> 00:05:57,290
It was probably deleted in that case

116
00:05:57,290 --> 00:06:01,823
and hence, I want to schedule it for removal from the cart.

117
00:06:01,823 --> 00:06:03,580
That's why I created

118
00:06:03,580 --> 00:06:06,753
this deletableCartItemProductIds helper array here,

119
00:06:06,753 --> 00:06:09,596
because I then push this productid

120
00:06:09,596 --> 00:06:12,450
that doesn't exist anymore in the collection

121
00:06:12,450 --> 00:06:16,062
into this array and then I use the continue keyword,

122
00:06:16,062 --> 00:06:20,020
which I also introduced briefly earlier in the course,

123
00:06:20,020 --> 00:06:22,450
which simply ensures that the next iteration

124
00:06:22,450 --> 00:06:24,930
of this four loop starts without going through

125
00:06:24,930 --> 00:06:28,140
the remaining code in that for loop first.

126
00:06:28,140 --> 00:06:31,240
So I skipped dead remaining code in that for loop

127
00:06:31,240 --> 00:06:34,173
if I scheduled a product for deletion.

128
00:06:35,450 --> 00:06:38,330
Now, we'll see what happens with these scheduled products

129
00:06:38,330 --> 00:06:40,070
in a second, for the moment,

130
00:06:40,070 --> 00:06:42,170
let's continue with the next lines of code

131
00:06:42,170 --> 00:06:45,730
and dose only run if I did find a product.

132
00:06:45,730 --> 00:06:47,163
So if the product that's stored

133
00:06:47,163 --> 00:06:50,640
or that belongs to a card item still exists

134
00:06:50,640 --> 00:06:52,443
in the product selection.

135
00:06:52,443 --> 00:06:55,760
If that's the case, I simply update the product data

136
00:06:55,760 --> 00:06:57,480
stored in the card item

137
00:06:57,480 --> 00:07:01,320
with that latest product data from the database.

138
00:07:01,320 --> 00:07:03,540
For that, I override the product stored

139
00:07:03,540 --> 00:07:05,970
in the cart item with the fetch product.

140
00:07:05,970 --> 00:07:08,428
And I update the total price of the cart item

141
00:07:08,428 --> 00:07:11,935
by taking the quantity of the product, which hasn't changed

142
00:07:11,935 --> 00:07:14,616
and multiplying it with the latest price

143
00:07:14,616 --> 00:07:17,486
which I got from the database.

144
00:07:17,486 --> 00:07:19,729
Keep in mind that cartItem.product was updated

145
00:07:19,729 --> 00:07:22,587
in the line before so when I referred to it here,

146
00:07:22,587 --> 00:07:25,043
I am referring to the latest data.

147
00:07:26,759 --> 00:07:29,410
With that, the for loop is done so I did that

148
00:07:29,410 --> 00:07:30,751
for all the cart items.

149
00:07:30,751 --> 00:07:34,770
Now, then we move on to the next chunk of code here,

150
00:07:34,770 --> 00:07:38,440
where I use this deletableCartItemProductIds array

151
00:07:38,440 --> 00:07:41,330
to now delete items from the cart for which

152
00:07:41,330 --> 00:07:43,853
the products were deleted from the database.

153
00:07:44,760 --> 00:07:47,310
This code only runs if I have at least one item

154
00:07:47,310 --> 00:07:50,490
scheduled for deletion in this helper array.

155
00:07:50,490 --> 00:07:53,100
So if it has a length of zero this code doesn't run

156
00:07:53,100 --> 00:07:56,300
but if there is at least one item in it, this code runs.

157
00:07:56,300 --> 00:07:59,445
And then here I use the filter method on the cart items,

158
00:07:59,445 --> 00:08:02,630
which has a number built in array method in JavaScript,

159
00:08:02,630 --> 00:08:03,841
just like map and find

160
00:08:03,841 --> 00:08:07,590
and just like map and find filter takes a function.

161
00:08:07,590 --> 00:08:11,560
For example, this anonymous function as a parameter value,

162
00:08:11,560 --> 00:08:14,160
and this function will be executed automatically

163
00:08:14,160 --> 00:08:17,370
by Javascript for every item in that array

164
00:08:17,370 --> 00:08:19,640
on which you call filter,

165
00:08:19,640 --> 00:08:22,170
you will then get that item automatically passed

166
00:08:22,170 --> 00:08:23,610
into this function

167
00:08:23,610 --> 00:08:26,920
once the function is executed by JavaScript,

168
00:08:26,920 --> 00:08:29,324
and then in this function, you have to return true

169
00:08:29,324 --> 00:08:31,360
if you want to keep an item,

170
00:08:31,360 --> 00:08:33,020
if it should not be filtered out

171
00:08:33,020 --> 00:08:35,969
or false if you want to drop an item.

172
00:08:35,969 --> 00:08:38,479
Filter will then return a new array

173
00:08:38,479 --> 00:08:41,703
and I set this new array as my new items array.

174
00:08:41,703 --> 00:08:43,860
And since I dropped all the items

175
00:08:43,860 --> 00:08:47,090
for which I returned false, this will then be a new array

176
00:08:47,090 --> 00:08:50,590
with less items than before, at least if I found items

177
00:08:50,590 --> 00:08:52,425
that have to be deleted.

178
00:08:52,425 --> 00:08:54,810
Now, what's my logic for determining

179
00:08:54,810 --> 00:08:56,922
whether items should be dropped or not?

180
00:08:56,922 --> 00:09:00,970
I have a look at this deletableCartItemProductIds array,

181
00:09:00,970 --> 00:09:04,350
which contains at least one item now, as we know,

182
00:09:04,350 --> 00:09:07,430
and the indexof method is another built in method

183
00:09:07,430 --> 00:09:10,637
in JavaScript that you can execute on erase,

184
00:09:10,637 --> 00:09:15,637
which allows you to search for a specific value in an array

185
00:09:15,962 --> 00:09:19,900
and it will then return to index off that value.

186
00:09:19,900 --> 00:09:23,260
And you learned indexes start at zero for erase

187
00:09:23,260 --> 00:09:26,419
and therefore then I look for a given product ID

188
00:09:26,419 --> 00:09:30,713
in this array of productids that should be deleted.

189
00:09:31,630 --> 00:09:33,970
And if I find the index here,

190
00:09:33,970 --> 00:09:36,690
so if I get a value of zero or higher,

191
00:09:36,690 --> 00:09:39,750
then I know that this productid is part of this

192
00:09:39,750 --> 00:09:42,570
deletableCartItemProductIds array,

193
00:09:42,570 --> 00:09:44,721
because I found the index.

194
00:09:44,721 --> 00:09:48,950
Now indexof will return minus one as a result,

195
00:09:48,950 --> 00:09:51,990
if it could not find a value in an array.

196
00:09:51,990 --> 00:09:53,940
And that's why I have this condition

197
00:09:53,940 --> 00:09:56,480
because then filter returns true

198
00:09:56,480 --> 00:09:59,960
if I could not find an item, a productid

199
00:09:59,960 --> 00:10:03,210
in this deletableCartItemProductIds array

200
00:10:03,210 --> 00:10:06,440
and that means this is not a product that was deleted

201
00:10:06,440 --> 00:10:08,680
so the cart items should be kept.

202
00:10:08,680 --> 00:10:11,773
That's why I then return true and on the other hand,

203
00:10:11,773 --> 00:10:13,840
this will return false this condition

204
00:10:13,840 --> 00:10:15,860
and hence the card item will be dropped.

205
00:10:15,860 --> 00:10:17,941
If I do find a productid

206
00:10:17,941 --> 00:10:21,010
in the deletableCartItemProductIds array,

207
00:10:21,010 --> 00:10:22,393
that's the logic here.

208
00:10:24,190 --> 00:10:27,980
Well then, after, since I updated card item data,

209
00:10:27,980 --> 00:10:30,326
or I may be even removed card items.

210
00:10:30,326 --> 00:10:34,590
I recalculate the cart totals by resetting

211
00:10:34,590 --> 00:10:37,057
the cart totalQuantity and price to zero

212
00:10:37,057 --> 00:10:40,033
and then by recalculating it by again,

213
00:10:40,033 --> 00:10:43,152
well, deriving the new totalQuantity

214
00:10:43,152 --> 00:10:45,630
by going through all the items here

215
00:10:45,630 --> 00:10:47,580
and increasing the totalQuantity

216
00:10:47,580 --> 00:10:49,603
by the item.quantities step-by-step.

217
00:10:49,603 --> 00:10:52,513
And I do pretty much the same for the totalPrice,

218
00:10:52,513 --> 00:10:56,703
updating the carts total price with the item.totalPrices.

219
00:10:57,559 --> 00:10:59,680
That's the idea here.

220
00:10:59,680 --> 00:11:03,580
Now that updatePrices method should therefore

221
00:11:03,580 --> 00:11:07,040
help us keep the prices in the cart updated

222
00:11:07,040 --> 00:11:10,170
and to execute this, I added a new middleware,

223
00:11:10,170 --> 00:11:12,090
the update-cart-prices middleware

224
00:11:12,090 --> 00:11:13,720
in the middleware's function,

225
00:11:13,720 --> 00:11:17,344
where I simply get my cart from res.locals.cart.

226
00:11:17,344 --> 00:11:20,680
I place it there in my other cart middleware

227
00:11:20,680 --> 00:11:22,970
where I get it from the session.

228
00:11:22,970 --> 00:11:25,710
So here I get it from res.locals.cart.

229
00:11:25,710 --> 00:11:28,153
I call updatePrices and I awaited this

230
00:11:28,153 --> 00:11:30,860
because it's a async function.

231
00:11:30,860 --> 00:11:32,450
Hence this is also async.

232
00:11:32,450 --> 00:11:34,510
And then I call next thereafter

233
00:11:35,590 --> 00:11:39,090
and then I used this middleware in app.js.

234
00:11:39,090 --> 00:11:43,270
Here I imported right where I also import

235
00:11:43,270 --> 00:11:45,600
all the other middleware functions

236
00:11:45,600 --> 00:11:48,460
and then use it right after the cart middleware

237
00:11:48,460 --> 00:11:51,210
here I use the updateCartPrices middleware,

238
00:11:51,210 --> 00:11:55,270
and that means for every request I update cart prices.

239
00:11:55,270 --> 00:11:56,740
You don't have to do it like this.

240
00:11:56,740 --> 00:11:59,000
You could also decide that you just want to do that

241
00:11:59,000 --> 00:12:02,390
whenever the cart is loaded or an order is placed,

242
00:12:02,390 --> 00:12:04,550
and you can definitely also play around with

243
00:12:04,550 --> 00:12:06,700
the logic for updating the prices.

244
00:12:06,700 --> 00:12:10,398
I just use a relatively simple straight forward approach

245
00:12:10,398 --> 00:12:13,733
so that this is hopefully quite understandable.

246
00:12:15,310 --> 00:12:18,430
Now with all of that we can of course test

247
00:12:18,430 --> 00:12:19,870
wherever that works.

248
00:12:19,870 --> 00:12:21,970
For this, I'll keep that window open

249
00:12:22,930 --> 00:12:25,170
and I opened a brand new incognito window

250
00:12:25,170 --> 00:12:27,420
where I'm therefore not logged in.

251
00:12:27,420 --> 00:12:28,886
And I will now log in

252
00:12:28,886 --> 00:12:33,453
with my administration account, like this.

253
00:12:34,620 --> 00:12:36,290
Now keep in mind, and the other account

254
00:12:36,290 --> 00:12:38,390
I have to keyboard in the cart

255
00:12:38,390 --> 00:12:41,413
and the current price is $99.99.

256
00:12:42,580 --> 00:12:44,855
In my administration account I'll now manage

257
00:12:44,855 --> 00:12:49,855
this keyboard and change the price to $109.99,

258
00:12:50,090 --> 00:12:51,700
and then saved this.

259
00:12:51,700 --> 00:12:53,543
So now here, the price was saved.

260
00:12:54,690 --> 00:12:56,678
Of course, here, I still see the old price

261
00:12:56,678 --> 00:13:00,560
because we have no a feature that would reload the page

262
00:13:00,560 --> 00:13:02,010
to user is currently on.

263
00:13:02,010 --> 00:13:04,749
But if I navigate around and come back to the cart,

264
00:13:04,749 --> 00:13:07,340
indeed, I now have the latest price here

265
00:13:07,340 --> 00:13:11,103
and the total price also was updated, as you can tell.

266
00:13:12,040 --> 00:13:13,550
So that worked.

267
00:13:13,550 --> 00:13:16,384
Now what if I delete the keyboard altogether?

268
00:13:16,384 --> 00:13:18,620
If I do that here in the admin page

269
00:13:18,620 --> 00:13:21,780
and I then reload the cart, my cart is now empty

270
00:13:21,780 --> 00:13:23,813
because that item was deleted.

271
00:13:25,420 --> 00:13:27,360
So this is now working.

272
00:13:27,360 --> 00:13:28,680
This should do the trick here,

273
00:13:28,680 --> 00:13:30,807
and this should ensure that we always see

274
00:13:30,807 --> 00:13:34,253
the latest data in our cart and also in the end

275
00:13:34,253 --> 00:13:38,293
use the latest cart when we then place an order.

