Your IP : 216.73.216.220


Current Path : /home/deltalab/PMS/partner-manager-backend/graphql/schema/
Upload File :
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,
};