merchantData.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. const axios = require("axios");
  2. const bcrypt = require("bcryptjs");
  3. const Error = require("../models/error");
  4. const Merchant = require("../models/merchant");
  5. const Recipe = require("../models/recipe");
  6. const Ingredient = require("../models/ingredient");
  7. const InventoryAdjustment = require("../models/inventoryAdjustment");
  8. const token = "b48068eb-411a-918e-ea64-52007147e42c";
  9. module.exports = {
  10. //GET - Checks clover for new or deleted recipes
  11. //Returns:
  12. // merchant: Full merchant (recipe ingredients populated)
  13. // count: Number of new recipes
  14. updateRecipes: function(req, res){
  15. if(!req.session.user){
  16. req.session.error = "Must be logged in to do that";
  17. return res.redirect("/");
  18. }
  19. Merchant.findOne({_id: req.session.user})
  20. .populate("recipes")
  21. .then((merchant)=>{
  22. axios.get(`https://apisandbox.dev.clover.com/v3/merchants/${merchant.posId}/items?access_token=${token}`)
  23. .then((result)=>{
  24. let deletedRecipes = merchant.recipes.slice();
  25. for(let i = 0; i < result.data.elements.length; i++){
  26. for(let j = 0; j < deletedRecipes.length; j++){
  27. if(result.data.elements[i].id === deletedRecipes[j].posId){
  28. result.data.elements.splice(i, 1);
  29. deletedRecipes.splice(j, 1);
  30. i--;
  31. break;
  32. }
  33. }
  34. }
  35. for(let recipe of deletedRecipes){
  36. for(let i = 0; i < merchant.recipes.length; i++){
  37. if(recipe._id === merchant.recipes[i]._id){
  38. merchant.recipes.splice(i, 1);
  39. break;
  40. }
  41. }
  42. }
  43. let newRecipes = []
  44. for(let recipe of result.data.elements){
  45. let newRecipe = new Recipe({
  46. posId: recipe.id,
  47. merchant: merchant._id,
  48. name: recipe.name,
  49. ingredients: []
  50. });
  51. merchant.recipes.push(newRecipe);
  52. newRecipes.push(newRecipe);
  53. }
  54. Recipe.create(newRecipes)
  55. .catch((err)=>{
  56. let errorMessage = "There was an error and your new recipes could not be saved";
  57. let error = new Error({
  58. code: 547,
  59. displayMessage: errorMessage,
  60. error: err
  61. });
  62. error.save();
  63. return res.json(errorMessage);
  64. });
  65. merchant.save()
  66. .then((newMerchant)=>{
  67. newMerchant.populate("recipes.ingredients.ingredient").execPopulate()
  68. .then((newestMerchant)=>{
  69. merchant.password = undefined;
  70. return res.json({merchant: newestMerchant, count: result.data.elements.length});
  71. })
  72. .catch((err)=>{
  73. let errorMessage = "Unable to retrieve recipe ingredients";
  74. let error = new Error({
  75. code: 626,
  76. displayMessage: errorMessage,
  77. error: err
  78. });
  79. error.save();
  80. return res.json(errorMessage);
  81. });
  82. })
  83. .catch((err)=>{
  84. let errorMessage = "Unable to save changes from Clover";
  85. let error = new Error({
  86. code: 547,
  87. displayMessage: errorMessage,
  88. error: err
  89. });
  90. error.save();
  91. return res.json(errorMessage);
  92. });
  93. })
  94. .catch((err)=>{
  95. let errorMessage = "Unable to retrieve data from Clover";
  96. let error = new Error({
  97. code: 111,
  98. displayMessage: errorMessage,
  99. error: err
  100. });
  101. error.save();
  102. return res.json(errorMessage);
  103. });
  104. })
  105. .catch((err)=>{
  106. let errorMessage = "Unable to retrieve merchant data";
  107. let error = new Error({
  108. code: 626,
  109. displayMessage: errorMessage,
  110. error: err
  111. });
  112. error.save();
  113. return res.json(errorMessage);
  114. });
  115. },
  116. //POST - Creates a Clover merchant from all entered data
  117. //Inputs:
  118. // req.body.data: All data from frontend in form of merchant model
  119. //Redirect to "/inventory"
  120. createMerchantClover: function(req, res){
  121. let data = JSON.parse(req.body.data);
  122. data.email = data.email.toLowerCase();
  123. if(data.password.length < 15 || data.password !== data.confirmPassword){
  124. req.session.error = "Passwords must match and contain at least 15 characters";
  125. return res.redirect("/");
  126. }
  127. axios.get(`https://apisandbox.dev.clover.com/v3/merchants/${req.session.posId}?access_token=${token}`)
  128. .then((cloverMerchant)=>{
  129. req.session.posId = undefined;
  130. let salt = bcrypt.genSaltSync(10);
  131. let hash = bcrypt.hashSync(data.password, salt);
  132. let merchant = new Merchant({
  133. name: cloverMerchant.data.name,
  134. email: data.email,
  135. password: hash,
  136. pos: "clover",
  137. posId: cloverMerchant.data.id
  138. });
  139. for(let item of data.inventory){
  140. merchant.inventory.push({
  141. ingredient: item.ingredient.id,
  142. quantity: item.quantity
  143. });
  144. }
  145. for(let recipe of data.recipes){
  146. recipe.merchant = merchant._id;
  147. }
  148. Recipe.create(data.recipes)
  149. .then((recipes)=>{
  150. for(let recipe of recipes){
  151. merchant.recipes.push(recipe._id);
  152. }
  153. merchant.save()
  154. .then((merchant)=>{
  155. req.session.user = merchant._id;
  156. return res.redirect("/inventory");
  157. })
  158. .catch((err)=>{
  159. let errorMessage = "There was an error and your account could not be created";
  160. let error = new Error({
  161. code: 547,
  162. displayMessage: errorMessage,
  163. error: err
  164. });
  165. error.save();
  166. return;
  167. });
  168. })
  169. .catch((err)=>{
  170. let errorMessage = "There was an error and your recipes could not be saved";
  171. let error = new Error({
  172. code: 547,
  173. displaymessage: errorMessage,
  174. error: err
  175. });
  176. error.save();
  177. return;
  178. });
  179. })
  180. .catch((err)=>{
  181. let errorMessage = "Unable to retrieve your data from Clover";
  182. let error = new Error({
  183. code: 111,
  184. displayMessage: errorMessage,
  185. error: err
  186. });
  187. error.save();
  188. return;
  189. });
  190. },
  191. //POST - Creates a non-pos merchant from all entered data
  192. //Inputs:
  193. // req.body.data: All data from frontend in form of merchant model
  194. //Redirects to "/inventory"
  195. createMerchantNone: function(req, res){
  196. let data = JSON.parse(req.body.data);
  197. data.email = data.email.toLowerCase();
  198. if(data.password.length < 15 || data.password !== data.confirmPassword){
  199. req.session.error = "Passwords must match and contain at least 15 characters";
  200. return res.redirect("/");
  201. }
  202. let salt = bcrypt.genSaltSync(10);
  203. let hash = bcrypt.hashSync(data.password, salt);
  204. let merchant = new Merchant({
  205. name: data.name,
  206. email: data.email,
  207. password: hash,
  208. pos: "none"
  209. });
  210. for(let item of data.inventory){
  211. merchant.inventory.push({
  212. ingredient: item.ingredient.id,
  213. quantity: item.quantity
  214. });
  215. }
  216. for(let recipe of data.recipes){
  217. recipe.merchant = merchant._id;
  218. }
  219. Recipe.create(data.recipes)
  220. .then((recipes)=>{
  221. for(let recipe of recipes){
  222. merchant.recipes.push(recipe._id);
  223. }
  224. merchant.save()
  225. .then((merchant)=>{
  226. req.session.user = merchant._id;
  227. return res.redirect("/inventory");
  228. })
  229. .catch((err)=>{
  230. let errorMessage = "There was an error and your account could not be created";
  231. let error = new Error({
  232. code: 547,
  233. displayMessage: errorMessage,
  234. error: err
  235. });
  236. error.save();
  237. return;
  238. });
  239. })
  240. .catch((err)=>{
  241. let errorMessage = "There was an error while trying to save your recipes";
  242. let error = new Error({
  243. code: 547,
  244. displayMessage: errorMessage,
  245. error: err
  246. });
  247. error.save();
  248. return;
  249. });
  250. },
  251. //POST - Adds an ingredient to merchant's inventory
  252. //Inputs:
  253. // req.body: A merchant inventory item (ingredient id and quantity)
  254. //Returns:
  255. // ingredient: Newly added ingredient
  256. addMerchantIngredient: function(req, res){
  257. if(!req.session.user){
  258. req.session.error = "Must be logged in to do that";
  259. return res.redirect("/");
  260. }
  261. Merchant.findOne({_id: req.session.user})
  262. .then((merchant)=>{
  263. merchant.inventory.push(req.body);
  264. merchant.save()
  265. .then((newMerchant)=>{
  266. newMerchant.populate("inventory.ingredient", (err)=>{
  267. if(err){
  268. let errorMessage = "Ingredient updated, page refresh required to display";
  269. let error = new Error({
  270. code: 626,
  271. displayMessage: errorMessage,
  272. error: err
  273. });
  274. error.save();
  275. return res.json(errorMessage);
  276. }else{
  277. let newIngredient = newMerchant.inventory.find(i => i.ingredient._id.toString() === req.body.ingredient);
  278. return res.json(newIngredient);
  279. }
  280. });
  281. })
  282. .catch((err)=>{
  283. let errorMessage = "Unable to save new ingredient";
  284. let error = new Error({
  285. code: 547,
  286. displayMessage: errorMessage,
  287. error: err
  288. });
  289. error.save();
  290. console.log(err);
  291. return res.json(errorMessage);
  292. });
  293. })
  294. .catch((err)=>{
  295. let errorMessage = "Unable to retrieve merchant data";
  296. let error = new Error({
  297. code: 547,
  298. displayMessage: errorMessage,
  299. error: err
  300. });
  301. error.save();
  302. console.log("error2");
  303. return res.json(errorMessage);
  304. });
  305. },
  306. //POST - Removes an ingredient from the merchant's inventory
  307. //Inputs:
  308. // ingredientId: id of ingredient to remove
  309. //Returns: Nothing
  310. removeMerchantIngredient: function(req, res){
  311. if(!req.session.user){
  312. req.session.error = "Must be logged in to do that";
  313. return res.redirect("/");
  314. }
  315. Merchant.findOne({_id: req.session.user})
  316. .then((merchant)=>{
  317. for(let i = 0; i < merchant.inventory.length; i++){
  318. if(req.body.ingredientId === merchant.inventory[i]._id.toString()){
  319. merchant.inventory.splice(i, 1);
  320. break;
  321. }
  322. }
  323. merchant.save()
  324. .then((merchant)=>{
  325. return res.json(req.body);
  326. })
  327. .catch((err)=>{
  328. let errorMessage = "Unable to update ingredients";
  329. let error = new Error({
  330. code: 547,
  331. displayMessage: errorMessage,
  332. error: err
  333. });
  334. error.save();
  335. return res.json(errorMessage);
  336. });
  337. })
  338. .catch((err)=>{
  339. let errorMessage = "Unable to retrieve merchant data";
  340. let error = new Error({
  341. code: 626,
  342. displayMessage: errorMessage,
  343. error: err
  344. });
  345. error.save();
  346. return res.json(errorMessage);
  347. });
  348. },
  349. //POST - Update the quantity for a merchant inventory item
  350. //Inputs:
  351. // req.body.ingredientId: Id of ingredient to update
  352. // req.body.quantityChange: Amount to change ingredient (not the new value)
  353. //Returns: Nothing
  354. updateMerchantIngredient: function(req, res){
  355. if(!req.session.user){
  356. req.session.error = "Must be logged in to do that";
  357. return res.redirect("/");
  358. }
  359. Merchant.findOne({_id: req.session.user})
  360. .then((merchant)=>{
  361. let updateIngredient = merchant.inventory.find(i => i._id.toString() === req.body.ingredientId);
  362. updateIngredient.quantity += req.body.quantityChange;
  363. merchant.save()
  364. .then((merchant)=>{
  365. res.json(req.body.quantityChange);
  366. })
  367. .catch((err)=>{
  368. let errorMessage = "There was an error and your data could not be saved";
  369. let error = new Error({
  370. code: 547,
  371. displayMessage: errorMessage,
  372. error: err
  373. });
  374. error.save();
  375. return res.json(errorMessage);
  376. })
  377. })
  378. .catch((err)=>{
  379. let errorMessage = "There was an error and we could not retrieve your data";
  380. let error = new Error({
  381. code: 626,
  382. displayMessage: errorMessage,
  383. error: err
  384. });
  385. error.save();
  386. return res.json(errorMessage);
  387. });
  388. let invAdj = new InventoryAdjustment({
  389. date: Date.now(),
  390. merchant: req.session.user,
  391. ingredient: req.body.ingredientId,
  392. quantity: req.body.quantityChange
  393. });
  394. invAdj.save()
  395. .catch((err)=>{
  396. let error = new Error({
  397. code: 547,
  398. displayMessage: "none",
  399. error: err
  400. });
  401. error.save();
  402. });
  403. },
  404. //POST - Adds an ingredient to a recipe
  405. //Inputs:
  406. // req.body.recipeId: Id of recipe to change
  407. // req.body.item: Ingredient to add with a quantity
  408. //Returns:
  409. // recipe: Updated recipe with populated ingredients
  410. addRecipeIngredient: function(req, res){
  411. if(!req.session.user){
  412. req.session.error = "Must be logged in to do that";
  413. return res.redirect("/");
  414. }
  415. Recipe.findOne({_id: req.body.recipeId})
  416. .then((recipe)=>{
  417. recipe.ingredients.push({
  418. ingredient: req.body.item.ingredient,
  419. quantity: req.body.item.quantity
  420. });
  421. recipe.save()
  422. .then((recipe)=>{
  423. recipe.populate("ingredients.ingredient", (err)=>{
  424. if(err){
  425. let errorMessage = "Error: could not retrieve ingredients. Please refresh page to see changes";
  426. let error = new Error({
  427. code: 626,
  428. displayMessage: errorMessage,
  429. error: err
  430. });
  431. error.save();
  432. return res.json(errorMessage);
  433. }
  434. return res.json(recipe);
  435. })
  436. })
  437. .catch((err)=>{
  438. let errorMessage = "There was an error and the recipe could not be updated";
  439. let error = new Error({
  440. code: 547,
  441. displayMessage: errorMessage,
  442. error: err
  443. });
  444. error.save();
  445. return res.json(errorMessage);
  446. });
  447. })
  448. .catch((err)=>{
  449. let errorMessage = "There was an error and the recipe could not be updated"
  450. let error = new Error({
  451. code: 626,
  452. displayMessage: errorMessage,
  453. error: err
  454. });
  455. error.save();
  456. return res.json(errorMessage);
  457. });
  458. },
  459. //POST - Change quantity of a recipe's ingredient
  460. //Inputs:
  461. // req.body.recipeId: Id of recipe containing the ingredient
  462. // req.body.ingredient: The ingredient to update (_id and quantity)
  463. //Returns: Nothing
  464. updateRecipeIngredient: function(req, res){
  465. if(!req.session.user){
  466. req.session.error = "Must be logged in to do that";
  467. return res.redirect("/");
  468. }
  469. Recipe.findOne({_id: req.body.recipeId})
  470. .then((recipe)=>{
  471. for(let ingredient of recipe.ingredients){
  472. if(ingredient._id.toString() === req.body.ingredient._id){
  473. ingredient.quantity = req.body.ingredient.quantity;
  474. recipe.save()
  475. .then((recipe)=>{
  476. return res.json({});
  477. })
  478. .catch((err)=>{
  479. let errorMessage = "There was an error and the recipe could not be updated";
  480. let error = new Error({
  481. code: 547,
  482. displayMessage: errorMessage,
  483. error: err
  484. });
  485. error.save();
  486. return res.json(errorMessage);
  487. });
  488. }
  489. }
  490. })
  491. .catch((err)=>{
  492. let errorMessage = "There was an error and the recipe could not be updated";
  493. let error = new Error({
  494. code: 626,
  495. displayMessage: errorMessage,
  496. error: err
  497. });
  498. error.save();
  499. return res.json(errorMessage);
  500. });
  501. },
  502. //POST - Remove an ingredient from a recipe
  503. //Inputs:
  504. // req.body.ingredientId: Id of ingredient to be removed
  505. // req.body.recipeId: Id of recipe to remove ingredient from
  506. //Returns: Nothing
  507. removeRecipeIngredient: function(req, res){
  508. if(!req.session.user){
  509. req.session.error = "Must be logged in to do that";
  510. return res.redirect("/");
  511. }
  512. Recipe.findOne({_id: req.body.recipeId})
  513. .then((recipe)=>{
  514. for(let i = 0; i < recipe.ingredients.length; i++){
  515. if(recipe.ingredients[i]._id.toString() === req.body.ingredientId){
  516. recipe.ingredients.splice(i, 1);
  517. }
  518. }
  519. recipe.save()
  520. .then((recipe)=>{
  521. return res.json({});
  522. })
  523. .catch((err)=>{
  524. let errorMessage = "There was an error and the ingredient could not be remove from the recipe";
  525. let error = new Error({
  526. code: 547,
  527. displayMessage: errorMessage,
  528. error: err
  529. });
  530. error.save();
  531. return res.json(errorMessage);
  532. });
  533. })
  534. .catch((err)=>{
  535. let errorMessage = "There was an error and the ingredient could not be removed from the recipe";
  536. let error = new Error({
  537. code: 626,
  538. displayMessage: errorMessage,
  539. error: err
  540. });
  541. error.save();
  542. return res.json(errorMessage);
  543. });
  544. }
  545. }