portal/modules/reports/server/work/buyer/telecaller/methods.js

import BuyerUnits from '/common/db/buyerUnit';
import IncomingRequests from '/common/db/request';
import resultRows from '/modules/reports/server/resultRows';
import {Meteor} from 'meteor/meteor';
import {check, Match} from 'meteor/check';
Meteor.methods({
	/**
	 * @param {Object} options assignedToQueryject containing from (Date), to (Date)  and assignedTo (Array of ids) fields.
	 * @summary
	 * 1. Find all required telecallers
	 * 2. Find all rawUnits assigned to those telecallers and loop on them
	 * 3. if cancelled, count as cancelled, else {
	 * 			count statuses
	 * 			count callLaters
	 * 		}
	 * 4. if (callLater)
	 * @returns {Object} reactive-table-data
	 */
	async 'reports.tcWork.buyer'(options) {
		check(options, Object);
		check(options.relationship, Match.Maybe(String));
		options.from = options.date?.[0] ? new Date(options.date[0]) : null;
		options.to = options.date?.[1] ? new Date(options.date[1]) : null;
		delete options.date;

		var baseRow = {
			name: '', 'requests-closed': [], 'requests-closedAlt': [], 'requests-open': [],
			'inception-enquired': {groups: [], ids: []},
			'inception-suggested': {groups: [], ids: []},
			'shortlisting-shortlisted': {groups: [], ids: []},
			'visit-pending': {groups: [], ids: []},
			'visit-scheduled': {groups: [], ids: []},
			'visit-completed-enq': {groups: [], ids: []},
			'visit-completed-sug': {groups: [], ids: []},
			'visit-completed': {groups: [], ids: []},
			'decision-pending-enq': {groups: [], ids: []},
			'decision-pending-sug': {groups: [], ids: []},
			'decision-pending': {groups: [], ids: []},
			'decision-visitReject-enq': {groups: [], ids: []},
			'decision-visitReject-sug': {groups: [], ids: []},
			'decision-visitReject': {groups: [], ids: []},
			'decision-interested-enq': {groups: [], ids: []},
			'decision-interested-sug': {groups: [], ids: []},
			'decision-interested': {groups: [], ids: []},
		};
		var total = jp(js(baseRow)); total.name = ' Total Count';
		// prepare the baseObject
		var baseObject = resultRows(options, baseRow);

		let dateQuery;
		if (options.from && options.to) {
			dateQuery = {$gte: new ServerDate(new Date(options.from).setHours(0, 0, 0, 0)), $lt: new ServerDate(new Date(options.to).setHours(24, 0, 0, 0))};
			// cDateQuery = {$gte: new ServerDate(new Date(options.from).setHours(-6, 0, 0, 0)), $lt: new ServerDate(new Date(options.to).setHours(18, 0, 0, 0))};
		}
		var fillData = function(units) {
			for (let i = 0; i < units.length; i ++) {
				let assignedTo = units[i]._id.assignedTo;
				let st = units[i]._id.process + '-' + units[i]._id.status;
				if (units[i].subjects) {
					baseObject[assignedTo][st] = units[i].subjects;
					total[st] = total[st].concat(units[i].subjects);
				}
				else {
					baseObject[assignedTo][st].groups = units[i].groups;
					baseObject[assignedTo][st].ids = units[i].ids;
					total[st].groups = total[st].groups.concat(units[i].groups);
					total[st].ids = total[st].ids.concat(units[i].ids);
				}
			}
		};

		let users = {};
		Meteor.users.find({_id: {$in: options.assignedTo}}, {fields: {'status.inactive': 1}}).fetch().map(function(u) { users[u._id] = u; });

		// total requests created
		total['requests-created'] = IncomingRequests.find({createdAt: dateQuery}).count();

		// assigned requests
		let requests = IncomingRequests.aggregate([
			{$match: {createdAt: dateQuery, 'assignedTo.userId': {$in: options.assignedTo}, 'status.duplicateOf': null}},
			{$project: {'assignedTo.userId': 1, 'status': {$cond: {if: {$eq: ['$status.open', true]}, then: 'open', else: 'closed'}}}},
			{$group: {_id: {assignedTo: '$assignedTo.userId', process: 'requests', status: '$status'}, subjects: {$addToSet: '$_id'}}},
		]);
		fillData(requests);
		requests = IncomingRequests.aggregate([
			{$match: {'status.open': false, 'status.updatedAt': dateQuery, 'assignedTo.userId': {$in: options.assignedTo}, 'status.duplicateOf': null}},
			{$project: {'assignedTo.userId': 1}},
			{$group: {_id: {assignedTo: '$assignedTo.userId', process: 'requests', status: 'closedAlt'}, subjects: {$addToSet: '$_id'}}},
		]);
		fillData(requests);

		// suggested units
		let query = {removed: false, 'processDetails.0.updatedBy': {$in: options.assignedTo}};
		if (dateQuery) query['processDetails.0.updatedAt'] = dateQuery;
		let units = BuyerUnits.aggregate([
			{$match: query},
			{$project: {processDetails: 1, 'group.id': 1}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.process': 'inception'}},
			{$group: {_id: {assignedTo: '$processDetails.updatedBy', process: '$processDetails.process', status: '$processDetails.status'}, ids: {$addToSet: '$_id'}, groups: {$addToSet: '$group.id'}}},
		]);
		fillData(units);
		let unitIds = [];
		units.map(function(it) {
			unitIds = [...unitIds, ...it.ids];
		});
		// shortlisted
		units = BuyerUnits.aggregate([
			{$match: {_id: {$in: unitIds}}},
			{$project: {processDetails: 1, 'group.id': 1}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.history.assignedTo': {$in: options.assignedTo}, 'processDetails.process': 'shortlisting', 'processDetails.stage': 'done'}},
			{$unwind: '$processDetails.history'},
			{$match: {'processDetails.history.assignedTo': {$in: options.assignedTo}, 'processDetails.process': 'shortlisting', 'processDetails.history.status': 'shortlisted'}},
			{$group: {_id: {assignedTo: '$processDetails.history.assignedTo', process: '$processDetails.process', status: '$processDetails.history.status'}, groups: {$addToSet: '$group.id'}, ids: {$addToSet: '$_id'}}},
		]);
		fillData(units);
		// visit pending
		units = BuyerUnits.aggregate([
			{$match: {_id: {$in: unitIds}}},
			{$project: {processDetails: 1, 'group.id': 1}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.process': 'visit', 'processDetails.stage': 'pending'}},
			{$unwind: '$processDetails.history'},
			{$group: {_id: '$_id', assignedTo: {$last: '$processDetails.history.assignedTo'}, groupId: {$last: '$group.id'}}},
			{$match: {'assignedTo': {$in: options.assignedTo}}},
			{$group: {_id: {assignedTo: '$assignedTo', process: 'visit', status: 'pending'}, groups: {$addToSet: '$groupId'}, ids: {$addToSet: '$_id'}}},
		]);
		fillData(units);

		// visit scheduled
		units = BuyerUnits.aggregate([
			{$match: {'processDetails.history.createdAt': dateQuery, 'processDetails.2.process': 'visit', 'processDetails.history.createdBy': {$in: options.assignedTo}, removed: false}},
			{$project: {processDetails: 1, 'group.id': 1}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.history.createdBy': {$in: options.assignedTo}, 'processDetails.history.createdAt': dateQuery, 'processDetails.process': 'visit'}},
			{$unwind: '$processDetails.history'},
			{$match: {'processDetails.history.createdBy': {$in: options.assignedTo}, 'processDetails.history.status': {$in: ['scheduled', 'rescheduled']}, 'processDetails.history.createdAt': dateQuery}},
			{$group: {_id: {assignedTo: '$processDetails.history.createdBy', process: '$processDetails.process', status: 'scheduled'}, groups: {$addToSet: '$group.id'}, ids: {$addToSet: '$_id'}}},
		]);
		fillData(units);

		// visit completed
		units = BuyerUnits.aggregate([
			{$match: {'processDetails.history.createdAt': dateQuery, 'processDetails.2.process': 'visit', 'processDetails.history.createdBy': {$in: options.assignedTo}, removed: false}},
			{$project: {processDetails: 1, 'group.id': 1, inception: {$arrayElemAt: [ '$processDetails', 0]}}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.history.assignedTo': {$in: options.assignedTo}, 'processDetails.history.createdAt': dateQuery, 'processDetails.process': 'visit'}},
			{$unwind: '$processDetails.history'},
			{$match: {'processDetails.history.assignedTo': {$in: options.assignedTo}, 'processDetails.history.status': 'completed', 'processDetails.history.createdAt': dateQuery}},
			{$project: {
				processDetails: 1,
				status: {$concat: [
					'$processDetails.history.status',
					'-',
					{$cond: [{$eq: ['$inception.status', 'enquired']}, 'enq', 'sug']},
				]},
				group: 1,
			}},
			{$group: {_id: {
				assignedTo: '$processDetails.history.assignedTo',
				process: '$processDetails.process',
				status: '$status',
			}, ids: {$addToSet: '$_id'}, groups: {$addToSet: '$group.id'}}},
		]);
		fillData(units);
		unitIds = [];
		units.map(function(it) {
			unitIds = [...unitIds, ...it.ids];
		});
		// decision
		units = BuyerUnits.aggregate([
			{$match: {_id: {$in: unitIds}}},
			{$project: {processDetails: 1, 'group.id': 1, inception: {$arrayElemAt: [ '$processDetails', 0]}}},
			{$unwind: '$processDetails'},
			{$match: {'processDetails.process': 'decision'}},
			{$unwind: '$processDetails.history'},
			{$group: {
				_id: '$_id',
				status: {$first: '$processDetails.status'},
				stage: {$first: '$processDetails.stage'},
				assignedTo: {$first: '$processDetails.history.assignedTo'},
				groupId: {$first: '$group.id'},
				inception: {$first: '$inception'},
			}},
			{$match: {'assignedTo': {$in: options.assignedTo}}},
			{$project: {
				assignedTo: 1,
				groupId: 1,
				status: {$concat: [
					{$cond: {if: {$eq: ['$stage', 'pending']}, then: 'pending', else: '$status'}},
					'-',
					{$cond: [{$eq: ['$inception.status', 'enquired']}, 'enq', 'sug']},
				]},
			}},
			{$group: {_id: {
				assignedTo: '$assignedTo',
				process: 'decision',
				status: '$status',
			}, ids: {$addToSet: '$_id'}, groups: {$addToSet: '$groupId'}}},
		]);
		fillData(units);

		// // decision done
		// units = BuyerUnits.aggregate([
		// 	{$match: {removed: false, 'cancellation.flag': false, 'processDetails.process': 'negotiation', 'processDetails.stage': 'pending', 'assignedTo.userId': {$in: options.assignedTo}}},
		// 	{$project: {processDetails: 1, 'group.id': 1}},
		// 	{$unwind: '$processDetails'},
		// 	{$match: {'processDetails.process': 'negotiation', 'processDetails.stage': 'pending'}},
		// 	{$unwind: '$processDetails.history'},
		// 	{$match: {'assignedTo': {$in: options.assignedTo}, 'processDetails.history.status': {$in: ['visitReject', 'interested']}, 'processDetails.history.createdAt': dateQuery}},
		// 	{$group: {_id: {assignedTo: '$processDetails.history.assignedTo', process: '$processDetails.process', status: '$processDetails.history.status'}, groups: {$addToSet: '$group.id'}, ids: {$addToSet: '$_id'}}},
		// ]);
		// fillData(units);

		// prepare resultData
		var resultData = [];

		for (let i in baseObject) {
			if (Object.prototype.hasOwnProperty.call(baseObject, i)) {
				['visit-completed', 'decision-pending', 'decision-visitReject', 'decision-interested'].map(st => {
					baseObject[i][st].ids = [...new Set([...baseObject[i][`${st}-enq`].ids, ...baseObject[i][`${st}-sug`].ids])];
					baseObject[i][st].groups = [...new Set([...baseObject[i][`${st}-enq`].groups, ...baseObject[i][`${st}-sug`].groups])];
					total[st].groups = total[st].groups.concat(baseObject[i][st].groups);
					total[st].ids = total[st].ids.concat(baseObject[i][st].ids);
				});
				resultData.push({userId: i, inactive: (users[i]?.status || {}).inactive, ...baseObject[i]});
			}
		}
		resultData.push({userId: null, ...total});
		return resultData;
	},
});