| Current Path : /home/deltalab/PMS/partner-manager-backend/graphql/schema/ |
| Current File : //home/deltalab/PMS/partner-manager-backend/graphql/schema/product.schema.js |
const ims = require('../../services/ims');
const auth = require('../../services/auth.js');
const { listingTC } = require('../types/listing.type');
const { partnerTC } = require('../types/partner.type');
const { productTC } = require('../types/product.type');
const { warehouseTC } = require('../types/warehouse.type');
const { categoryTC } = require('../types/category.type');
const { productModel } = require('../../models/mongoose/product');
const { warehouseModel } = require('../../models/mongoose/warehouse');
// RESOLVERS ========================================
/**
* Listing products
* Find products that belong to a listing
*/
productTC.addResolver({
kind: 'query',
name: 'getProductsByListingsID',
type: [productTC],
args: {
listings: '[MongoID]',
},
resolve: async ({ args }) => {
const list = await productModel.find({ listingIds: { $in: args.listings } }).exec();
return list;
},
});
/**
* Listing available products
* Find products that are not currently added to the listing (thus available for insertion)
*/
productTC.addResolver({
kind: 'query',
name: 'getAvailableProductsByListingsID',
type: [productTC],
args: {
listings: '[MongoID]',
},
resolve: async ({ args }) => {
const list = await productModel.find({ listingIds: { $nin: args.listings } }).exec();
return list;
},
});
/**
* Adjust availability by product ID
*
*/
productTC.addResolver({
kind: 'mutation',
name: 'setInventoryLevelByProductID',
type: productTC,
args: {
user: 'MongoID',
product: 'MongoID',
warehouse: 'MongoID',
quantity: 'Float',
},
resolve: async ({ args }) => {
let found = false;
const product = await productModel.findById(args.product);
const warehouse = await warehouseModel.findById(args.warehouse);
if (product.trackInventory) {
for (let j = 0; j < product.inventoryLevels.length; j++) {
if (product.inventoryLevels[j].warehouseId.equals(warehouse._id)) {
found = true;
console.log(`current availability: ${product.inventoryLevels[j].amount}`);
const delta = args.quantity - product.inventoryLevels[j].amount;
if (delta !== 0) {
const externalWarehouse = delta > 0 && warehouse.partnerId.toString() !== args.user;
if (externalWarehouse) {
console.log('diminuisco in inventory level, dovrà essere confermata');
product.inventoryLevels[j].amount -= args.quantity;
// const quantity = await ims.adjustProductQuantity(product.imsgid, delta);
}
console.log('changed availability in warehouse ' + warehouse.name + ' by ' + delta + ', new total ' + product.inventoryLevels[j].amount);
// if (quantity) {
const totalQuantity = externalWarehouse ? args.quantity : args.quantity + delta;
console.log('aggiungo journal');
await ims.addEntryToWarehouseJournal(args.warehouse, args.product, args.user, delta, totalQuantity, delta > 0 ? 'INCREASE' : 'DECREASE', product.refrigerated, !externalWarehouse);
await product.save();
// }
}
}
}
if (!found) {
// no inventory level for this product, add it
console.log(`no warehouse ${warehouse.name} in product, adding it with ${args.quantity} starting quantity`);
product.inventoryLevels.push({ warehouseId: warehouse._id, amount: args.quantity });
await ims.addEntryToWarehouseJournal(args.warehouse, args.product, args.user, args.quantity, args.quantity, 'INITIAL', product.refrigerated);
}
}
return product;
},
});
// RELATIONS =========================================
/**
* Product's Listing relation
* This relation univocally connects a product to a listing
*/
// productTC.addRelation(
// 'listings',
// {
// resolver: () => listingTC.mongooseResolvers.findMany(),
// prepareArgs: {
// _id: source => source.listingIds
// },
// projection: { listingIds: true },
// }
// );
/**
* Product's Partner relation
* This relation univocally connects a product to a partner
*/
productTC.addRelation(
'partner',
{
resolver: () => partnerTC.mongooseResolvers.findOne(),
prepareArgs: {
_id: (source) => source.partnerId,
},
projection: { partnerId: true },
},
);
/**
* Fill in the warehouse data for the inventory
*/
const invetoryLevelsTC = productTC.getFieldTC('inventoryLevels');
invetoryLevelsTC.addRelation(
'warehouse',
{
resolver: () => warehouseTC.mongooseResolvers.findById(),
prepareArgs: {
_id: (source) => source.warehouseId,
},
projection: { warehouseId: true },
},
);
productTC.addRelation(
'category',
{
resolver: () => categoryTC.mongooseResolvers.findById(),
prepareArgs: {
_id: (source) => source.categoryId,
},
projection: { categoryId: true },
},
);
// CUSTOM RESOLVERS ==================================
/**
* Create product resolver: create the product document to Mongo and contact the IMS (async)
*/
/* productTC.addResolver({
kind: 'mutation',
name: 'productCreateOne',
type: productTC,
args: productTC.mongooseResolvers.createOne().args,
resolve: createProductToIMS(productTC.mongooseResolvers.createOne)
}); */
// QUERIES ===========================================
const productQuery = {
...auth.authenticationRequired({
productById: productTC.mongooseResolvers.findById(),
productOne: productTC.mongooseResolvers.findOne(),
productMany: productTC.mongooseResolvers.findMany(),
productCount: productTC.mongooseResolvers.count(),
getProductsByListingsID: productTC.getResolver('getProductsByListingsID'),
getAvailableProductsByListingsID: productTC.getResolver('getAvailableProductsByListingsID'),
}),
};
// MUTATIONS =========================================
const productMutation = {
...auth.authenticationRequired({
productCreateOne: ims.productCreateWrapper(productTC.mongooseResolvers.createOne()),
productUpdateById: ims.referenceUpdateWrapper(productTC.mongooseResolvers.updateById()),
productRemoveById: ims.productRemoveByIdWrapper(productTC.mongooseResolvers.removeById()),
setInventoryLevelByProductID: productTC.getResolver('setInventoryLevelByProductID'),
}),
};
// EXPORTS ===========================================
module.exports = {
productQuery,
productMutation,
};