merchantData.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. const Merchant = require("../models/merchant");
  2. const Recipe = require("../models/recipe");
  3. const InventoryAdjustment = require("../models/inventoryAdjustment");
  4. const helper = require("./helper.js");
  5. const axios = require("axios");
  6. const bcrypt = require("bcryptjs");
  7. module.exports = {
  8. /*
  9. POST - Create a new merchant with no POS system
  10. req.body = {
  11. name: retaurant name,
  12. email: registration email,
  13. password: password,
  14. confirmPassword: confirmation password
  15. }
  16. Redirects to /dashboard
  17. */
  18. createMerchantNone: async function(req, res){
  19. if(req.body.password.length < 10){
  20. throw "PASSWORD MUST CONTAIN AT LEAST 10 CHARACTERS";
  21. }
  22. if(req.body.password !== req.body.confirmPassword){
  23. throw "PASSWORDS DO NOT MATCH";
  24. }
  25. const merchantFind = await Merchant.findOne({email: req.body.email.toLowerCase()});
  26. if(merchantFind !== null){
  27. throw "USER WITH THIS EMAIL ADDRESS ALREADY EXISTS";
  28. }
  29. let salt = bcrypt.genSaltSync(10);
  30. let hash = bcrypt.hashSync(req.body.password, salt);
  31. let merchant = new Merchant({
  32. name: req.body.name,
  33. email: req.body.email.toLowerCase(),
  34. password: hash,
  35. pos: "none",
  36. lastUpdatedTime: Date.now(),
  37. createdAt: Date.now(),
  38. status: ["unverified"],
  39. inventory: [],
  40. recipes: [],
  41. verifyId: helper.generateId(15)
  42. });
  43. merchant.save()
  44. .then((merchant)=>{
  45. return res.redirect(`/verify/email/${merchant._id}`);
  46. })
  47. .catch((err)=>{
  48. if(typeof(err) === "string"){
  49. req.session.error = err;
  50. }else if(err.name === "ValidationError"){
  51. req.session.error = err.errors.name.properties.message;
  52. }else{
  53. req.session.error = "ERROR: UNABLE TO CREATE ACCOUNT AT THIS TIME";
  54. }
  55. return res.redirect("/");
  56. });
  57. },
  58. /*
  59. POST - Creates new Clover merchant
  60. Redirects to /dashboard
  61. */
  62. createMerchantClover: async function(req, res){
  63. let merchant = {}
  64. axios.get(`${process.env.CLOVER_ADDRESS}/v3/merchants/${req.session.merchantId}?access_token=${req.session.accessToken}`)
  65. .then((response)=>{
  66. merchant = new Merchant({
  67. name: response.data.name,
  68. pos: "clover",
  69. posId: req.session.merchantId,
  70. posAccessToken: req.session.accessToken,
  71. lastUpdatedTime: Date.now(),
  72. createdAt: Date.now(),
  73. inventory: [],
  74. recipes: []
  75. });
  76. return axios.get(`${process.env.CLOVER_ADDRESS}/v3/merchants/${req.session.merchantId}/items?access_token=${req.session.accessToken}`);
  77. })
  78. .then((response)=>{
  79. let recipes = [];
  80. for(let i = 0; i < response.data.elements.length; i++){
  81. let recipe = new Recipe({
  82. posId: response.data.elements[i].id,
  83. merchant: merchant,
  84. name: response.data.elements[i].name,
  85. price: response.data.elements[i].price,
  86. ingredients: []
  87. });
  88. recipes.push(recipe);
  89. merchant.recipes.push(recipe);
  90. }
  91. Recipe.create(recipes).catch((err)=>{});
  92. return merchant.save();
  93. })
  94. .then((newMerchant)=>{
  95. req.session.accessToken = undefined;
  96. req.session.user = newMerchant._id;
  97. return res.redirect("/dashboard");
  98. })
  99. .catch((err)=>{
  100. if(typeof(err) === "string"){
  101. req.session.error = err;
  102. }else if(err.name === "ValidationError"){
  103. req.session.error = err.errors.name.properties.message;
  104. }else{
  105. req.session.error = "ERROR: UNABLE TO RETRIEVE DATA FROM CLOVER";
  106. }
  107. return res.redirect("/");
  108. });
  109. },
  110. createMerchantSquare: function(req, res){
  111. let merchant = {}
  112. axios.get(`${process.env.SQUARE_ADDRESS}/v2/merchants/${req.session.merchantId}`, {
  113. headers: {
  114. Authorization: `Bearer ${req.session.accessToken}`
  115. }
  116. })
  117. .then((response)=>{
  118. req.session.merchantId = undefined;
  119. return new Merchant({
  120. name: response.data.merchant.business_name,
  121. pos: "square",
  122. posId: response.data.merchant.id,
  123. posAccessToken: req.session.accessToken,
  124. lastUpdatedTime: new Date(),
  125. createdAt: new Date(),
  126. squareLocation: response.data.merchant.main_location_id,
  127. inventory: [],
  128. recipes: []
  129. });
  130. })
  131. .then((newMerchant)=>{
  132. req.session.accessToken = undefined;
  133. merchant = newMerchant;
  134. return axios.post(`${process.env.SQUARE_ADDRESS}/v2/catalog/search`, {
  135. object_types: ["ITEM"]
  136. }, {
  137. headers: {
  138. Authorization: `Bearer ${merchant.posAccessToken}`
  139. }
  140. });
  141. })
  142. .then((response)=>{
  143. let recipes = [];
  144. for(let i = 0; i < response.data.objects.length; i++){
  145. if(response.data.objects[i].item_data.variations.length > 1){
  146. for(let j = 0; j < response.data.objects[i].item_data.variations.length; j++){
  147. let recipe = new Recipe({
  148. posId: response.data.objects[i].item_data.variations[j].id,
  149. merchant: merchant._id,
  150. name: `${response.data.objects[i].item_data.name} '${response.data.objects[i].item_data.variations[j].item_variation_data.name}'`,
  151. price: response.data.objects[i].item_data.variations[j].item_variation_data.price_money.amount
  152. });
  153. recipes.push(recipe);
  154. merchant.recipes.push(recipe);
  155. }
  156. }else{
  157. let recipe = new Recipe({
  158. posId: response.data.objects[i].item_data.variations[0].id,
  159. merchant: merchant._id,
  160. name: response.data.objects[i].item_data.name,
  161. price: response.data.objects[i].item_data.variations[0].item_variation_data.price_money.amount,
  162. ingredients: []
  163. });
  164. recipes.push(recipe);
  165. merchant.recipes.push(recipe);
  166. }
  167. }
  168. return Recipe.create(recipes);
  169. })
  170. .then((recipes)=>{
  171. return merchant.save();
  172. })
  173. .then((merchant)=>{
  174. req.session.user = merchant._id;
  175. return res.redirect("/dashboard");
  176. })
  177. .catch((err)=>{
  178. if(typeof(err) === "string"){
  179. req.session.error = err;
  180. }else if(err.name === "ValidationError"){
  181. req.session.error = err.errors.name.properties.message;
  182. }else{
  183. req.session.error = "ERROR: UNABLE TO CREATE NEW USER";
  184. }
  185. return res.redirect("/");
  186. });
  187. },
  188. /*
  189. POST - Update the quantity for a merchant inventory item
  190. req.body = [{
  191. id: id of ingredient to update,
  192. quantity: change in quantity
  193. }]
  194. */
  195. updateMerchantIngredient: function(req, res){
  196. if(!req.session.user){
  197. req.session.error = "MUST BE LOGGED IN TO DO THAT";
  198. return res.redirect("/");
  199. }
  200. let adjustments = [];
  201. let changedIngredients = [];
  202. Merchant.findOne({_id: req.session.user})
  203. .populate("inventory.ingredient")
  204. .then((merchant)=>{
  205. for(let i = 0; i < req.body.length; i++){
  206. let updateIngredient;
  207. for(let j = 0; j < merchant.inventory.length; j++){
  208. if(merchant.inventory[j].ingredient._id.toString() === req.body[i].id){
  209. updateIngredient = merchant.inventory[j];
  210. break;
  211. }
  212. }
  213. adjustments.push(new InventoryAdjustment({
  214. date: Date.now(),
  215. merchant: req.session.user,
  216. ingredient: req.body[i].id,
  217. quantity: req.body[i].quantity - updateIngredient.quantity,
  218. }));
  219. updateIngredient.quantity = helper.convertQuantityToBaseUnit(req.body[i].quantity, updateIngredient.defaultUnit);
  220. changedIngredients.push(updateIngredient);
  221. }
  222. return merchant.save();
  223. })
  224. .then((newMerchant)=>{
  225. res.json(changedIngredients);
  226. InventoryAdjustment.create(adjustments).catch(()=>{});
  227. return;
  228. })
  229. .catch((err)=>{
  230. if(typeof(err) === "string"){
  231. return res.json(err);
  232. }
  233. if(err.name === "ValidationError"){
  234. return res.json(err.errors.name.properties.message);
  235. }
  236. return res.json("ERROR: UNABLE TO UPDATE DATA");
  237. });
  238. },
  239. /*
  240. POST - Changes the users password
  241. req.body = {
  242. pass: new password,
  243. confirmPass: new password confirmation,
  244. hash: hashed version of old password
  245. }
  246. */
  247. updatePassword: function(req, res){
  248. Merchant.findOne({password: req.body.hash})
  249. .then((merchant)=>{
  250. if(merchant){
  251. if(req.body.pass.length < 10){
  252. throw "PASSWORD MUST CONTAIN AT LEAST 10 CHARACTERS";
  253. }
  254. if(req.body.pass !== req.body.confirmPass){
  255. throw "PASSWORDS DO NOT MATCH";
  256. }
  257. let salt = bcrypt.genSaltSync(10);
  258. let hash = bcrypt.hashSync(req.body.pass, salt);
  259. merchant.password = hash;
  260. return merchant.save();
  261. }else{
  262. req.session.error = "ERROR: UNABLE TO RETRIEVE USER DATA";
  263. return res.redirect("/");
  264. }
  265. })
  266. .then((merchant)=>{
  267. req.session.error = "PASSWORD SUCCESSFULLY RESET. PLEASE LOG IN";
  268. return res.redirect("/");
  269. })
  270. .catch((err)=>{
  271. if(typeof(err) === "string"){
  272. return res.json(err);
  273. }
  274. if(err.name === "ValidationError"){
  275. return res.json(err.errors.name.properties.message);
  276. }
  277. return res.json("ERROR: UNABLE TO UPDATE YOUR PASSWORD");
  278. });
  279. }
  280. }