portal/modules/reports/server/work/call/methods.js

import Conversations from '/common/db/conversation';
import resultRows from '/modules/reports/server/resultRows';
import {Meteor} from 'meteor/meteor';

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.calls'(options = {}) {
		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;
		if (!options.from || !options.to) return []; // retun no options

		var baseRow = {name: '', callsMade: [], interested: [], notInterested: [], talked: [], callLater: [], notTalked: [], busy: [], noAnswer: [], rejected: [], switchedOff: [], unreachable: [], wrongNumber: []};
		var total = jp(js(baseRow)); total.name = ' Total Count';
		var baseObject = resultRows(options, baseRow);

		var query = {removed: false, type: 'outgoing', relationship: 'seller', 'talked.by': {$in: options.assignedTo}, 'talked.at': {$gte: new ServerDate(options.from.setHours(0, 0, 0, 0)), $lt: new ServerDate(options.to.setHours(24, 0, 0, 0))}};
		let pipeline = [
			{$match: query},
			{$project: {'talked.by': 1, 'talked.flag': 1, notTalkedReason: 1, status: 1}},
			{$group: {_id: {talked: '$talked.flag', talkedBy: '$talked.by', status: '$status', notTalkedReason: '$notTalkedReason'}, subjects: {$addToSet: '$group.id'}}},
		];
		switch (options.type) {
			case 'rawUnits':
				query['rawUnits.id'] = {$type: 2};
				pipeline[0].$match = query;
				pipeline[1].$project['rawUnits.id'] = 1;
				pipeline = [pipeline[0], pipeline[1],
					// need to unwind and get first as rawUnits.0.id is not working
					{$unwind: '$rawUnits'},
					{$group: {_id: '$_id', talkedFlag: {$first: '$talked.flag'}, talkedBy: {$first: '$talked.by'}, notTalkedReason: {$first: '$notTalkedReason'}, status: {$first: '$status'}, rawUnitId: {$first: '$rawUnits.id'}}},
					{$group: {_id: {talked: '$talkedFlag', talkedBy: '$talkedBy', status: '$status', notTalkedReason: '$notTalkedReason'}, subjects: {$addToSet: '$rawUnitId'}}},
				];
				break;
			case 'units':
				query['units.id'] = {$type: 2};
				pipeline[0].$match = query;
				pipeline[1].$project['units.id'] = 1;
				pipeline = [pipeline[0], pipeline[1],
					// need to unwind and get first as rawUnits.0.id is not working
					{$unwind: '$units'},
					{$group: {_id: '$_id', talkedFlag: {$first: '$talked.flag'}, talkedBy: {$first: '$talked.by'}, notTalkedReason: {$first: '$notTalkedReason'}, status: {$first: '$status'}, unitId: {$first: '$units.id'}}},
					{$group: {_id: {talked: '$talkedFlag', talkedBy: '$talkedBy', status: '$status', notTalkedReason: '$notTalkedReason'}, subjects: {$addToSet: '$unitId'}}},
				];
				break;
			case 'buyers':
				query.relationship = 'buyer'; query['group.id'] = {$type: 2}; query['request.id'] = null;
				pipeline[0].$match = query;
				pipeline[1].$project['group.id'] = 1;
				break;
			case 'requests':
				query['request.id'] = {$type: 2};
				delete query.type;
				delete query.relationship;
				pipeline[0].$match = query;
				pipeline[1].$project['request.id'] = 1;
				pipeline[2].$group.subjects.$addToSet = '$request.id';
				break;
			case 'groups':
				query.relationship = 'seller'; query['group.id'] = {$type: 2};
				pipeline[0].$match = query;
				pipeline[1].$project['group.id'] = 1;
				break;
			case 'others':
				query.relationship = {$nin: ['seller', 'buyer']};
				pipeline[0].$match = query;
				pipeline[2].$group.subjects.$addToSet = '$_id';
				break;
			default: return [];
		}

		var calls = Conversations.aggregate(pipeline);
		for (let i = 0; i < calls.length; i ++) {
			let call = calls[i];
			baseObject[call._id.talkedBy].callsMade = baseObject[call._id.talkedBy].callsMade.concat(call.subjects);
			total.callsMade = total.callsMade.concat(call.subjects);
			if (call._id.talked) {
				// for talked use statuses
				baseObject[call._id.talkedBy].talked = baseObject[call._id.talkedBy].talked.concat(call.subjects);
				total.talked = total.talked.concat(call.subjects);
				if (!baseObject[call._id.talkedBy][call._id.status]) continue;
				baseObject[call._id.talkedBy][call._id.status] = call.subjects;
				total[call._id.status] = total[call._id.status].concat(call.subjects);
			}
			else {
				// for not talked use reasons
				baseObject[call._id.talkedBy].notTalked = baseObject[call._id.talkedBy].notTalked.concat(call.subjects);
				total.notTalked = total.notTalked.concat(call.subjects);
				if (!baseObject[call._id.talkedBy][call._id.notTalkedReason]) continue;
				baseObject[call._id.talkedBy][call._id.notTalkedReason] = call.subjects;
				total[call._id.notTalkedReason] = total[call._id.notTalkedReason].concat(call.subjects);
			}
		}

		var resultData = [];
		for (const i in baseObject) if (Object.prototype.hasOwnProperty.call(baseObject, i)) resultData.push({userId: i, inactive: ((Meteor.users.findOne({_id: i}) || {}).status || {}).inactive, ...baseObject[i]});
		resultData.push({userId: null, ...total});
		return resultData;
	},
});