Fix: APIs & Schema (#25)

Alof of API Fixes
This commit is contained in:
Sathishkumar Krishnan
2022-03-03 02:09:00 +05:30
committed by GitHub
parent 52d020717c
commit 4763da2d69
33 changed files with 1360 additions and 346 deletions

View File

@@ -1,7 +1,6 @@
const mongoose = require("mongoose");
const Item = require("../models/Item");
const WidgetFamily = require("../models/WidgetFamily");
const Inventory = require("../models/Inventory");
const {
PickItemTransaction,
PutItemTransaction,
@@ -11,11 +10,11 @@ const {
ReportItemTransaction,
AdjustItemTransaction,
} = require("../models/ItemTransaction");
const { S3 } = require("./../config/aws");
const ItemAssociation = require("../models/ItemAssociation");
const Sublevel = require("../models/Sublevel");
const { InventoryTypes, ReportItemForTypes } = require("../config/constants");
const { ReportItemForTypes } = require("../config/constants");
const { filterItems, filterItemAssociations } = require("./utils/aggregation");
module.exports = {
/**
* Gets the Item data by `id`
@@ -24,16 +23,22 @@ module.exports = {
const { id } = req.params;
if (!id) {
res.status(400).send("Missing id param");
res.status(400).send({ success: false, error: "Missing id param" });
return;
}
try {
const itemData = await Item.findById(id);
const itemData = await Item.findById(id).populate({ path: "widgetFamily", populate: "inventory" });
if (!itemData) {
res.status(404);
res.status(404).send({ success: false, error: "Item not found" });
return;
}
if (itemData.images && itemData.images.length > 0) {
itemData.images = itemData.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
res.send({ success: true, data: itemData });
} catch (error) {
next(error);
@@ -63,9 +68,16 @@ module.exports = {
countPerPalletPackage: req.body.countPerPalletPackage,
customAttributes: req.body.customAttributes,
widgetFamily: widgetFamily,
policiesMetadata: {
underStockLevelCount: req.body.policiesMetadata.underStockLevelCount,
overStockLevelCount: req.body.policiesMetadata.overStockLevelCount,
alertStockLevelCount: req.body.policiesMetadata.alertStockLevelCount,
reorderStockLevelCount: req.body.policiesMetadata.reorderStockLevelCount,
},
};
for (const key of Object.keys(item)) {
if (["customAttributes"].includes(key)) continue;
if (item[key] === undefined) {
res.status(400).send({ success: false, error: `Missing required param: "${key}"` });
return;
@@ -80,6 +92,24 @@ module.exports = {
res.status(404);
return;
}
const images = req.files;
for (let i = 0; i < images.length; i++) {
const url = await S3.uploadFile(
`item/${itemData._id.toString()}-${Date.now()}-${i}.${images[i].originalname.split(".").slice(-1).pop()}`,
images[i].path
);
itemData.images ||= [];
itemData.images.push({ url });
}
itemData.save();
if (itemData.images) {
itemData.images = itemData.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
res.send({ success: true, data: itemData });
} catch (error) {
next(error);
@@ -130,8 +160,32 @@ module.exports = {
itemData[key] = item[key];
}
}
// Removal of images
const existingImageIds = req.body.imageIds || [];
itemData.images = itemData.images.filter((image) => {
if (!image) return false;
return existingImageIds.includes(image._id.toString());
});
// Addition of images
const images = req.files;
if (images && Array.isArray(images)) {
for (let i = 0; i < images.length; i++) {
const url = await S3.uploadFile(
`item/${itemData._id.toString()}-${Date.now()}-${i}.${images[i].originalname.split(".").slice(-1).pop()}`,
images[i].path
);
itemData.images ||= [];
itemData.images.push({ url });
}
}
await itemData.save();
if (itemData.images) {
itemData.images = itemData.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
res.send({ success: true, data: itemData });
} catch (error) {
next(error);
@@ -142,75 +196,39 @@ module.exports = {
* Gets the Items data by filter
*/
getItemsByFilter: async (req, res, next) => {
let { family, type, inventory, page, perPage } = req.query;
let { family, inventory, page, perPage } = req.query;
page = page ? parseInt(page) : 0;
perPage = perPage ? parseInt(perPage) : 10;
const inventoryFilters = {};
let inventories;
let widgetFamilies;
let itemFilters;
try {
if (type && InventoryTypes.includes(type)) {
inventoryFilters["type"] = type;
}
const results = await filterItems(inventory, family, page, perPage);
if (inventory) {
inventoryFilters["_id"] = inventory;
for (const item of results[0].result) {
if (item.images) {
item.images = item.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
}
res.send({ success: true, data: results[0] });
} catch (error) {
next(error);
}
},
getItemAssociationsByFilter: async (req, res, next) => {
let { family, inventory, page, perPage } = req.query;
page = page ? parseInt(page) : 0;
perPage = perPage ? parseInt(perPage) : 10;
try {
const results = await filterItemAssociations(inventory, family, page, perPage);
if (Object.keys(inventoryFilters).length > 0) {
inventories = await Inventory.find(inventoryFilters);
for (const item of results[0].result) {
if (item.images) {
item.images = item.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
}
const widgetFamilyFilters = [];
if (inventories) {
widgetFamilyFilters.push({
inventory: { $in: inventories.map((_) => _._id) },
});
}
if (family) {
widgetFamilyFilters.push({
name: family,
});
}
if (widgetFamilyFilters.length > 0) {
widgetFamilies = await WidgetFamily.find({
$or: widgetFamilyFilters,
});
}
if (widgetFamilies) {
itemFilters = { widgetFamily: { $in: widgetFamilies.map((_) => _._id) } };
} else {
itemFilters = {};
}
const itemData = await Item.find(
itemFilters,
{
id: 1,
commonName: 1,
formalName: 1,
description: 1,
manufacturer: 1,
widgetFamily: 1,
size: 1,
color: 1,
type: 1,
unitOfMaterial: 1,
unitCost: 1,
packageCount: 1,
countPerPallet: 1,
countPerPalletPackage: 1,
customAttributes: 1,
},
{ skip: page * perPage, limit: perPage }
).populate({ path: "widgetFamily" });
if (!itemData) {
res.status(404);
return;
}
res.send({ success: true, data: itemData });
res.send({ success: true, data: results[0] });
} catch (error) {
next(error);
}
@@ -229,7 +247,7 @@ module.exports = {
return;
}
const { putQuantity, subLevel } = req.body;
const { putQuantity, subLevel, usageReason, job } = req.body;
if (!(putQuantity && putQuantity > 0) || !(subLevel && mongoose.isValidObjectId(subLevel))) {
res.status(400).send("Invalid value for putQuantity/subLevel");
return;
@@ -250,6 +268,8 @@ module.exports = {
performedBy: res.locals.user,
putQuantity: putQuantity,
subLevel: subLevelObj,
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemAssociation, itemTransaction } });
res.send({ success: true, data: { itemAssociation, itemTransaction } });
@@ -272,7 +292,7 @@ module.exports = {
return;
}
const { pickupQuantity, subLevel } = req.body;
const { pickupQuantity, subLevel, usageReason, job } = req.body;
if (!(pickupQuantity && pickupQuantity > 0) || !(subLevel && mongoose.isValidObjectId(subLevel))) {
res.status(400).send("Invalid value for pickupQuantity/subLevel");
return;
@@ -293,6 +313,8 @@ module.exports = {
performedBy: res.locals.user,
pickupQuantity: pickupQuantity,
subLevel: subLevelObj,
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemAssociation, itemTransaction } });
} catch (error) {
@@ -314,15 +336,15 @@ module.exports = {
return;
}
const { reserveQuantity, job, pickupDate } = req.body;
if (!(reserveQuantity && reserveQuantity > 0) || !(job && mongoose.isValidObjectId(job)) || !(pickupDate && Date.parse(pickupDate))) {
res.status(400).send("Invalid value for reserveQuantity/job/pickupDate");
const { reserveQuantity, job, pickupDate, usageReason } = req.body;
if (!(reserveQuantity && reserveQuantity > 0) || !(job && mongoose.isValidObjectId(job))) {
res.status(400).send("Invalid value for reserveQuantity/job");
return;
}
const itemAssociation = await ItemAssociation.findOne({ item_id: item._id, availableQuantity: { $gte: reserveQuantity } });
if (!itemAssociation) {
res.status(500).send("Quantity unavailable");
res.status(500).send({ success: false, error: "Quantity unavailable" });
return;
}
itemAssociation.reservedQuantity = itemAssociation.reservedQuantity + reserveQuantity;
@@ -335,7 +357,8 @@ module.exports = {
performedBy: res.locals.user,
reserveQuantity: reserveQuantity,
job: job,
pickupDate: Date.parse(pickupDate),
pickupDate: pickupDate ? Date.parse(pickupDate) : undefined,
usageReason: usageReason ? usageReason : "",
});
res.send({ success: true, data: { itemAssociation, itemTransaction } });
} catch (error) {
@@ -357,19 +380,17 @@ module.exports = {
return;
}
const { checkInMeterReading, hasIssue, issueDescription } = req.body;
if (!(checkInMeterReading && checkInMeterReading > 0)) {
res.status(400).send("Invalid value for checkInMeterReading");
return;
}
const { checkInMeterReading, hasIssue, issueDescription, usageReason, job } = req.body;
const itemTransaction = await CheckInItemTransaction.create({
type: "CHECK-IN",
performedOn: item,
performedBy: res.locals.user,
checkInMeterReading: checkInMeterReading,
hasIssue: hasIssue,
hasIssue: hasIssue || false,
issueDescription: hasIssue ? issueDescription : "",
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemTransaction } });
} catch (error) {
@@ -391,19 +412,15 @@ module.exports = {
return;
}
const { checkOutMeterReading, job, usageReason } = req.body;
if (!(checkOutMeterReading && checkOutMeterReading > 0) || !(job && mongoose.isValidObjectId(job))) {
res.status(400).send("Invalid value for checkOutMeterReading/job");
return;
}
const { checkOutMeterReading, usageReason, job } = req.body;
const itemTransaction = await CheckOutItemTransaction.create({
type: "CHECK-OUT",
performedOn: item,
performedBy: res.locals.user,
checkOutMeterReading: checkOutMeterReading,
job: job,
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemTransaction } });
} catch (error) {
@@ -425,7 +442,7 @@ module.exports = {
return;
}
const { reportingFor, details } = req.body;
const { reportingFor, details, usageReason, job } = req.body;
if (!(reportingFor && ReportItemForTypes.includes(reportingFor))) {
res.status(400).send("Invalid value for checkOutMeterReading/job");
return;
@@ -437,6 +454,8 @@ module.exports = {
performedBy: res.locals.user,
reportingFor: reportingFor,
details: details ? details : "",
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemTransaction } });
} catch (error) {
@@ -458,7 +477,7 @@ module.exports = {
return;
}
const { recountedQuantity, damagedQuantity, subLevel } = req.body;
const { recountedQuantity, damagedQuantity, subLevel, usageReason, job } = req.body;
if (!(recountedQuantity && recountedQuantity > 0) || !(subLevel && mongoose.isValidObjectId(subLevel))) {
res.status(400).send("Invalid value for pickupQuantity/subLevel");
return;
@@ -483,10 +502,64 @@ module.exports = {
damagedQuantity,
totalAdjustment,
newAdjustedQuantity: itemAssociation.totalQuantity,
usageReason: usageReason ? usageReason : "",
job: job,
});
res.send({ success: true, data: { itemAssociation, itemTransaction } });
} catch (error) {
next(error);
}
},
addImageToItem: async (req, res, next) => {
const { id } = req.params;
if (!mongoose.isValidObjectId(id)) {
res.status(400).send({ success: false, error: "invalid id" });
}
const item = await Item.findById(id);
if (!item) {
res.status(404).send({ success: false, error: "item not found" });
}
const image = req.file;
const url = await S3.uploadFile(`item/${item._id.toString()}-${Date.now()}-0.${image.originalname.split(".").slice(-1).pop()}`, image.path);
item.images ||= [];
item.images.push({ url });
await item.save();
if (item.images) {
item.images = item.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
res.send({ success: true, data: item });
},
removeImageFromItem: async (req, res, next) => {
const { id, image_id } = req.params;
if (!mongoose.isValidObjectId(id)) {
res.status(400).send({ success: false, error: "invalid id" });
}
if (!mongoose.isValidObjectId(image_id)) {
res.status(400).send({ success: false, error: "invalid image_id" });
}
const item = await Item.findById(id);
if (!item) {
res.status(404).send({ success: false, error: "item not found" });
}
item.images = item.images.filter((itemImage) => {
return itemImage._id.toString() != image_id;
});
await item.save();
if (item.images) {
item.images = item.images.map((_) => {
return { _id: _._id, url: S3.generatePresignedUrl(_.url) };
});
}
res.send({ success: true, data: item });
},
};