import {Meteor} from 'meteor/meteor';
import {check} from 'meteor/check';
import VerifiedFields from '/common/db/verifiedField';
import addSecs from '/common/utils/date/addSecs';
import {Roles} from 'meteor/alanning:roles';
Meteor.methods({
/**
* Finds all requests for a given listing id and updates the unit info, for any change in listing id that is triggered by changes in url or refreshUrl fields in the listings section(find updateListings method)
* @param {Number} listingId listing Id to query for in requests, this can also be used to query for units, if unit object is not passed i.e calling from frontend
* @param {Object} unitDetail Unit details object including id,identifier,location,saleInfo,spaces
* @returns {void}
*/
'request.updateUnitInfo'(listingId, unitDetail) {
const {default: Units} = require('/common/db/unit');
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.unitUpdate');
if (!listingId) throw new Meteor.Error(404, 'listingId not found!');
check(listingId, String);
if (!unitDetail) {
const {default: Listings} = require('/common/db/listing');
const unitId = Listings.findOne({listingId})?.doc?.id;
const {_id: id, identifier} = Units.findOne({_id: unitId}, {fields: {_id: 1, identifier: 1}}) || {};
unitDetail = {id, identifier};
}
if (!unitDetail.id) throw new Meteor.Error('notFatal', 'Failed to acquire info regarding unit - request.unitUpdate');
const {default: IncomingRequest} = require('/common/db/request/server');
IncomingRequest.update({'info.propertyId': listingId}, {$set: {'info.unit': unitDetail}}, {multi: true});
},
'request.updateGroup'(_id, {group: {id, identifier, name} = {}} = {}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.unitUpdate');
const {default: IncomingRequest} = require('/common/db/request/server');
const ir = IncomingRequest.findOne({_id}, {defaults: false});
ir && id && ir.updateGroup({id, identifier, name});
},
'request.updateStatus'(id, data) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.updateStatus');
const {default: IncomingRequest} = require('/common/db/request/server');
var ir = IncomingRequest.findOne({_id: id});
const isAdminOrManager = Roles.userIsInRole(Meteor.userId(), ['admin'], 'portal-group') || Roles.userIsInRole(Meteor.userId(), ['manager'], 'portal-group') || Roles.userIsInRole(Meteor.userId(), 'manager', 'settlin-hr-ops');
//checking if call is placed after any incoming request
let mode;
switch (ir.mode) {
case 'whatsapp':
case 'online':
case 'email':
case 'sms':
mode = ir.mode;
break;
default: break;
}
const {default: Conversations} = require('/common/db/conversation');
const conversation = Conversations.findOne(
{
$or: [
{mode: 'call', 'talked.flag': true},
...(mode ? [{mode}] : []),
],
'group.id': ir.group.id,
createdAt: {$gte: ir.createdAt},
},
{fields: {_id: 1}},
);
if (!conversation && !isAdminOrManager && !(ir.createdAt < new Date(new Date().setDate(new Date().getDate() - require('/common/info/receptionistCanCloseXDaysOldRequest').default)) && data.reason === 'invalidContact')) throw new Meteor.Error('notFatal', 'Call the customer before closing');
if (ir.info.unit?.id && ir.type === 'verification') {
let verifiedCount = VerifiedFields.find({unitId: ir.info.unit.id, 'data.resolvedValue': null, 'data.origCorrect': false, removed: false}).count();
if (verifiedCount) throw new Meteor.Error('notFatal', 'Resolve all wrong entries in unit, to proceed');
}
if (!ir) throw new Meteor.Error(404, 'No request found!');
ir.updateStatus(data);
},
'requests.countByTeam'({groupId}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.updateStatus');
const {default: IncomingRequests} = require('/common/db/request');
if (!groupId) return {};
var query = {removed: false, 'status.open': true, 'group.id': groupId};
let count = IncomingRequests.aggregate([
{$match: query},
{$group: {_id: '$team', count: {$sum: 1}}},
]);
return count;
},
'request.assignedToUserId'({id, assignedId = '', changeBuyerAssignee}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.assignedToUserId');
const isAdminOrManager = Roles.userIsInRole(this.userId, ['manager', 'admin'], 'portal-group') || Roles.userIsInRole(this.userId, 'manager', 'settlin-seller-ops') || Roles.userIsInRole(this.userId, 'manager', 'settlin-primary-ops') || Roles.userIsInRole(this.userId, 'manager', 'settlin-analysis-ops') || Roles.userIsInRole(this.userId, 'manager', 'settlin-buyer-ops');
const {default: IncomingRequest} = require('/common/db/request/server');
let doc = IncomingRequest.findOne({_id: id});
const $or = [
...(doc.info.contact.phone.value ? [{'info.contact.phone.value': doc.info.contact.phone.value}] : []),
...(doc.individual.id ? [{'individual.id': doc.individual.id}] : []),
];
if ($or.length) {
IncomingRequest.find({
_id: {$ne: doc._id},
relationship: doc.relationship,
'status.open': true,
team: doc.team,
// admin/manager can reassignee all request to same assignee
// current user can reassignee his request only
...(!isAdminOrManager ? {'assignedTo.userId': this.userId} : {}),
$or,
}).fetch().forEach(ir => {
require('/common/server').Temp.insert({requestId: ir._id, docId: doc._id, reason: 'request.assignedToUserId'});
ir.updateAssignedTo({userId: assignedId, forceReAssign: true});
});
}
doc.updateAssignedTo({userId: assignedId, forceReAssign: true, changeBuyerAssignee});
return assignedId;
},
'request.open'({id, statusOpen, reason = '', remarks = ''}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.open');
const {default: IncomingRequest} = require('/common/db/request/server');
const ir = IncomingRequest.findOne({_id: id});
ir.set({'status.open': statusOpen, 'status.comment': remarks, 'status.reason': reason});
ir.save();
return ir.status;
},
'request.save'({currentGroupId, currentIndividualId, relationship, source, remarks = '', phone, requestIds, city = 'unknown'} = {}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.save');
check([currentGroupId, currentIndividualId, relationship, source, remarks], [String]);
let newReq = false;
const {default: Groups} = require('/common/db/group');
const group = Groups.findOne({_id: currentGroupId}) || {};
const {default: Users} = require('/common/db/user');
const individual = Users.findOne({_id: currentIndividualId}) || {};
const {default: IncomingRequest} = require('/common/db/request/server');
const getUsersInRole = require('/common/utils/server/getUsersInRole').default;
const {Random} = require('meteor/random');
let requestStatus = {};
requestIds.map(requestId => {
const ir = IncomingRequest.findOne({_id: requestId}) || new IncomingRequest({_id: Random.id()}, {defaults: true});
let setAlert = false;
if (relationship !== 'unknown' && relationship !== ir.relationship) setAlert = true;
if (!ir) throw new Meteor.Error('notFatal', 'No request found!');
ir.info = ir.info || {};
if (IncomingRequest.isNew(ir)) {
newReq = true;
ir.info.status = 'interested';
}
if (newReq) ir.info.contact = {phone: {value: phone}};
const date = new Date();
let existing;
if (date.getHours() <= 18) existing = group.createdAt <= new Date(date).setHours(-6, 0, 0, 0); // group created before 6pm yesterday
else existing = group.createdAt <= new Date(date).setHours(18, 0, 0, 0); // group created before 6pm today
const groupData = {id: group._id, identifier: group.identifier, name: group.name, existing};
const individualData = {id: individual._id, identifier: individual.identifier, name: (individual.profile || {}).name};
// save request
const {requests} = require('/common/info/collectionBasedRolesAndScopes').default;
// current user
const currUser = Meteor.userId();
switch (relationship) {
case 'seller': {
let isCurrAssigneeValid = requests?.isAssigneeValid({doc: ir});
if (!isCurrAssigneeValid) isCurrAssigneeValid = requests?.isAssigneeValid({doc: ir, userId: currUser});
if (isCurrAssigneeValid) ir.setAssignedTo(currUser);
else {
let manager = ir.type === 'verification' ? getUsersInRole({scope: 'settlin-analysis-ops', role: 'manager', limit: 1}) : getUsersInRole({scope: 'settlin-seller-ops', role: 'manager', limit: 1});
ir.setAssignedTo(manager._id);
}
break;
}
case 'buyer': {
let isCurrAssigneeValid = requests?.isAssigneeValid({doc: ir});
if (!isCurrAssigneeValid) isCurrAssigneeValid = requests?.isAssigneeValid({doc: ir, userId: currUser});
// if current user is valid, then assignee him/her
if (isCurrAssigneeValid) ir.setAssignedTo(currUser);
else {
const {getAssigneeOne} = require('/common/utils/getAssignee');
let assignedTo = getAssigneeOne({collection: 'buyers', docId: group._id, teams: ir.team});
if (assignedTo?.userIds?.[0]) {
ir.setAssignedTo(assignedTo.userIds?.[0], {forceReAssign: true});
}
}
break;
}
default: ir.setAssignedTo(currUser);
}
let type = source === 'preLaunchExternal' ? 'preLaunch' : newReq ? 'incoming' : ir.type || 'outgoing';
let team = relationship === 'seller' ? '' : ['project', 'preLaunch'].includes(type) ? 'b2c' : 'c2c';
ir.set({relationship, source, group: groupData, individual: individualData, type, 'info.remarks': remarks, team});
ir.location = ir.location || {};
ir.location.city = city;
if (ir.assignedTo?.userId) {
let isAssigneePrimaryOps = Roles.userIsInRole(ir.assignedTo?.userId, ['telecaller', 'manager'], 'settlin-primary-ops');
if (isAssigneePrimaryOps) {
ir.team = 'b2c';
}
}
if (remarks) ir.set({'followUp.remarks': remarks});
if (newReq) {
ir.followUp.at = new Date();
ir.mode = 'portal';
}
ir.save();
//updating conversation with this request id.
const {default: Conversations} = require('/common/db/conversation');
Conversations.update({'request.id': ir._id}, {$set: {group: groupData, individual: individualData}});
if (requestIds.length > 1 && newReq) requestStatus[ir._id] = {new: ir._id};
else if (requestIds.length === 1 && newReq) {
requestStatus.new = newReq;
requestStatus.id = ir._id;
}
if (setAlert) {
requestStatus.setAlert = setAlert;
requestStatus.savedRelationship = ir.relationship;
}
});
return requestStatus;
},
'request.findSimilarRequestsCount'({phone = '', currentGroupId = '', currentIndividualId = '', requestId = ''}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.findSimilarrequestsCount');
check([phone, currentGroupId, currentIndividualId, requestId], [String]);
const {default: IncomingRequests} = require('/common/db/request');
return IncomingRequests.find({
_id: {$ne: requestId},
'status.open': true,
$or: [
{'info.contact.phone.value': phone},
{'individual.id': currentIndividualId},
],
'assignedTo.userId': this.userId,
relationship: 'unknown',
}).fetch().map(ir => ir._id);
},
'request.addUnitsAndRawUnits'({units = [], rawUnits = [], groupId, relationship, requestId}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.addUnitsAndRawUnits');
check([requestId, groupId], [String]);
const {default: IncomingRequest} = require('/common/db/request/server');
const ir = IncomingRequest.findOne({_id: requestId});
if (!ir) throw new Meteor.Error('notFatal', 'No request found!');
ir.set({units, rawUnits, relationship});
ir.save();
const {default: Buyer} = require('/common/db/buyer/portal');
let buyer = Buyer.findOne({_id: groupId, relationship: 'buyer'}, {defaults: false});
if (buyer) {
if ((ir.units[0] || {}).id) {
Meteor.call('notification.buyer.modification', {groupId, unitId: ir.units[0].id, requestId: ir._id, process: 'inception', status: 'enquired'}, function(err) {
if (err) Log.fatal('Problem Making Notification', err);
});
}
}
return {relationship, groupId, requestId: ir._id};
},
'request.createIncomingNotification'({userId} = {}) {
const {default: IncomingRequests} = require('/common/db/request');
check(userId, String);
const currentDate = addSecs(-2 * 60);
return IncomingRequests.findOne({'assignedTo.userId': userId, 'status.open': true, type: {$in: ['incoming', 'whatsapp']}, createdAt: {$gte: currentDate}}, {sort: {createdAt: -1}});
},
'request.updateFollowUp'({relationship, followUp, groupId, individualId}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.updateFollowUp');
const {default: IncomingRequest} = require('/common/db/request/server');
if (!groupId && !individualId) return;
let query = {};
if (groupId) query['group.id'] = groupId;
if (individualId) query['individual.id'] = individualId;
const incomingRequests = IncomingRequest.find({...query, removed: {$ne: true}, relationship, 'status.open': true, 'assignedTo.userId': this.userId}).fetch();
incomingRequests.forEach((p) => {
p.followUp = {
remarks: followUp.remarks || 'Triggered Automatically by request.updateFollowUp',
at: followUp.at || require('/common/utils/date/infinity').infinity,
};
p.save();
});
},
'request.getCount'({groupId, relationship, docId, individualId}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.getCounts');
const {default: IncomingRequests} = require('/common/db/request');
check([relationship, docId], [String]);
if (!groupId && !individualId) return 0;
let query = {};
if (groupId) query['group.id'] = groupId;
if (individualId) query['individual.id'] = individualId;
return {requestsCount: IncomingRequests.find({...query, _id: {$ne: docId}, relationship, 'status.open': true, 'assignedTo.userId': this.userId}).count()};
},
'request.getReceivedRequests'({unitId}) {
if (!Meteor.users.findOne({_id: this.userId, uses: 'portal'})) throw new Meteor.Error(403, 'Not authorized to do this operation - request.getReceivedRequests');
if (!unitId) return [];
const {default: Requests} = require('/common/db/request');
return Requests.find({'units.id': unitId}, {fields: {_id: 1, units: 1}}).fetch();
},
});