orderData.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. const Order = require("../models/order.js");
  2. const Merchant = require("../models/merchant.js");
  3. const ObjectId = require("mongoose").Types.ObjectId;
  4. const Validator = require("./validator.js");
  5. const helper = require("./helper.js");
  6. const xlsx = require("xlsx");
  7. const fs = require("fs");
  8. module.exports = {
  9. /*
  10. GET - get the 25 most recent orders
  11. return = [
  12. _id: id of order,
  13. name: user created id for order,
  14. date: date order was created,
  15. ingredients: [{
  16. _id: unused id of this object,
  17. ingredient: id of the ingredient,
  18. price: price per unit of the ingredient,
  19. quantity: quantity of ingredient in this order
  20. }]
  21. ]
  22. */
  23. getOrders: function(req, res){
  24. if(!req.session.user){
  25. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  26. return res.redirect("/");
  27. }
  28. Order.aggregate([
  29. {$match: {merchant: ObjectId(req.session.user)}},
  30. {$sort: {date: -1}},
  31. {$limit: 25},
  32. {$project: {
  33. name: 1,
  34. date: 1,
  35. taxes: 1,
  36. fees: 1,
  37. ingredients: 1
  38. }}
  39. ])
  40. .then((orders)=>{
  41. return res.json(orders);
  42. })
  43. .catch((err)=>{
  44. return res.json("ERROR: UNABLE TO RETRIEVE YOUR ORDERS");
  45. });
  46. },
  47. /*
  48. POST - retrieves a list of transactions based on the filter
  49. req.body = {
  50. startDate: starting date to filter on,
  51. endDate: ending date to filter on,
  52. ingredients: list of recipes.to filter on
  53. }
  54. */
  55. orderFilter: function(req, res){
  56. if(!req.session.user){
  57. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  58. return res.redirect("/");
  59. }
  60. let objectifiedIngredients = [];
  61. for(let i = 0; i < req.body.ingredients.length; i++){
  62. objectifiedIngredients.push(new ObjectId(req.body.ingredients[i]));
  63. }
  64. let startDate = new Date(req.body.startDate);
  65. let endDate = new Date(req.body.endDate);
  66. endDate = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate() + 1);
  67. Order.aggregate([
  68. {$match: {
  69. merchant: new ObjectId(req.session.user),
  70. date: {
  71. $gte: startDate,
  72. $lt: endDate
  73. },
  74. ingredients: {
  75. $elemMatch: {
  76. ingredient: {
  77. $in: objectifiedIngredients
  78. }
  79. }
  80. }
  81. }},
  82. {$sort: {date: -1}}
  83. ])
  84. .then((orders)=>{
  85. return res.json(orders);
  86. })
  87. .catch((err)=>{
  88. return res.json("ERROR: UNABLE TO RETRIEVE YOUR TRANSACTIONS");
  89. });
  90. },
  91. /*
  92. POST - Creates a new order from the site
  93. req.body = {
  94. name: user created order id
  95. date: creation date
  96. ingredients: [{
  97. ingredient: id of the ingredient
  98. quantity: amount of the ingredient purchased
  99. pricePerUnit: price per gram
  100. }]
  101. }
  102. */
  103. createOrder: function(req, res){
  104. if(!req.session.user){
  105. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  106. return res.redirect("/");
  107. }
  108. let validation = Validator.order(req.body);
  109. if(validation !== true){
  110. return res.json(validation);
  111. }
  112. let newOrder = new Order(req.body);
  113. newOrder.merchant = req.session.user;
  114. newOrder.save()
  115. .then((response)=>{
  116. res.json(response);
  117. })
  118. .catch((err)=>{
  119. return res.json("ERROR: UNABLE TO SAVE ORDER");
  120. });
  121. Merchant.findOne({_id: req.session.user})
  122. .then((merchant)=>{
  123. for(let i = 0; i < req.body.ingredients.length; i++){
  124. for(let j = 0; j < merchant.inventory.length; j++){
  125. if(req.body.ingredients[i].ingredient === merchant.inventory[j].ingredient.toString()){
  126. merchant.inventory[j].quantity += parseFloat(req.body.ingredients[i].quantity);
  127. }
  128. }
  129. }
  130. return merchant.save();
  131. })
  132. .then((merchant)=>{
  133. return;
  134. })
  135. .catch(()=>{});
  136. },
  137. createFromSpreadsheet: function(req, res){
  138. if(!req.session.user){
  139. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  140. return res.redirect("/");
  141. }
  142. //read file, get the correct sheet, create array from sheet
  143. let workbook = xlsx.readFile(req.file.path);
  144. fs.unlink(req.file.path, ()=>{});
  145. let sheets = Object.keys(workbook.Sheets);
  146. let sheet = {};
  147. for(let i = 0; i < sheets.length; i++){
  148. let str = sheets[i].toLowerCase();
  149. if(str === "order" || str === "orders"){
  150. sheet = workbook.Sheets[sheets[i]];
  151. }
  152. }
  153. const array = xlsx.utils.sheet_to_json(sheet, {
  154. header: 1
  155. });
  156. //get property locations
  157. let locations = {};
  158. for(let i = 0; i < array[0].length; i++){
  159. switch(array[0][i].toLowerCase()){
  160. case "name": locations.name = i; break;
  161. case "date": locations.date = i; break;
  162. case "taxes": locations.taxes = i; break;
  163. case "fees": locations.fees = i; break;
  164. case "ingredients": locations.ingredients = i; break;
  165. case "quantity": locations.quantity = i; break;
  166. case "price": locations.price = i; break;
  167. }
  168. }
  169. let merchant = {};
  170. Merchant.findOne({_id: req.session.user})
  171. .populate("inventory.ingredient")
  172. .then((response)=>{
  173. merchant = response;
  174. let orders = [];
  175. let currentOrder = {};
  176. for(let i = 1; i < array.length; i++){
  177. if(array[i].length === 0 || array[i][locations.ingredients] === undefined){
  178. continue;
  179. }
  180. if(array[i][locations.name] !== undefined){
  181. currentOrder = {
  182. merchant: req.session.user,
  183. name: array[i][locations.name],
  184. taxes: parseInt(array[i][locations.taxes] * 100),
  185. fees: parseInt(array[i][locations.fees] * 100),
  186. ingredients: []
  187. }
  188. if(array[i][locations.date] === undefined){
  189. currentOrder.date = new Date();
  190. }else{
  191. currentOrder.date = new Date(array[i][locations.date]);
  192. }
  193. orders.push(currentOrder);
  194. }
  195. let exists = false;
  196. for(let j = 0; j < merchant.inventory.length; j++){
  197. if(merchant.inventory[j].ingredient.name.toLowerCase() === array[i][locations.ingredients].toLowerCase()){
  198. const baseQuantity = helper.convertQuantityToBaseUnit(array[i][locations.quantity], merchant.inventory[j].defaultUnit);
  199. currentOrder.ingredients.push({
  200. ingredient: merchant.inventory[j].ingredient._id,
  201. quantity: baseQuantity,
  202. pricePerUnit: helper.convertPrice(array[i][locations.price] * 100, merchant.inventory[j].defaultUnit)
  203. });
  204. merchant.inventory[j].quantity += baseQuantity;
  205. exists = true;
  206. break;
  207. }
  208. }
  209. if(exists === false){
  210. throw `CANNOT FIND INGREDIENT ${array[i][locations.ingredients]} FROM ORDER ${array[i][locations.name]}`;
  211. }
  212. }
  213. return Promise.all([Order.create(orders), merchant.save()]);
  214. })
  215. .then((response)=>{
  216. return res.json(response[0]);
  217. })
  218. .catch((err)=>{
  219. if(typeof(err) === "string"){
  220. return res.json(err);
  221. }
  222. return res.json("ERROR: UNABLE TO CREATE YOUR ORDERS");
  223. });
  224. },
  225. /*
  226. GET - Creates and sends a template xlsx for uploading orders
  227. */
  228. spreadsheetTemplate: function(req, res){
  229. if(!req.session.user){
  230. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  231. return res.redirect("/");
  232. }
  233. Merchant.findOne({_id: req.session.user})
  234. .populate("inventory.ingredient")
  235. .then((merchant)=>{
  236. let workbook = xlsx.utils.book_new();
  237. workbook.SheetNames.push("Order");
  238. let workbookData = [];
  239. workbookData.push(["Name", "Date", "Taxes", "Fees", "Ingredients", "Quantity", "Price", "<- Price Per Unit", "Ingredient Reference"]);
  240. for(let i = 0; i < merchant.inventory.length; i++){
  241. let data = ["", "", "", "", "", "", "", "", merchant.inventory[i].ingredient.name];
  242. workbookData.push(data);
  243. }
  244. workbookData[1][0] = "My Order Name";
  245. workbookData[1][1] = "2020-02-29";
  246. workbookData[1][2] = 10.99;
  247. workbookData[1][3] = 5.98;
  248. workbookData[1][4] = "Example ingredient 1";
  249. workbookData[1][5] = 100;
  250. workbookData[1][6] = 1.99;
  251. workbookData[2][4] = "Example ingredient 2";
  252. workbookData[2][5] = 55;
  253. workbookData[2][6] = 0.95;
  254. workbook.Sheets.Order = xlsx.utils.aoa_to_sheet(workbookData);
  255. xlsx.writeFile(workbook, "SublineOrder.xlsx");
  256. return res.download("SublineOrder.xlsx", (err)=>{
  257. fs.unlink("SublineOrder.xlsx", ()=>{});
  258. });
  259. })
  260. .catch((err)=>{});
  261. },
  262. /*
  263. DELETE - Remove an order from the database
  264. */
  265. removeOrder: function(req, res){
  266. if(!req.session.user){
  267. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  268. return res.redirect("/");
  269. }
  270. let merchant = {};
  271. let order = {}
  272. Merchant.findOne({_id: req.session.user})
  273. .then((response)=>{
  274. merchant = response;
  275. return Order.findOne({_id: req.params.id});
  276. })
  277. .then((response)=>{
  278. order = response;
  279. return Order.deleteOne({_id: req.params.id})
  280. })
  281. .then((response)=>{
  282. res.json({});
  283. for(let i = 0; i < order.ingredients.length; i++){
  284. for(let j = 0; j < merchant.inventory.length; j++){
  285. if(order.ingredients[i].ingredient.toString() === merchant.inventory[j].ingredient.toString()){
  286. merchant.inventory[j].quantity -= order.ingredients[i].quantity;
  287. break;
  288. }
  289. }
  290. }
  291. return merchant.save();
  292. })
  293. .catch((err)=>{
  294. return res.json("ERROR: UNABLE TO REMOVE ORDER");
  295. });
  296. }
  297. }