merchantData.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  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. let salt = bcrypt.genSaltSync(10);
  199. let hash = bcrypt.hashSync(data.password, salt);
  200. let merchant = new Merchant({
  201. name: data.name,
  202. email: data.email,
  203. password: hash,
  204. pos: "none"
  205. });
  206. for(let item of data.inventory){
  207. merchant.inventory.push({
  208. ingredient: item.ingredient.id,
  209. quantity: item.quantity
  210. });
  211. }
  212. for(let recipe of data.recipes){
  213. recipe.merchant = merchant._id;
  214. }
  215. Recipe.create(data.recipes)
  216. .then((recipes)=>{
  217. for(let recipe of recipes){
  218. merchant.recipes.push(recipe._id);
  219. }
  220. merchant.save()
  221. .then((merchant)=>{
  222. req.session.user = merchant._id;
  223. return res.redirect("/inventory");
  224. })
  225. .catch((err)=>{
  226. let errorMessage = "There was an error and your account could not be created";
  227. let error = new Error({
  228. code: 547,
  229. displayMessage: errorMessage,
  230. error: err
  231. });
  232. error.save();
  233. return;
  234. });
  235. })
  236. .catch((err)=>{
  237. let errorMessage = "There was an error while trying to save your recipes";
  238. let error = new Error({
  239. code: 547,
  240. displayMessage: errorMessage,
  241. error: err
  242. });
  243. error.save();
  244. return;
  245. });
  246. },
  247. //POST - Adds an ingredient to merchant's inventory
  248. //Inputs:
  249. // req.body: A merchant inventory item (ingredient id and quantity)
  250. //Returns:
  251. // ingredient: Newly added ingredient
  252. addMerchantIngredient: function(req, res){
  253. if(!req.session.user){
  254. req.session.error = "Must be logged in to do that";
  255. return res.redirect("/");
  256. }
  257. Merchant.findOne({_id: req.session.user})
  258. .then((merchant)=>{
  259. merchant.inventory.push(req.body);
  260. merchant.save()
  261. .then((newMerchant)=>{
  262. newMerchant.populate("inventory.ingredient", (err)=>{
  263. if(err){
  264. let errorMessage = "Ingredient updated, page refresh required to display";
  265. let error = new Error({
  266. code: 626,
  267. displayMessage: errorMessage,
  268. error: err
  269. });
  270. error.save();
  271. return res.json(errorMessage);
  272. }else{
  273. let newIngredient = newMerchant.inventory.find(i => i.ingredient._id.toString() === req.body.ingredient);
  274. return res.json(newIngredient);
  275. }
  276. });
  277. })
  278. .catch((err)=>{
  279. let errorMessage = "Unable to save new ingredient";
  280. let error = new Error({
  281. code: 547,
  282. displayMessage: errorMessage,
  283. error: err
  284. });
  285. error.save();
  286. console.log(err);
  287. return res.json(errorMessage);
  288. });
  289. })
  290. .catch((err)=>{
  291. let errorMessage = "Unable to retrieve merchant data";
  292. let error = new Error({
  293. code: 547,
  294. displayMessage: errorMessage,
  295. error: err
  296. });
  297. error.save();
  298. console.log("error2");
  299. return res.json(errorMessage);
  300. });
  301. },
  302. //POST - Removes an ingredient from the merchant's inventory
  303. //Inputs:
  304. // ingredientId: id of ingredient to remove
  305. //Returns: Nothing
  306. removeMerchantIngredient: function(req, res){
  307. if(!req.session.user){
  308. req.session.error = "Must be logged in to do that";
  309. return res.redirect("/");
  310. }
  311. Merchant.findOne({_id: req.session.user})
  312. .then((merchant)=>{
  313. for(let i = 0; i < merchant.inventory.length; i++){
  314. if(req.body.ingredientId === merchant.inventory[i]._id.toString()){
  315. merchant.inventory.splice(i, 1);
  316. break;
  317. }
  318. }
  319. merchant.save()
  320. .then((merchant)=>{
  321. return res.json(req.body);
  322. })
  323. .catch((err)=>{
  324. let errorMessage = "Unable to update ingredients";
  325. let error = new Error({
  326. code: 547,
  327. displayMessage: errorMessage,
  328. error: err
  329. });
  330. error.save();
  331. return res.json(errorMessage);
  332. });
  333. })
  334. .catch((err)=>{
  335. let errorMessage = "Unable to retrieve merchant data";
  336. let error = new Error({
  337. code: 626,
  338. displayMessage: errorMessage,
  339. error: err
  340. });
  341. error.save();
  342. return res.json(errorMessage);
  343. });
  344. },
  345. //POST - Update the quantity for a merchant inventory item
  346. //Inputs:
  347. // req.body.ingredientId: Id of ingredient to update
  348. // req.body.quantityChange: Amount to change ingredient (not the new value)
  349. //Returns: Nothing
  350. updateMerchantIngredient: function(req, res){
  351. if(!req.session.user){
  352. req.session.error = "Must be logged in to do that";
  353. return res.redirect("/");
  354. }
  355. Merchant.findOne({_id: req.session.user})
  356. .then((merchant)=>{
  357. let updateIngredient = merchant.inventory.find(i => i._id.toString() === req.body.ingredientId);
  358. updateIngredient.quantity += req.body.quantityChange;
  359. merchant.save()
  360. .then((merchant)=>{
  361. res.json(req.body.quantityChange);
  362. })
  363. .catch((err)=>{
  364. let errorMessage = "There was an error and your data could not be saved";
  365. let error = new Error({
  366. code: 547,
  367. displayMessage: errorMessage,
  368. error: err
  369. });
  370. error.save();
  371. return res.json(errorMessage);
  372. })
  373. })
  374. .catch((err)=>{
  375. let errorMessage = "There was an error and we could not retrieve your data";
  376. let error = new Error({
  377. code: 626,
  378. displayMessage: errorMessage,
  379. error: err
  380. });
  381. error.save();
  382. return res.json(errorMessage);
  383. });
  384. let invAdj = new InventoryAdjustment({
  385. date: Date.now(),
  386. merchant: req.session.user,
  387. ingredient: req.body.ingredientId,
  388. quantity: req.body.quantityChange
  389. });
  390. invAdj.save()
  391. .catch((err)=>{
  392. let error = new Error({
  393. code: 547,
  394. displayMessage: "none",
  395. error: err
  396. });
  397. error.save();
  398. });
  399. },
  400. //POST - Adds an ingredient to a recipe
  401. //Inputs:
  402. // req.body.recipeId: Id of recipe to change
  403. // req.body.item: Ingredient to add with a quantity
  404. //Returns:
  405. // recipe: Updated recipe with populated ingredients
  406. addRecipeIngredient: function(req, res){
  407. if(!req.session.user){
  408. req.session.error = "Must be logged in to do that";
  409. return res.redirect("/");
  410. }
  411. Recipe.findOne({_id: req.body.recipeId})
  412. .then((recipe)=>{
  413. recipe.ingredients.push({
  414. ingredient: req.body.item.ingredient,
  415. quantity: req.body.item.quantity
  416. });
  417. recipe.save()
  418. .then((recipe)=>{
  419. recipe.populate("ingredients.ingredient", (err)=>{
  420. if(err){
  421. let errorMessage = "Error: could not retrieve ingredients. Please refresh page to see changes";
  422. let error = new Error({
  423. code: 626,
  424. displayMessage: errorMessage,
  425. error: err
  426. });
  427. error.save();
  428. return res.json(errorMessage);
  429. }
  430. return res.json(recipe);
  431. })
  432. })
  433. .catch((err)=>{
  434. let errorMessage = "There was an error and the recipe could not be updated";
  435. let error = new Error({
  436. code: 547,
  437. displayMessage: errorMessage,
  438. error: err
  439. });
  440. error.save();
  441. return res.json(errorMessage);
  442. });
  443. })
  444. .catch((err)=>{
  445. let errorMessage = "There was an error and the recipe could not be updated"
  446. let error = new Error({
  447. code: 626,
  448. displayMessage: errorMessage,
  449. error: err
  450. });
  451. error.save();
  452. return res.json(errorMessage);
  453. });
  454. },
  455. //POST - Change quantity of a recipe's ingredient
  456. //Inputs:
  457. // req.body.recipeId: Id of recipe containing the ingredient
  458. // req.body.ingredient: The ingredient to update (_id and quantity)
  459. //Returns: Nothing
  460. updateRecipeIngredient: function(req, res){
  461. if(!req.session.user){
  462. req.session.error = "Must be logged in to do that";
  463. return res.redirect("/");
  464. }
  465. Recipe.findOne({_id: req.body.recipeId})
  466. .then((recipe)=>{
  467. for(let ingredient of recipe.ingredients){
  468. if(ingredient._id.toString() === req.body.ingredient._id){
  469. ingredient.quantity = req.body.ingredient.quantity;
  470. recipe.save()
  471. .then((recipe)=>{
  472. return res.json({});
  473. })
  474. .catch((err)=>{
  475. let errorMessage = "There was an error and the recipe could not be updated";
  476. let error = new Error({
  477. code: 547,
  478. displayMessage: errorMessage,
  479. error: err
  480. });
  481. error.save();
  482. return res.json(errorMessage);
  483. });
  484. }
  485. }
  486. })
  487. .catch((err)=>{
  488. let errorMessage = "There was an error and the recipe could not be updated";
  489. let error = new Error({
  490. code: 626,
  491. displayMessage: errorMessage,
  492. error: err
  493. });
  494. error.save();
  495. return res.json(errorMessage);
  496. });
  497. },
  498. //POST - Remove an ingredient from a recipe
  499. //Inputs:
  500. // req.body.ingredientId: Id of ingredient to be removed
  501. // req.body.recipeId: Id of recipe to remove ingredient from
  502. //Returns: Nothing
  503. removeRecipeIngredient: function(req, res){
  504. if(!req.session.user){
  505. req.session.error = "Must be logged in to do that";
  506. return res.redirect("/");
  507. }
  508. Recipe.findOne({_id: req.body.recipeId})
  509. .then((recipe)=>{
  510. for(let i = 0; i < recipe.ingredients.length; i++){
  511. if(recipe.ingredients[i]._id.toString() === req.body.ingredientId){
  512. recipe.ingredients.splice(i, 1);
  513. }
  514. }
  515. recipe.save()
  516. .then((recipe)=>{
  517. return res.json({});
  518. })
  519. .catch((err)=>{
  520. let errorMessage = "There was an error and the ingredient could not be remove from the recipe";
  521. let error = new Error({
  522. code: 547,
  523. displayMessage: errorMessage,
  524. error: err
  525. });
  526. error.save();
  527. return res.json(errorMessage);
  528. });
  529. })
  530. .catch((err)=>{
  531. let errorMessage = "There was an error and the ingredient could not be removed from the recipe";
  532. let error = new Error({
  533. code: 626,
  534. displayMessage: errorMessage,
  535. error: err
  536. });
  537. error.save();
  538. return res.json(errorMessage);
  539. });
  540. },
  541. }