Merchant.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. class Ingredient{
  2. constructor(id, name, category, unit, quantity){
  3. if(this.validate(name, category, unit, quantity)){
  4. this.id = id;
  5. this.name = name;
  6. this.category = category;
  7. this.unit = unit;
  8. this.quantity = quantity
  9. }
  10. }
  11. validate(name, category, unit, quantity, createBanner = true){
  12. let errors = [];
  13. if(!isSanitary(name) ||
  14. !isSanitary(category) ||
  15. !isSanitary(unit)){
  16. errors.push("Contains illegal characters");
  17. }
  18. if(isNaN(quantity) || quantity === ""){
  19. errors.push("Must enter a valid number");
  20. }
  21. if(quantity < 0){
  22. banner.createError("Quantity cannot be a negative number");
  23. }
  24. if(errors.length > 0){
  25. if(createBanner){
  26. for(let i = 0; i < errors.length; i++){
  27. banner.createError(errors[i]);
  28. }
  29. }
  30. return false;
  31. }
  32. return true;
  33. }
  34. }
  35. class Recipe{
  36. constructor(name, price, ingredients){
  37. this.name = name;
  38. this.price = price
  39. this.ingredients = ingredients;
  40. }
  41. }
  42. class Merchant{
  43. constructor(oldMerchant, transactions){
  44. this.name = oldMerchant.name;
  45. this.inventory = [];
  46. this.recipes = [];
  47. this.transactions = [];
  48. for(let i = 0; i < oldMerchant.inventory.length; i++){
  49. this.inventory.push(new Ingredient(
  50. oldMerchant.inventory[i].ingredient._id,
  51. oldMerchant.inventory[i].ingredient.name,
  52. oldMerchant.inventory[i].ingredient.category,
  53. oldMerchant.inventory[i].ingredient.unit,
  54. oldMerchant.inventory[i].quantity
  55. ));
  56. }
  57. for(let i = 0; i < oldMerchant.recipes.length; i++){
  58. let newRecipe = {
  59. name: oldMerchant.recipes[i].name,
  60. price: oldMerchant.recipes[i].price,
  61. ingredients: [],
  62. }
  63. for(let j = 0; j < oldMerchant.recipes[i].ingredients.length; j++){
  64. for(let k = 0; k < this.inventory.length; k++){
  65. if(oldMerchant.recipes[i].ingredients[j].ingredient._id === this.inventory[k].id){
  66. newRecipe.ingredients.push({
  67. ingredient: this.inventory[k],
  68. quantity: oldMerchant.recipes[i].ingredients[j].quantity
  69. });
  70. break;
  71. }
  72. }
  73. }
  74. }
  75. for(let i = 0; i < transactions.length; i++){
  76. this.transactions.push(new Transaction(
  77. transactions[i].date,
  78. transactions[i].recipes
  79. ));
  80. }
  81. }
  82. /*
  83. Updates all specified item in the merchant's inventory and updates the page
  84. If ingredient doesn't exist, add it
  85. Inputs:
  86. Array of objects
  87. id: id of ingredient
  88. quantityChange: change in quantity (if not removing)
  89. name: name of ingredient (only for new ingredient)
  90. category: category of ingredient (only for new ingredient)
  91. unit: unit of measurement (only for new ingredient)
  92. remove: if true, remove ingredient from inventory
  93. */
  94. addIngredients(ingredients, remove = false){
  95. for(let i = 0; i < ingredients.length; i++){
  96. let isNew = true;
  97. for(let j = 0; j < merchant.inventory.length; j++){
  98. if(merchant.inventory[j].ingredient._id === ingredients[i].id){
  99. if(remove){
  100. merchant.inventory.splice(j, 1);
  101. }else{
  102. merchant.inventory[j].quantity += ingredients[i].quantity;
  103. }
  104. isNew = false;
  105. break;
  106. }
  107. }
  108. if(isNew){
  109. merchant.inventory.push({
  110. ingredient: {
  111. _id: ingredients[i].id,
  112. category: ingredients[i].category,
  113. name: ingredients[i].name,
  114. unit: ingredients[i].unit
  115. },
  116. quantity: parseFloat(ingredients[i].quantityChange)
  117. });
  118. }
  119. }
  120. homeStrandObj.drawInventoryCheckCard();
  121. ingredientsStrandObj.populateByProperty("category");
  122. addIngredientsComp.isPopulated = false;
  123. closeSidebar();
  124. }
  125. /*
  126. Updates a recipe in the merchants list of recipes
  127. Can create, edit or remove
  128. Inputs:
  129. recipe: object
  130. _id: id of recipe
  131. name: name of recipe
  132. price: price of recipe
  133. ingredients: list of ingredients
  134. ingredient: id of ingredient
  135. quantity: quantity of ingredient
  136. remove: if true, remove ingredient from inventory
  137. */
  138. addRecipe(recipe, remove = false){
  139. let isNew = true;
  140. let index = 0;
  141. for(let i = 0; i < recipe.ingredients.length; i++){
  142. for(let j = 0; j < merchant.inventory.length; j++){
  143. if(merchant.inventory[j].ingredient._id === recipe.ingredients[i].ingredient){
  144. recipe.ingredients[i].ingredient = merchant.inventory[j].ingredient;
  145. break;
  146. }
  147. }
  148. }
  149. for(let i = 0; i < merchant.recipes.length; i++){
  150. if(recipe._id === merchant.recipes[i]._id){
  151. if(remove){
  152. merchant.recipes.splice(i, 1);
  153. }else{
  154. merchant.recipes[i] = recipe;
  155. index = i;
  156. }
  157. isNew = false;
  158. break;
  159. }
  160. }
  161. if(isNew){
  162. merchant.recipes.push(recipe);
  163. index = merchant.recipes.length - 1;
  164. }
  165. recipeBookStrandObj.populateRecipes();
  166. closeSidebar();
  167. }
  168. /*
  169. Gets the indices of two dates from transactions
  170. Inputs
  171. from: starting date
  172. to: ending date (default to now)
  173. Output
  174. Array containing starting index and ending index
  175. Note: Will return false if it cannot find both necessary dates
  176. */
  177. getTransactionIndices(from, to = new Date()){
  178. let indices = [];
  179. for(let i = 0; i < this.transactions.length; i++){
  180. if(this.transactions[i].date > from){
  181. indices.push(i);
  182. break;
  183. }
  184. }
  185. for(let i = this.transactions.length - 1; i >=0; i--){
  186. if(this.transactions[i].date < to){
  187. indices.push(i);
  188. break;
  189. }
  190. }
  191. if(indices.length < 2){
  192. return false;
  193. }
  194. return indices;
  195. }
  196. calculateRevenue(indices){
  197. let total = 0;
  198. for(let i = indices[0]; i <= indices[1]; i++){
  199. for(let j = 0; j < this.transactions[i].recipes.length; j++){
  200. for(let k = 0; k < this.recipes.length; k++){
  201. if(this.transactions[i].recipes[j].recipe === this.recipes[k]._id){
  202. total += this.transactions[i].recipes[j].quantity * this.recipes[k].price;
  203. }
  204. }
  205. }
  206. }
  207. return total / 100;
  208. }
  209. }
  210. class Order{
  211. constructor(date, ingredients){
  212. this.date = date;
  213. this.ingredients = ingredients;
  214. }
  215. }
  216. class Transaction{
  217. constructor(date, recipes){
  218. this.date = new Date(date);
  219. this.recipes = recipes;
  220. }
  221. }
  222. let isSanitary = (str, createBanner = true)=>{
  223. let disallowed = ["\\", "<", ">", "$", "{", "}", "(", ")"];
  224. for(let char of disallowed){
  225. if(str.includes(char)){
  226. if(createBanner){
  227. banner.createError("Your string contains illegal characters");
  228. }
  229. return false;
  230. }
  231. }
  232. return true;
  233. }