Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

How do I write this query?

Here's my current method:

this.displayActivityForm = function (companyId, proposalId, type) {
		//console.log(type);
		$.get('/companies/proposal/delete/' + id, function (resp) {
                if (resp.error) {
                    CAMS.alert('Error', resp.msg, 'error');
                    return false;
                }
                CAMS.alert('Success', 'Your proposal has been deleted successfully');
                $this.parents('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });
        var model = objectModels[type],
	
            fc = model.singular.substring(0, 1),
            config = {
                title: 'Add a' + ((fc == 'a' || fc == 'e' || fc == 'i' || fc == 'o' || fc == 'u') ? 'n' : '') + ' ' + ucwords(model.singular),
                directionsText: 'Make your changes below and then click, "SAVE."',
                fields: model.fields,
                onShow: function (self) {
                    // add in the additional events and plugins
                    // add in datetime support
                    self.$el.find('input.field-datetime').datepicker({
                        autoClose: true,
                        language: 'en',
                        timepicker: true,
                        dateFormat: 'mm/dd/yyyy',
                        timeFormat: 'h:ii AA',
                        showEvent: 'focus',
                        minutesStep: 5
                    });
					self.$el.find('#formit-notes').val("hello");
					self.$el.find('#formit-date').val("04/04/2020");
					self.$el.find('#formit-activityType').val("Call Note");
				

                },
                ajax: {
                    path: '/companies/edit-activity',
                    params: {
                        company: companyId,
                        proposal: proposalId,
                        type: type,
                    },
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }
                        companyId = (companyId == 'bulk' ? resp.data.id : companyId);
                        recordId = companyId;
                        $(window).trigger('open-company-details', [companyId, ((typeof route != 'undefined') ? route : '/companies/'), 'history']);
                    }
                }
            };

        // show the form
        formIt.show(config);
    };

Open in new window


This working code, but the first part, while it works, is something I copied from a different part of the page. It's this:

$.get('/companies/proposal/delete/' + id, function (resp) {
                if (resp.error) {
                    CAMS.alert('Error', resp.msg, 'error');
                    return false;
                }
                CAMS.alert('Success', 'Your proposal has been deleted successfully');
                $this.parents('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });

Open in new window


What I need to do is run a query that retrieves the Activity values you see towards the bottom of the page. These guys:

self.$el.find('#formit-notes').val("hello");
self.$el.find('#formit-date').val("04/04/2020");
self.$el.find('#formit-activityType').val("Call Note");

Instead of what I have hardcoded, I need the values to be what I retrieve from the "get" at the top of the method.

I don't know how.

I'm looking at other parts of the app and it appears that the "activity" is always being retrieved in the context of retrieving info about the company.

This is the route that retrieves info about a single company:

/ get the details of a single company
router.get('/companies/:orgId', async (req, res) => {
    let vars = Object.assign({
        userSettings: global._user.account.settings
    }, base);

    try {
        //let company = await Prospect.getOne(req.params.orgId);

        //vars.data = Prospect.success(company);
        let company = await Company.getOne(req.params.orgId);
        if (company) {
            let meta = company.meta;
            if (meta) { meta.fundingStatus = (typeof meta.fundingType != 'undefined') ? meta.fundingType : meta.fundingStatus; }
        }

        // get the company proposals
        company.proposals = typeof company.proposals == 'undefined' ? {} : company.proposals;
        company.proposals = await Company.getProposals(company._id);
        if (company.proposals) {
            if (company.proposals.length > 0) {
                company.proposals.forEach((row, rsi) => {
                    if (typeof row.services != 'undefined') {
                        row.services.forEach(async (item, ri) => {
                            if (item.service) {
                                company.proposals[rsi].services[ri].service = await Company.getService(item.service);
                            }
                        });
                    }
                });
            }
        }

        // get the company activity
        company.activity = typeof company.activity == 'undefined' ? [] : company.activity;
        company.activity = await Company.getActivity(company._id);

        // make sure there is a default file key
        company.files = typeof company.files == 'undefined' ? {} : company.files;
        company.files = company.files || {};

        // load the proposal files
        company.proposalFiles = typeof company.proposalFiles == 'undefined' ? [] : company.proposalFiles;
        company.proposalFiles = await Company.getFiles(company._id);
        company.route = 'companies';

        // check if the request just wants a JSON payload - Used for Proposal form
        if (req.query.json) {
            return res.send(Company.success(company));
        }
        vars.data = company;

    } catch (err) {
        vars.msg = `<div class="alert alert-danger">${err.message}</div>`;
    }

    res.render('companies-edit.html.twig', vars);
});

Open in new window


This line smells awfully good:

company.activity = await Company.getActivity(company._id);

The problem, however, is that it's going to retrieve ALL of the activity as opposed to an individual note or call etc.

There are two collections: I've to a "company" collection and an "activity" collection. Here are those respective services:

company.js:

const { ObjectId } = require('mongodb');
const { Util } = require('node-utils');
const moment = require('moment-timezone');
const mongoose = require('mongoose');
const uuid = require('uuid/v4');

const Service = require('./service');
const CompanySchema = require('../schemas/CompanySchema');
const ActivitySchema = require('../schemas/ActivitySchema');
const EventSchema = require('../schemas/EventSchema');
const ProposalSchema = require('../schemas/ProposalSchema');
const SavedFilterSchema = require('../schemas/SavedFilterSchema');
const UserSchema = require('../schemas/UserSchema');
const CompanyContactSchema = require('../schemas/CompanyContactSchema');
const CompanyAddressSchema = require('../schemas/CompanyAddressSchema');
const CompanyAddress = require('../services/companyaddress');
const GeoLocations = require('../services/GeoLocations');

const objectModels = require('../lib/object-models');
const Vendors = require('../lib/Vendors');

const ServiceSchema = require('../schemas/ServiceSchema');
const ProductsAndService = mongoose.model('Service', ServiceSchema);
const Proposal = mongoose.model('Proposal', ProposalSchema);
const User = require('../services/user.js');

let userModel = mongoose.model('User', UserSchema);

class Company extends Service {

    constructor() {
        super();

        this.collection = 'companies';
        this.plural = 'companies';
        this.singular = 'company';

        this.model = mongoose.model('Company', CompanySchema);

        this.fields = require('../lib/model-company');
        this.fields._id = {};
        this.fields._id.type = ObjectId;

        this.corePipeline = [
            {
                $lookup: {
                    from: 'users',
                    foreignField: '_id',
                    localField: 'owner',
                    as: 'owner'
                }
            },
            {$unwind: {path: '$owner',preserveNullAndEmptyArrays: true}},
                //{ "$addFields": { "brokers": { "$slice": ["$brokers", 1] } } },
                //{ "$unwind": { path: "$brokers", preserveNullAndEmptyArrays: true } },
                //{ "$addFields": { "contacts": { "$slice": ["$contacts", 1] } } },
                //{ "$unwind": { path: "$contacts", preserveNullAndEmptyArrays: true } },
                //{ '$match': { 'addresses.postal': { '$in': global._user.account.postalCodes } } }
            
        ];
    }

    datatable(input, baseFilters = {}) {
		//console.log(global._user.account.postalCodes);
		return new Promise((resolve, reject) => {
			let config = this._getDataTablesFilters(input);
			let pipeline = [];
			let countPipeline = []; // the filters used for counts

			// add in the base filters
			config.filters = Util.merge(baseFilters, config.filters);

			// set the base pipeline where/match clause
			pipeline.push({ $match: this._enforceScope() });

			// add sorting
			if (Object.keys(config.sort).length > 0) {
				if (typeof config.sort[0] == 'undefined') {
					pipeline.push({ $sort: config.sort });
				}

			}
			// Owner
			pipeline.push(
				{$lookup: {from: 'users',let: { 'ownerId': '$owner' },pipeline: [{$match: {$expr: {$and: [{ $eq: ["$_id", "$$ownerId"] }]}}},{$project: {name: {$concat: ['$firstName', ' ', '$lastName']}}}],as: 'owner'}},
				{ $unwind: { path: '$owner', preserveNullAndEmptyArrays: true } }
			);
			// Broker            
			pipeline.push(
				{ "$addFields": { "brokers": { "$slice": ["$brokers", 1] } } },
				{ "$unwind": { path: "$brokers", preserveNullAndEmptyArrays: true } }
			);
			pipeline.push(
				{ "$addFields": { "contacts": { "$slice": ["$contacts", 1] } } },
				{ "$unwind": { path: "$contacts", preserveNullAndEmptyArrays: true } }
			);
			//pipeline.push(
			//    { "$addFields": { "addresses": { "$slice": ["$addresses", 1] } } },
			//    { "$unwind": { path: "$addresses", preserveNullAndEmptyArrays: true } }
			//);
			if(global._user.account.postalCodes) {
				 pipeline.push({
					$match: {
					  $or: [
						{ 'addresses.postal': { $in: global._user.account.postalCodes } },
						{ clientImport: global._user.account._id }
					  ]
					}
				  });
			}


			// Search text      
			if (typeof input.search != 'undefined') {
				if (input.search.value) {

					var searchQuery = this._getDataTablesSearch(input.search.value);
					if (typeof searchQuery != 'undefined') {
						pipeline.push({ $match: searchQuery });
					}
				}
			}

			// set the filters pipeline where/match clause
			if (Object.keys(config.filters).length > 0) {
				pipeline.push({ $match: config.filters });
			}

			// set the count pipeline here since all of the filters should be applied
			// by this point
			countPipeline = Array.from(pipeline);




			// add the limits
			pipeline.push({ $skip: config.limits[0] });
			pipeline.push({ $limit: config.limits[1] });

			// add in a datatable specific field
			pipeline.push({
				$addFields: {
					DT_RowId: '$_id',
					currentUserId: global._user._id //for 'Assign to me' link
				}
			});

			// call the lifecycle method to allow extending classes to customize just
			// the pipeline without having to overwrite the whole method
			pipeline = this._beforeDatatablesPipeline(pipeline);


			this.model.aggregate(pipeline).then(async (data) => {
				resolve({
					draw: parseInt(input.draw),
					data: data,
					recordsFiltered: await this.__aggCount(countPipeline),//filter wrong? await this._count(this._enforceScope()),
					recordsTotal: await this._count(this._enforceScope())
				});
			}).catch((err) => {
				//console.log("it's here we've got a problem");
				console.log('Aggregate Error: ', err);
				reject(err);
			});
		});
    }


    getOne(companyId) {
        return new Promise((resolve, reject) => {
            companyId = this._getId(companyId);
            if (!companyId) {
                return reject('Invalid company ID provided.');
            }

            // create a clone of the pipeline so we don't alter the original
            let pipeline = this.corePipeline.slice(0);

            // add an initial match stage to the core pipeline
            pipeline.unshift({
                $match: this._enforceScope({
                    _id: companyId
                })
            });

            this.model.aggregate(pipeline).then((data) => {
                if (data.length === 0) {
                    reject('Could not find record.');
                } else {
                    resolve(data[0]);
                }
            }).catch((err) => {
                reject(err);
            });
        });
    }
    getOneContact(contactId, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            let contact_id = this._getId(contactId);
            let pipeline = [{ $match: { _id: company_Id } },
            {$project: {
                contacts: {$filter: {
                    input: "$contacts",
                    as: "contacts",
                    cond: { $eq: ["$$contacts._id", contact_id] }
                    }}
            }},
            {$addFields:{'contacts.company':'$_id'}},
            {$unwind:{path:"$contacts",preserveNullAndEmptyArrays:true}},
                { $project: { 'contacts': 1, _id: 0 } }];
            this.model.aggregate(pipeline).then((rows) => {
                resolve(rows[0].contacts);
            }).catch((error) => {
                console.log(error.message);
                reject(error.message);
            });           
        });
    }
    saveContact(contactId, contact) {
        return new Promise((resolve, reject) => {
            let companyId = contact.company;
            contact.active = true;
            if (contactId === 'new') {                        
                delete contact.company;
                this.model.updateOne({ _id: companyId }, { $push: { contacts: contact } }, { setDefaultsOnInsert: true }).then(response => {                    
                    contact.company = companyId;
                    resolve(contact);
                }).catch(err => {
                    reject(err);
                });
            } else {
                this.model.updateOne({ _id: companyId },
                    {
                        $set: {
                            'contacts.$[i].email': contact.email,
                            'contacts.$[i].name': contact.name,
                            'contacts.$[i].phone': contact.phone
                        }
                    },
                    {
                        arrayFilters: [{
                                "i._id": this._getId(contactId)
                            }], setDefaultsOnInsert: true
                    }
                ).then(response => {
                    contact.company = companyId;
                    resolve(contact);
                }).catch(err => {
                    reject(err);
                });
            }
            
        });
    }
    getOneAddress(addressId, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            let address_id = this._getId(addressId);
            let pipeline = [{ $match: { _id: company_Id } },
            {$project: {
                addresses: {$filter: {
                    input: "$addresses",
                    as: "addresses",
                    cond: { $eq: ["$$addresses._id", address_id] }
                    }}
            }},
            {$addFields:{'addresses.company':'$_id'}},
            {$unwind:{path:"$addresses",preserveNullAndEmptyArrays:true}},
                { $project: { 'addresses': 1, _id: 0 } }];
            this.model.aggregate(pipeline).then((rows) => {
                resolve(rows[0].addresses);
            }).catch((error) => {
                console.log(error.message);
                reject(error.message);
            });           
        });
    }
    saveAddress(addressId, address) {
        return new Promise((resolve, reject) => {
            let companyId = address.company;
            address.active = true;
            if (addressId === 'new') {
                delete address.company;
                this.model.updateOne({ _id: companyId }, { $push: { addresses: address } }, { setDefaultsOnInsert: true }).then(response => {
                    address.company = companyId;
                    resolve(address);
                }).catch(err => {
                    reject(err);
                });
            } else {
                this.model.updateOne({ _id: companyId },
                    {
                        $set: {
                            'addresses.$[i].street': address.street,
                            'addresses.$[i].city': address.city,
                            'addresses.$[i].state': address.state,
                            'addresses.$[i].postal': address.postal,
                            //'addresses.$[i].geo': geoaddress.geo,
                            'addresses.$[i].hash': address.hash,
                            'addresses.$[i].nonGeo': address.nonGeo
                        }
                    },
                    {
                        arrayFilters: [{
                            "i._id": this._getId(addressId)
                        }], setDefaultsOnInsert: true
                    }
                ).then(response => {
                    address.company = companyId;
                    resolve(address);
                }).catch(err => {
                    reject(err);
                });
            }

        });
    }
    getOneBroker(index, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            this.model.findOne({ _id: company_Id, account: global._user.account._id }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                resolve(res.brokers[index]);
            });
        });
    }

    saveBroker(index, broker) {
        return new Promise((resolve, reject) => {
            let companyId = this._getId(broker.company);
            let accountId = this._getId(broker.account);
            delete broker.company;
            delete broker.account;
            this.model.findOne({ _id: companyId, account: accountId }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                res.brokers = res.brokers ? res.brokers : [];
                if (index == 'new') {                    
                    res.brokers.push(broker); 
                    broker = res.brokers;
                } else {
                    res.brokers[index] = broker;
                    broker = res.brokers;
                }
                this.model.updateOne({ _id: companyId, account: accountId }, { $set: { brokers: broker }}, (err, raw) => {
                    if (err) { console.log(err); reject(err); }
                    resolve(raw);
                });
            });
        });
    }
    //Fix: This function will check for dates field type array and convert it into object. Converts array field to Object
    resolveDatesArray() {
        return new Promise((resolve, reject) => {
            let condition = { dates: { $type: "array" } };
            this.model.updateMany(condition, { dates: {} }, { upsert: true }, (err, raw) => {
                if (err) { 
					console.log(err); 
					reject(err); 
				}
                resolve(raw);
            });            
        });
    }
    select2(query) {
        return new Promise((resolve, reject) => {
            this.model.aggregate([
                {
                    '$match': this._enforceScope({
                        name: {
                            '$regex': query,
                            '$options': 'i'
                        }
                    })
                },
                {
                    '$sort': {
                        name: 1
                    }
                },
                { '$limit': 25 },
                {
                    '$project': {
                        id: '$_id',
                        text: '$name'
                    }
                }
            ]).then((rows) => {
                resolve(rows);
            }).catch((err) => {
                reject(err);
            });
        });
    }

    assign(companies, user) {
        return new Promise((resolve, reject) => {
            let where = this._enforceScope({ _id: { $in: [] } });
            let update = { $set: {} };

            if (typeof user == 'undefined' || companies == 'undefined') {
                return reject('Invalid or missing parameters.');
            }

            let ids = [];
            for (let i in companies) {
                where._id['$in'].push(this._getId(companies[i]));
                ids.push(this._getId(companies[i]));
            }
            let pipeline = [{ $match: { _id: { $in: ids } } }, { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } }];
            this.model.aggregate(pipeline).then((beforeRows) => {


                update = {
                    $set: {
                        owner: this._getId(user),
                        account: global._user.account._id,//new added
                        active: true,//new added
                        'dates.assigned': new Date(moment().toISOString())// new added for reporting, pipeline target column display
                    }
                };                

                this.model.updateMany(where, update, (err, res) => {
                    if (err) {
                        reject(this.error('Invalid parameters provided.'));
                    } else {
                        let count = 0;
                        beforeRows.forEach((oldDoc) => {
                            pipeline = [{ $match: { _id: oldDoc._id } }, { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } }, { $limit: 1 }];
                            this.model.aggregate(pipeline).then(async (rows) => {
                                let newDoc = rows[0];
                                let meta = await this.jsonDiff(
                                    { owner: (oldDoc.owner.length > 0) ? '<a href="javascript:void(0);" class="user-info" data-user-id="' + oldDoc.owner[0]._id + '">' + oldDoc.owner[0].firstName + ' ' + oldDoc.owner[0].lastName + '</a>' : 'Unassigned' },
                                    { owner: (newDoc.owner.length > 0) ? '<a href="javascript:void(0);" class="user-info" data-user-id="' + newDoc.owner[0]._id + '">' + newDoc.owner[0].firstName + ' ' + newDoc.owner[0].lastName + '</a>' : 'Unassigned' }
                                );

                                let history = await this.addHistory('Owner change', newDoc._id, '', global._user._id, meta);
                                count = count + 1;
                                if (count = beforeRows.length) {
                                    resolve(this.success());
                                }
                            });

                        });
                    }
                });
            });
        });
    }

    unassign(companies) {
        return new Promise((resolve, reject) => {            
            let update = { $set: { owner: null } };
            let id;

            if (companies == 'undefined') {
                reject('Invalid or missing parameters.');
            }

            for (let i in companies) {
                id = this._getId(companies[i]);
                if (id) {
                    let pipeline = [
                        { $match: { _id: id } },
                        { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } },                        
                        { $limit: 1 }];
                    this.model.aggregate(pipeline).then((res) => {
                        if (res.length > 0) {                            
                            this.model.updateOne({ _id: id }, update, async(err, doc) => {
                                if (err) { console.log(err); }
                                if (typeof res[0].owner != 'undefined') {
                                    let meta = await this.jsonDiff(
                                        { owner: res[0].owner.length > 0 ? '<a href="javascript:void(0)" class="user-info" data-route="company" data-user-id="' + res[0].owner[0]._id + '">' + res[0].owner[0].firstName + " " + res[0].owner[0].lastName + '</a>' : "Unassigned" },
                                        { owner: 'Unassinged' }
                                    );
                                    await this.addHistory('Owner change', id, '', global._user._id, meta);
                                }                                
                                if ((parseInt(i)+1) === companies.length) {
                                    resolve(this.success());
                                }
                            });
                        }
                    }).catch((error) => { console.log(error); });
                }                
            }
        });
    }
    softDeleteItems(companies) {
        return new Promise((resolve, reject) => {
            if (typeof companies == 'undefined' || companies === 0) {
                return reject(Company.error('Please provide one or more company ID\'s.'));
            }            
            for (let i in companies) {
             let  id = this._getId(companies[i]);
                if (id) {
                    let pipeline = [
                        { $match: { _id: id } },
                        { $lookup: { from: "proposals", localField: "_id", foreignField: "company", as: "proposals" } },
                        { $limit: 1 }];
                    this.model.aggregate(pipeline).then((res) => {
                        if (res.length > 0) {
                            this.model.updateOne({ _id: id }, {$set: {deleted: true,active: false}}, async (err, doc) => {
                                if (err) { console.log(err); }
                                // delete Proposals
                                if (res[0].proposals.length > 0) {
                                    await Proposal.updateMany({ company: id }, { $set: { active: false } }, async (err, doc) => {
                                        if (err) { console.log(err);}
                                        // Todo nothing.
                                    });
                                }
                                let meta = await this.jsonDiff(
                                    { active: true },
                                    { active: false, deleted:true }
                                );
                                await this.addHistory('Company deleted', id, '', global._user._id, meta);

                                if ((parseInt(i) + 1) === companies.length) {
                                    resolve(this.success());
                                }
                            });
                        }
                    }).catch((error) => { console.log(error); });
                }
            }
        });
    }

    getActivity(companyId) {
        return new Promise((resolve, reject) => {
            const Activity = mongoose.model('Activity', ActivitySchema);
            //let pipeline = [
            //            {
            //                $match: {
            //                    account: global._user.account._id,
            //                    company: companyId
            //                }
            //            },
            //            {
            //                $sort: {
            //                    date: -1
            //                }
            //            },
            //            { $limit: 100 },
            //            {
            //                $lookup: {
            //                    from: 'users',
            //                    foreignField: '_id',
            //                    localField: 'user',
            //                    as: 'user'
            //                }
            //            },
            //            { $unwind: '$user' }
            //        ];
            //  Activity.aggregate(pipeline).then((rows) => {
            //  var activity = [];

            //  for (let i in rows) {
            //    // get the icon by type
            //    rows[i].icon = this.getIconByType(rows[i].type);

            //    // add it to the list
            //    activity.push(rows[i]);
            //  }

            //  resolve(activity);
            //}).catch((err) => {
            //  reject(err);
            //});
            let pipeline = [
                {
                    $match: {
                        account: global._user.account._id,
                        company: companyId
                    }
                },
                {
                    $lookup: {
                        from: 'users',
                        foreignField: '_id',
                        localField: 'user',
                        as: 'user'
                    }
                },
                { $unwind: '$user' },
                {
                    $group: {
                        '_id': {
                            year: { $year: "$date" },
                            month: { $month: "$date" },
                            day: { $dayOfMonth: "$date" }
                        },
                        activities: {
                            $push: {
                                _id: '$_id',
                                type: '$type',
                                company: '$company',
                                proposal: '$proposal',
                                user: { _id: '$user._id', 'firstName': '$user.firstName', 'lastName': '$user.lastName' },
                                date: '$date',
                                meta: '$meta'

                            }
                        }
                    }
                },
                { $project: { date: '$_id', activities: 1, _id: 0 } },
                { $sort: { "activities.date": -1 } }
            ];
            Activity.aggregate(pipeline).then((rows) => {
                var activity = [];

                for (let i in rows) {
                    for (let j in rows[i].activities) {
                        // get the icon by type
                        rows[i].activities[j].icon = this.getIconByType(rows[i].activities[j].type);                        
                        rows[i].activities[j].prettyDate = moment(rows[i].activities[j].date).fromNow();
                        rows[i].activities[j].readableDate = moment(rows[i].activities[j].date).format('MMM Do - LT');
						rows[i].activities[j].doableDate = moment(rows[i].activities[j].date).format('m/d/Y');
                    }
                    // add it to the list 
                    rows[i].prettyDate = moment.utc(rows[i].date.year + '-' + rows[i].date.month + '-' + rows[i].date.day).local().fromNow();
                    activity.push(rows[i]);

                }

                resolve(activity);
            }).catch((err) => {
                reject(err);
            });
        });
    }

    getFiles(companyId) {
        return new Promise((resolve, reject) => {
            const Proposal = mongoose.model('Proposal', ProposalSchema);

            Proposal.aggregate([
                {
                    $match: {
                        company: companyId,
                        files: {
                            $exists: true
                        }
                    }
                },
                { $unwind: '$files' },
                {
                    $project: {
                        proposal: '$_id',
                        name: '$name',
                        file: '$files'
                    }
                }
            ]).then((rows) => {
                resolve(rows);
            }).catch((err) => {
                console.log('Error: ', err);
                reject(err);
            });
        });
    }

    addActivity(companyId, type, data) {
        return new Promise(async(resolve, reject) => {
            if (typeof type != 'string' || ['call', 'visit', 'reminder', 'event'].indexOf(type.trim()) == -1) {
                return reject('Invalid type provided');
            }
            const Schema = mongoose.Schema;
            const Base = mongoose.model('Activity', ActivitySchema);
            // to track activity on each pipeline stage
            if (data.proposal != 'undefined') {
                if (data.proposal != 'bulk') {
                    if (data.proposal) {
                        await Proposal.findById(this._getId(data.proposal), (err, res) => {
                            if (err) { console.log(err); }
                            if (res) {
                                data.pipeline = res.pipeline;
                            }
                        });
                    }
                }
            }
                       
            if (type == 'event') {
                // define dynamic Schema
                const Event = Base.discriminator('event', new mongoose.Schema({meta: {start: Date,end: Date,subject: String,participants: String,location: String,details: String}}));
                let _data = {
                    company: new ObjectId(companyId),
                    type: type.trim(),
                    meta: {
                        start: data.start,
                        end: data.end,
                        subject: data.subject,
                        participants: data.participants,
                        location: data.location,
                        details: data.details
                    },
                    user: global._user._id,
                    account: global._user.account._id
                };
                if (data.proposal != 'undefined') {
                    if (data.proposal != 'bulk') {
                        if (data.proposal) {
                            _data.proposal = data.proposal;
                            _data.pipeline = data.pipeline;
                        }
                    }
                }
                Event.create(_data, (err, record) => {
                    if (err) {
                        console.log('Error: ', err);
                        reject('An unexpected error was encountered. Please try again.');
                    } else {
                        resolve(record._id);
                    }
                });
            } else {
                // define dynamic Schema
                //FIX: descriminator with name 'call' already exists.
                const ActivityModel = Base.discriminators ? Object.keys(Base.discriminators).indexOf(type.trim()) >= 0 ? Base.discriminators[type.trim()] : Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } })) : Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } })); 
                //const ActivityModel = Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } })); 
                let _data = {
                    company: new ObjectId(companyId),
                    type: type.trim(),
                    meta: {
                        date: data.date,
                        notes: data.notes
                    },
                    user: global._user._id,
                    account: global._user.account._id
                };
                if (data.proposal != 'undefined') {
                    if (data.proposal != 'bulk') {
                        if (data.proposal) {
                            _data.proposal = data.proposal; 
                            _data.pipeline = data.pipeline;
                        }
                    }
                }
                ActivityModel.create(_data, (err, record) => {
                    if (err) {
                        console.log('Error: ', err);
                        reject('An unexpected error was encountered. Please try again.');
                    } else {
                        resolve(record._id);
                    }
                });
            }
        });
    }
	
	retrieveActivity(activityId) {
		
		
	}

    deleteActivity(activityId) {
        return new Promise((resolve, reject) => {
            let match = this._enforceScope({
                _id: new ObjectId(activityId)
            });

            const Activity = mongoose.model('Activity', ActivitySchema);

            Activity.deleteOne(match, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });
        });
    }

    exportToCSV(input) {
        return new Promise((resolve, reject) => {
            let config = this._getDataTablesFilters(input);
            let pipeline = [];
            let baseFilters = {
                account: global._user.account._id,
                active: true,
                deleted: {
                    $exists: false
                }
            };

            // add in the base filters
            config.filters = Util.merge(baseFilters, config.filters);

            // set the base pipeline where/match clause
            pipeline.push({ $match: this._enforceScope() });

            // lifecylce method to give the user the ability to inject setup stages to
            // the pipeline before we start adding in user-defined filters, limits and
            // sorting options
            pipeline = this._startPipeline(pipeline);

            // Search text      
            if (typeof input.search != 'undefined') {
                if (input.search.value) {

                    var searchQuery = this._getDataTablesSearch(input.search.value);
                    if (typeof searchQuery != 'undefined') {
                        pipeline.push({ $match: searchQuery });
                    }
                }
            }

            // set the filters pipeline where/match clause
            if (Object.keys(config.filters).length > 0) {
                pipeline.push({ $match: config.filters });
            }

            // add sorting
            if (Object.keys(config.sort).length > 0) {
                pipeline.push({ $sort: config.sort });
            }

            // we need to format the arrays - not sure what the heck is going on with
            // using $addresses.0.street in the projection stage below, but I had some
            // issues getting it to work
            pipeline.push({
                $addFields: {
                    _contact: {
                        $slice: ['$contacts', 1]
                    },
                    _address: {
                        $slice: ['$addresses', 1]
                    }
                }
            });

            pipeline.push({
                $unwind: {
                    path: '$owner',
                    preserveNullAndEmptyArrays: true
                }
            });

            pipeline.push({
                $unwind: {
                    path: '$_contact',
                    preserveNullAndEmptyArrays: true
                }
            });

            pipeline.push({
                $unwind: {
                    path: '$_address',
                    preserveNullAndEmptyArrays: true
                }
            });

            // add the project stage
            pipeline.push({
                $project: {
                    name: '$name',
                    owner: '$owner.name',
                    contact_name: '$_contact.name',
                    contact_email: '$_contact.email',
                    contact_phone: '$_contact.phone',
                    address_street: '$_address.street',
                    address_city: '$_address.city',
                    address_state: '$_address.state',
                    address_postal: '$_address.postal',
                    address_county: '$_address.county',
                    industry: '$meta.industry',
                    ftes: '$meta.ftes',
                    fteGrouping: '$meta.fteGrouping',
                    premium: '$meta.premium',
                    premiumPerFte: '$meta.premiumPerFte',
                    brokerCommissionTotal: '$meta.brokerCommissionTotal',
                    brokerFeesTotal: '$mata.brokerFeesTotal',
                    fundingType: '$meta.fundingType',
                    ein: '$meta.ein'
                }
            });

            // get the data
            this.model.aggregate(pipeline).then((rows) => {
                const papaparse = require('papaparse');
                console.log('Data: ', JSON.stringify(rows, undefined, 2));
                let csv = papaparse.unparse(rows);

                resolve(csv);
            }).catch((err) => {
                reject(err);
            });
        });
    }

    _startPipeline(pipeline) {
        let coreClone = this.corePipeline.slice(0);

        // remove the first stage of the core to add in the below projection
        coreClone.shift();

        // add in the owner's info
        coreClone.unshift({
            $lookup: {
                from: 'users',
                let: { 'ownerId': '$owner' },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $and: [
                                    { $eq: ["$_id", "$$ownerId"] }
                                ]
                            }
                        }
                    },
                    {
                        $project: {
                            name: {
                                $concat: ['$firstName', ' ', '$lastName']
                            }
                        }
                    }
                ],
                as: 'owner'
            }
        });

        return pipeline.concat(coreClone);
    }
    targetSelected(companies = [], user) {
        return new Promise(async (resolve, reject) => {
            try {
                if (companies.length > 0 && user.length > 0) {
                    let Targetpipelines = await this.getPipelineColumns();                    
                    var index = Targetpipelines.map(function (o) { return o.key; }).indexOf("target");
                    let Targetpipeline = Targetpipelines[index];
                    if (typeof Targetpipeline != 'undefined') {
                        let count = 0;
                        companies.forEach((company) => {
                            let targetProposal = {
                                name: '_target', owner: this._getId(user), company: this._getId(company), pipeline: Targetpipeline._id, active: true, services: [], files: [],
                                //dates: { target: new Date(moment().toISOString())},
                                _range: [new Date(moment().toISOString()), new Date(moment().toISOString())],
                                _pipelineDate: new Date(),
                                pipelineIndex: 0,
                                account: global._user.account._id,
                                pipelineDuration: [{
                                    pipelineFrom: Targetpipeline._id, fDate: new Date(moment().toISOString()),
                                    pipelineTo: Targetpipeline._id, tDate: new Date(moment().toISOString())
                                }]
                            };
                            targetProposal.dates = typeof targetProposal.dates == 'undefined' ? {} : targetProposal.dates;
                            targetProposal.dates[Targetpipeline._id] = new Date(moment().toISOString()), new Date(moment().toISOString());
                            Proposal.updateOne({ owner: this._getId(user), company: this._getId(company), name: '_target' }, targetProposal, { runValidators: true, upsert: true }, async(error, res) => {
                                if (error) {
                                    console.log(error);
                                }
                                let targetUser = await this.getUserbyID(user);//await User.getOne(this._getId(user));
                                if (targetUser) {
                                    let meta = { 'Target Selected to': "<a href='javascript:void(0);' class='user-info' data-user-id='" + targetUser._id + "' data-route='market'>" + targetUser.firstName + " " + targetUser.lastName + "</a>" };
                                    this.addHistory('Target selected', this._getId(company), '', global._user._id, meta);
                                }
                                

                                count = count + 1;
                                if (count == companies.length) {
                                    resolve(true);
                                }
                            });
                        });
                    } else {
                        reject('Pipeline Column is undefined.');
                    }
                } else {
                    reject('Invalid or undefined company id or user id provided.');
                }
            } catch (e) {
                console.log(e);
                reject(e);
            }
        });
    }
    getUserbyID(id) {
        return new Promise(async (resolve, reject) => {
            if (id) {
                userModel.findById(this._getId(id), (err, res) => {
                    if (err) { console.log(err); resolve(false);}
                    resolve(res);
                });
                
            } else {
                resolve(false);
            }
        });
    }
    ignoreTargetSelected(companies = []) {
        return new Promise(async (resolve, reject) => {
            try {
                if (companies.length > 0) {
                    let Targetpipelines = await this.getPipelineColumns();
                    var index = Targetpipelines.map(function (o) { return o.key; }).indexOf("target");
                    let Targetpipeline = Targetpipelines[index];
                    if (typeof Targetpipeline != 'undefined') {
                        let companyIds = [];
                        companies.forEach(async (company) => {
                            companyIds.push(this._getId(company));
                            await this.addHistory('Target ignored', this._getId(company), '', global._user._id, {});
                        });
                        Proposal.deleteMany({ company: { $in: companyIds }, name: '_target' }, (error) => {
                            if (error) { reject(error); }
                            resolve(true);
                        });

                    } else {
                        reject('Pipeline Column is undefined.');
                    }
                } else {
                    reject('Invalid or undefined company id provided.');
                }
            } catch (e) {
                console.log(e);
                reject(e);
            }
        });
    }

    getOneForHistory(id) {
        return new Promise((resolve, reject) => {
            id = this._getId(id);
            if (!id) {
                return reject('Invalid prospect ID provided.');
            }
            let pipeline = [{ $match: { _id: id } },
            {
                $lookup: {
                    from: "users",
                    let: { "ownerId": "$owner" },
                    pipeline: [
                        { $match: { $expr: { $eq: ["$_id", "$$ownerId"] } } },
                        {
                            $project: {
                                _id: 0,
                                assigned: { $concat: ["<a href='javascript:void(0)' class='user-info' data-user-id='", { $toString: "$_id" }, "'>", "$firstName", " ", "$lastName", "</a>"] }
                            }
                        }
                    ],
                    as: "owner"
                }
            },
            { $unwind: { path: "$owner", preserveNullAndEmptyArrays: true } },
            { $addFields: { owner: "$owner.assigned" } }
            ];


            this.model.aggregate(pipeline).then((data) => {
                if (data.length === 0) {
                    reject('Could not find record.');
                } else {
                    resolve(data[0]);
                }
            }).catch((err) => {
                reject(err);
            });
        });
    }
    getProposals(companyId) {
        return new Promise((resolve, reject) => {
            let scopedFilters = this._enforceScope();
            var pipeline = [
                {
                    $match: {
                        company: this._getId(companyId),
                        name: { "$ne": "_target" },// should not show _target proposals they are just 'Target Selected' pipeline
                        $or: [{ "active": { "$exists": false } }, { "active": true }]
                    }
                },
                {
                    $lookup: {
                        from: "pipelinecolumns",
                        localField: "pipeline",
                        foreignField: "_id",
                        as: "pipeline"
                    }
                },
                { $unwind: "$pipeline" },
                {
                    $lookup: {
                        from: "services",
                        localField: "services.service",
                        foreignField: "_id",
                        as: "products"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "owner",
                        foreignField: "_id",
                        as: "owner"
                    }
                },
                {
                    $project: {
                        "products.model": 0, "products.account": 0, "products.amount": 0,
                        "owner.settings": 0, "owner.password": 0, "owner.email": 0, "owner.mobile": 0, "owner.account": 0
                    }
                },
                {
                    $unwind: "$owner"
                }];

            Proposal.aggregate(pipeline, (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows);
                }
            });
        });
    }
    getService(serviceId) {
        return new Promise((resolve, reject) => {
            let pipeline = [{ $match: { "_id": serviceId } }];
            ProductsAndService.aggregate(pipeline, (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows[0]);
                }
            });
        });
    }
    heatmap(ids) {
        return new Promise((resolve, reject) => {
            let pipeline = [];

            let _ids = [];
            if (ids && ids.length > 0) {
                ids.forEach((id) => {
                    _ids.push(this._getId(id));
                });

                let match = { $match: this._enforceScope() };
                delete match['$match']['account'];
                match['$match']._id = { $in: _ids };
                pipeline.push(match);
                pipeline.push(
                    { $unwind: { path: "$addresses", preserveNullAndEmptyArrays: true } },
                    { "$addFields": { "company": { _id: "$_id", name: "$name" } } },
                    {
                        "$lookup": {
                            "from": "geo_locations", "let": { "addressId": "$addresses._id" }, "pipeline": [
                                { "$match": { "$and": [{ "$expr": { "$eq": ["$address", "$$addressId"] } }, { "$expr": { "$eq": ["$active", true] } }] } }], "as": "geo_locations"
                        }
                    },
                    { $unwind: { path: "$geo_locations", preserveNullAndEmptyArrays: true } },
                    {
                        "$project": {
                            "_id": 0,
                            "type": "Feature",
                            "properties": {
                                "name": '$name',
                                "popupContent": "$name",
                                "_id": "$_id", "street": "$addresses.street", "city": "$addresses.city", 'state': '$addresses.state', "postal": "$addresses.postal", "country": "$addresses.country", "county": "$addresses.county",
                                "addresses": "$addresses",
                                "company": "$company", "nonGeo": "$addresses.nonGeo"
                            },
                            "geometry": "$geo_locations.geo"
                        }
                    }
                );
                this.model.aggregate(pipeline).then(async (rows) => {
                    let count = 0;
                    rows.forEach(async (row, index) => {
                        if (row.geometry === undefined) {
                            row.properties.addresses = row.properties.addresses ? row.properties.addresses : {};
                            row.properties.addresses.company = row.properties.company._id;
                            let geoAddress = await this.getGeoAddress(row.properties.addresses);
                            rows[index].geometry = geoAddress.geo;
                            count = count + 1;
                        } else { count = count + 1; }
                        if (rows.length == count) {
                            resolve({ "type": "FeatureCollection", "features": rows });
                        }
                    });
                }).catch((err) => {
                    console.log('Aggregate Error: ', err);
                    reject(err);
                });
            } else {
                //reject('undefined parameter ids provided.');
                resolve({ "type": "FeatureCollection", "features": [] });
            }

        });
    }

    getGeoAddress(address = {}) {
        return new Promise(async (resolve, reject) => {
            try {
                if (typeof address.geo != 'undefined') {
                    resolve(address);
                } else {
                    var isValidAddress = false;                    
                    address.street = address.street ? address.street.trim() : address.street;
                    if (!address || address.street === '' || address.city === '' || address.state === '' || address.postal === '' || address.street === undefined || address.city === undefined || address.state === undefined || address.postal === undefined) {
                        isValidAddress = false;
                        address.error = 'invalid';
                        resolve(address);
                    }
                    else {
                        isValidAddress = true;
                    }
                    if (isValidAddress) {
                        let geoaddress = await CompanyAddress.getGeocode(address);
                        if (geoaddress) {
                            if (geoaddress.error_message) {
                                address.error = geoaddress.error_message;
                                resolve(address);
                            } else {
                                GeoLocations.model.updateOne(
                                    { address: address._id },//, account: global._user.account._id
                                    { $set: { address: address._id, company: address.company, geo: geoaddress.geo } },//account: global._user.account._id,
                                    { upsert: true, setDefaultsOnInsert: true }, (err) => {
                                        if (err) {
                                            resolve(address);
                                        } else {
                                            this.model.updateOne({ _id: address.company },
                                                {
                                                    $set: {
                                                        'addresses.$[i].street': geoaddress.street,
                                                        'addresses.$[i].city': geoaddress.city,
                                                        'addresses.$[i].state': geoaddress.state,
                                                        'addresses.$[i].postal': geoaddress.postal,
                                                        //'addresses.$[i].geo': geoaddress.geo,
                                                        'addresses.$[i].hash': geoaddress.hash,
                                                        'addresses.$[i].nonGeo': geoaddress.nonGeo
                                                    }
                                                },
                                                {
                                                    arrayFilters: [
                                                        {
                                                            "i._id": address._id
                                                        }]
                                                }
                                            ).then(response => {
                                                resolve(geoaddress);
                                            }).catch(err => {
                                                address.error = err.msg;
                                                resolve(address);
                                            });
                                        }
                                    });

                                //CompanyAddress.model.updateOne({ _id: address._id }, { '$set': { street: geoaddress.street, city: geoaddress.city, state: geoaddress.state, postal: geoaddress.postal, geo: geoaddress.geo, hash: geoaddress.hash, nonGeo: geoaddress.nonGeo } }, { runValidators: true }, (err) => {
                                //    if (err) {
                                //        address.error = err.msg;
                                //        resolve(address);
                                //    } else {
                                //        resolve(geoaddress);
                                //        //let ret = { _id: location._id, name: record.name, address: location.address, coordinates: location.address.geo.coordinates };
                                //        //resolve(ret);
                                //    }
                                //});
                            }
                        } else {
                            address.error = 'invalid';
                            resolve(address);
                        }
                    }
                }
            } catch (e) {
                // return reject(e);
                console.log(e);//console.log(e.message);
                resolve(address);
            }
        });
    }
    

}

module.exports = new Company();

Open in new window


...and here's the activity service...

const { ObjectId } = require('mongodb');
const { Util } = require('node-utils');
const moment = require('moment-timezone');
const Service = require('./service');

const mongoose = require('mongoose');
const ProposalSchema = require('../schemas/ProposalSchema');
const CompanySchema = require('../schemas/CompanySchema');
const UserSchema = require('../schemas/UserSchema');
const ActivitySchema = require('../schemas/ActivitySchema');

class Activity extends Service {

    constructor() {
        super();

        this.collection = 'activities';
        this.plural = 'activities';
        this.singular = 'activity';
        this.model = mongoose.model('Activity', ActivitySchema);        
        //this.fields = require('../lib/model-proposal');
    }   
}

module.exports = new Activity();

Open in new window


The activity service seems to be nothing other than architecture where the company service seems to be both architecture and a solid amount of database interaction code.

You'll notice a feeble beginning at , but I feel like a pig on rollerskates.

I need to retrieve the "activity" based on the activity id and forward those values into the aforementioned...

self.$el.find('#formit-notes').val("hello");
self.$el.find('#formit-date').val("04/04/2020");
self.$el.find('#formit-activityType').val("Call Note");

...variables.

How?
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Hey Bruce,

Bit of a tricky one this. A few bits of your architecture that I don't understand, so we may have to work the problem !

Firstly, if you want to retrieve a single Note, then you're going to need a method to do this (and probably a route as well). If you don't already have a method, then you'll need to create one - maybe inside your Company model, but probably inside your Activity model. If you look at your Company model, you'll see several getOne methods (getOneContact, getOneAddress). I think you'll need to replicate that:

getOneActivity(activityId, companyId, type) {
    ... make your DB query here!
}

Open in new window

Then you'll be able to retrieve an activity with a call to Activity.getOneActivity(...)

One of the bits I can't see is where you getting the Activity ID from. Your displayActivityForm() method takes in 3 arguments - I get the Company and Type, but it also passed in proposalId - is this how the Activity ID is being passed in ?

If you get your app set up so you can at least retrieve a single note (activity), then we can move on to populating the form with that data.
Avatar of Bruce Gust

ASKER

Hey, Chris!

Since posing the question, I was able to make some progress. Don't got away. Let me get to a place where I can pose an intelligent question and I'll be right with you. I need to knock it out of the park today...

Here's where I'm at:

My "acitivityID" is part of the data I'm embedding in my link:

<a href="#" class="note-link" data-prospect-id="{{ data._id }}" data-route="companies" data-company-name="{{ data.name|e('html_attr') }}" data-user-id="{{ (data.owner is empty?'undefined':data.owner._id) }}" data-activitId="{activity._id}}" data-toggle="tooltip" title="Edit Activity" data-activity-type="note" data-activityId={{ activity._id }}" style="float:right;"><i class="fas fa-fw fa-pencil fa-pencil-alt"></i></a>

...and that works as far as yielding accurate data.

So, "note-link" goes here:

$(document).on('click', '.note-link', function () {
      //console.log("boom");
      //console.log(activityId);
      var id = (typeof $(this).attr('data-company-id') != 'undefined') ? $(this).attr('data-company-id') : $(this).attr('data-prospect-id');
        //var cId = $(this).attr('data-company-id'),
      var cId = id, 
      pId = $(this).attr('data-proposal-id'),
      type = $(this).attr('data-activity-type');
      activityId = $(this).attr('data-activityId');
      route = ((typeof $(this).attr('data-route') == 'undefined') ? route : $(this).attr('data-route'));


        if (typeof cId == 'undefined' || typeof type == 'undefined') {
            CAMS.alert('Invalid Link', 'The selected link is not properly formatted. Please refresh the page or contact support.', 'error');
        }

        CAMS.displayActivityForm(cId, pId, type, activityId); //this is what's creating your fields
        // Engage / Add Activity for filtered or bulk dataset
        $companySelect = $(document).find('select[name="company"].select2');
        if (typeof $companySelect != 'undefined') {
            if ($companySelect.length > 0) {
                if (cId == 'bulk') {
                    // add the select2 elements
                    CAMS.createCompanySelector($companySelect);
                    // check for a company id in the opts
                    var _company = pickedList_s();
                    if (typeof _company != 'undefined') {
                        if (Array.isArray(_company)) {
                            _company.forEach((item) => {
                                $companySelect.append('<option value="' + item.id + '" selected="selected">' + item.name + '</option>').trigger('change');
                            });
                        }
                    }
                } else {
                    $companySelect.closest('.form-group').remove();
                }
            }
        }
    });

Open in new window


You'll notice on line #9, I've got my "activityID." I've console.log-ed that so I know that exists and it's credible.

On line #17, I've introduced yet another method that's similar to what's already in place, but with a couple of differences. Here's what I've got thus far:

this.displayActivityForm = function (companyId, proposalId, type, activityId) {
      console.log(activityId);
      /*
      $.get('/companies/proposal/delete/' + id, function (resp) {
                if (resp.error) {
                    CAMS.alert('Error', resp.msg, 'error');
                    return false;
                }
                CAMS.alert('Success', 'Your proposal has been deleted successfully');
                $this.parents('.card').remove();
            }, 'json').fail(function () {
                CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
            });
         */

        var model = objectModels[type],
   
            fc = model.singular.substring(0, 1),
            config = {
                title: 'Add a' + ((fc == 'a' || fc == 'e' || fc == 'i' || fc == 'o' || fc == 'u') ? 'n' : '') + ' ' + ucwords(model.singular),
                directionsText: 'Make your changes below and then click, "SAVE."',
                fields: model.fields,
                onShow: function (self) {
                    // add in the additional events and plugins
                    // add in datetime support
                    self.$el.find('input.field-datetime').datepicker({
                        autoClose: true,
                        language: 'en',
                        timepicker: true,
                        dateFormat: 'mm/dd/yyyy',
                        timeFormat: 'h:ii AA',
                        showEvent: 'focus',
                        minutesStep: 5
                    });
               self.$el.find('#formit-notes').val("hello");
               self.$el.find('#formit-date').val("04/04/2020");
               self.$el.find('.form-control displayType').val("Call Note");

           

                },
                ajax: {
                    path: '/companies/edit-activity',
                    params: {
                        company: companyId,
                        proposal: proposalId,
                        type: type,
                    },
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }
                        companyId = (companyId == 'bulk' ? resp.data.id : companyId);
                        recordId = companyId;
                        $(window).trigger('open-company-details', [companyId, ((typeof route != 'undefined') ? route : '/companies/'), 'history']);
                    }
                }
            };

        // show the form
        formIt.show(config);
    };

The first section that I have in bold is a working query that I found in another section of the app. Based on the Udemy course I'm going through right now, I recognized it as some usable scaffolding as far as the implementation of route that will engage a query and return the information that I need.

The second section of code that I have in bold is where I'm going to place the info I'm able to retrieve so it's positioned to be displayed by the formit.js dynamic.

Finally, what I have underlined is the route that I'm going to have to adjust so the result is the editing of information rather than the insertion of that data.

Here's a couple of screenshots of the collections as they exist in the Mongo database:

Activities

User generated image


Companies...

User generated image



And here are the "services" that I believe are relevant to the way in which those two collections are related to one another. I know there's different terminology and techniques involved here, as opposed to relational databases, but I'm thinking there's still a relationship that needs to be acknowledged...

activity.js


const { ObjectId } = require('mongodb');
const { Util } = require('node-utils');
const moment = require('moment-timezone');
const Service = require('./service');


const mongoose = require('mongoose');
const ProposalSchema = require('../schemas/ProposalSchema');
const CompanySchema = require('../schemas/CompanySchema');
const UserSchema = require('../schemas/UserSchema');
const ActivitySchema = require('../schemas/ActivitySchema');


class Activity extends Service {


    constructor() {
        super();


        this.collection = 'activities';
        this.plural = 'activities';
        this.singular = 'activity';
        this.model = mongoose.model('Activity', ActivitySchema);        
        //this.fields = require('../lib/model-proposal');
    }  
}


module.exports = new Activity();

Open in new window


company.js

const { ObjectId } = require('mongodb');
const { Util } = require('node-utils');
const moment = require('moment-timezone');
const mongoose = require('mongoose');
const uuid = require('uuid/v4');


const Service = require('./service');
const CompanySchema = require('../schemas/CompanySchema');
const ActivitySchema = require('../schemas/ActivitySchema');
const EventSchema = require('../schemas/EventSchema');
const ProposalSchema = require('../schemas/ProposalSchema');
const SavedFilterSchema = require('../schemas/SavedFilterSchema');
const UserSchema = require('../schemas/UserSchema');
const CompanyContactSchema = require('../schemas/CompanyContactSchema');
const CompanyAddressSchema = require('../schemas/CompanyAddressSchema');
const CompanyAddress = require('../services/companyaddress');
const GeoLocations = require('../services/GeoLocations');


const objectModels = require('../lib/object-models');
const Vendors = require('../lib/Vendors');


const ServiceSchema = require('../schemas/ServiceSchema');
const ProductsAndService = mongoose.model('Service', ServiceSchema);
const Proposal = mongoose.model('Proposal', ProposalSchema);
const User = require('../services/user.js');


let userModel = mongoose.model('User', UserSchema);


class Company extends Service {


    constructor() {
        super();


        this.collection = 'companies';
        this.plural = 'companies';
        this.singular = 'company';


        this.model = mongoose.model('Company', CompanySchema);


        this.fields = require('../lib/model-company');
        this.fields._id = {};
        this.fields._id.type = ObjectId;


        this.corePipeline = [
            {
                $lookup: {
                    from: 'users',
                    foreignField: '_id',
                    localField: 'owner',
                    as: 'owner'
                }
            },
            {$unwind: {path: '$owner',preserveNullAndEmptyArrays: true}},
                //{ "$addFields": { "brokers": { "$slice": ["$brokers", 1] } } },
                //{ "$unwind": { path: "$brokers", preserveNullAndEmptyArrays: true } },
                //{ "$addFields": { "contacts": { "$slice": ["$contacts", 1] } } },
                //{ "$unwind": { path: "$contacts", preserveNullAndEmptyArrays: true } },
                //{ '$match': { 'addresses.postal': { '$in': global._user.account.postalCodes } } }
           
        ];
    }


    datatable(input, baseFilters = {}) {
      //console.log(global._user.account.postalCodes);
      return new Promise((resolve, reject) => {
         let config = this._getDataTablesFilters(input);
         let pipeline = [];
         let countPipeline = []; // the filters used for counts


         // add in the base filters
         config.filters = Util.merge(baseFilters, config.filters);


         // set the base pipeline where/match clause
         pipeline.push({ $match: this._enforceScope() });


         // add sorting
         if (Object.keys(config.sort).length > 0) {
            if (typeof config.sort[0] == 'undefined') {
               pipeline.push({ $sort: config.sort });
            }


         }
         // Owner
         pipeline.push(
            {$lookup: {from: 'users',let: { 'ownerId': '$owner' },pipeline: [{$match: {$expr: {$and: [{ $eq: ["$_id", "$$ownerId"] }]}}},{$project: {name: {$concat: ['$firstName', ' ', '$lastName']}}}],as: 'owner'}},
            { $unwind: { path: '$owner', preserveNullAndEmptyArrays: true } }
         );
         // Broker            
         pipeline.push(
            { "$addFields": { "brokers": { "$slice": ["$brokers", 1] } } },
            { "$unwind": { path: "$brokers", preserveNullAndEmptyArrays: true } }
         );
         pipeline.push(
            { "$addFields": { "contacts": { "$slice": ["$contacts", 1] } } },
            { "$unwind": { path: "$contacts", preserveNullAndEmptyArrays: true } }
         );
         //pipeline.push(
         //    { "$addFields": { "addresses": { "$slice": ["$addresses", 1] } } },
         //    { "$unwind": { path: "$addresses", preserveNullAndEmptyArrays: true } }
         //);
         if(global._user.account.postalCodes) {
             pipeline.push({
               $match: {
                 $or: [
                  { 'addresses.postal': { $in: global._user.account.postalCodes } },
                  { clientImport: global._user.account._id }
                 ]
               }
              });
         }




         // Search text      
         if (typeof input.search != 'undefined') {
            if (input.search.value) {


               var searchQuery = this._getDataTablesSearch(input.search.value);
               if (typeof searchQuery != 'undefined') {
                  pipeline.push({ $match: searchQuery });
               }
            }
         }


         // set the filters pipeline where/match clause
         if (Object.keys(config.filters).length > 0) {
            pipeline.push({ $match: config.filters });
         }


         // set the count pipeline here since all of the filters should be applied
         // by this point
         countPipeline = Array.from(pipeline);








         // add the limits
         pipeline.push({ $skip: config.limits[0] });
         pipeline.push({ $limit: config.limits[1] });


         // add in a datatable specific field
         pipeline.push({
            $addFields: {
               DT_RowId: '$_id',
               currentUserId: global._user._id //for 'Assign to me' link
            }
         });


         // call the lifecycle method to allow extending classes to customize just
         // the pipeline without having to overwrite the whole method
         pipeline = this._beforeDatatablesPipeline(pipeline);




         this.model.aggregate(pipeline).then(async (data) => {
            resolve({
               draw: parseInt(input.draw),
               data: data,
               recordsFiltered: await this.__aggCount(countPipeline),//filter wrong? await this._count(this._enforceScope()),
               recordsTotal: await this._count(this._enforceScope())
            });
         }).catch((err) => {
            //console.log("it's here we've got a problem");
            console.log('Aggregate Error: ', err);
            reject(err);
         });
      });
    }




    getOne(companyId) {
        return new Promise((resolve, reject) => {
            companyId = this._getId(companyId);
            if (!companyId) {
                return reject('Invalid company ID provided.');
            }


            // create a clone of the pipeline so we don't alter the original
            let pipeline = this.corePipeline.slice(0);


            // add an initial match stage to the core pipeline
            pipeline.unshift({
                $match: this._enforceScope({
                    _id: companyId
                })
            });


            this.model.aggregate(pipeline).then((data) => {
                if (data.length === 0) {
                    reject('Could not find record.');
                } else {
                    resolve(data[0]);
                }
            }).catch((err) => {
                reject(err);
            });
        });
    }
    getOneContact(contactId, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            let contact_id = this._getId(contactId);
            let pipeline = [{ $match: { _id: company_Id } },
            {$project: {
                contacts: {$filter: {
                    input: "$contacts",
                    as: "contacts",
                    cond: { $eq: ["$$contacts._id", contact_id] }
                    }}
            }},
            {$addFields:{'contacts.company':'$_id'}},
            {$unwind:{path:"$contacts",preserveNullAndEmptyArrays:true}},
                { $project: { 'contacts': 1, _id: 0 } }];
            this.model.aggregate(pipeline).then((rows) => {
                resolve(rows[0].contacts);
            }).catch((error) => {
                console.log(error.message);
                reject(error.message);
            });          
        });
    }
    saveContact(contactId, contact) {
        return new Promise((resolve, reject) => {
            let companyId = contact.company;
            contact.active = true;
            if (contactId === 'new') {                        
                delete contact.company;
                this.model.updateOne({ _id: companyId }, { $push: { contacts: contact } }, { setDefaultsOnInsert: true }).then(response => {                    
                    contact.company = companyId;
                    resolve(contact);
                }).catch(err => {
                    reject(err);
                });
            } else {
                this.model.updateOne({ _id: companyId },
                    {
                        $set: {
                            'contacts.$[i].email': contact.email,
                            'contacts.$[i].name': contact.name,
                            'contacts.$[i].phone': contact.phone
                        }
                    },
                    {
                        arrayFilters: [{
                                "i._id": this._getId(contactId)
                            }], setDefaultsOnInsert: true
                    }
                ).then(response => {
                    contact.company = companyId;
                    resolve(contact);
                }).catch(err => {
                    reject(err);
                });
            }
           
        });
    }
    getOneAddress(addressId, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            let address_id = this._getId(addressId);
            let pipeline = [{ $match: { _id: company_Id } },
            {$project: {
                addresses: {$filter: {
                    input: "$addresses",
                    as: "addresses",
                    cond: { $eq: ["$$addresses._id", address_id] }
                    }}
            }},
            {$addFields:{'addresses.company':'$_id'}},
            {$unwind:{path:"$addresses",preserveNullAndEmptyArrays:true}},
                { $project: { 'addresses': 1, _id: 0 } }];
            this.model.aggregate(pipeline).then((rows) => {
                resolve(rows[0].addresses);
            }).catch((error) => {
                console.log(error.message);
                reject(error.message);
            });          
        });
    }
    saveAddress(addressId, address) {
        return new Promise((resolve, reject) => {
            let companyId = address.company;
            address.active = true;
            if (addressId === 'new') {
                delete address.company;
                this.model.updateOne({ _id: companyId }, { $push: { addresses: address } }, { setDefaultsOnInsert: true }).then(response => {
                    address.company = companyId;
                    resolve(address);
                }).catch(err => {
                    reject(err);
                });
            } else {
                this.model.updateOne({ _id: companyId },
                    {
                        $set: {
                            'addresses.$[i].street': address.street,
                            'addresses.$[i].city': address.city,
                            'addresses.$[i].state': address.state,
                            'addresses.$[i].postal': address.postal,
                            //'addresses.$[i].geo': geoaddress.geo,
                            'addresses.$[i].hash': address.hash,
                            'addresses.$[i].nonGeo': address.nonGeo
                        }
                    },
                    {
                        arrayFilters: [{
                            "i._id": this._getId(addressId)
                        }], setDefaultsOnInsert: true
                    }
                ).then(response => {
                    address.company = companyId;
                    resolve(address);
                }).catch(err => {
                    reject(err);
                });
            }


        });
    }
    getOneBroker(index, companyId) {
        return new Promise((resolve, reject) => {
            let company_Id = this._getId(companyId);
            this.model.findOne({ _id: company_Id, account: global._user.account._id }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                resolve(res.brokers[index]);
            });
        });
    }


    saveBroker(index, broker) {
        return new Promise((resolve, reject) => {
            let companyId = this._getId(broker.company);
            let accountId = this._getId(broker.account);
            delete broker.company;
            delete broker.account;
            this.model.findOne({ _id: companyId, account: accountId }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                res.brokers = res.brokers ? res.brokers : [];
                if (index == 'new') {                    
                    res.brokers.push(broker);
                    broker = res.brokers;
                } else {
                    res.brokers[index] = broker;
                    broker = res.brokers;
                }
                this.model.updateOne({ _id: companyId, account: accountId }, { $set: { brokers: broker }}, (err, raw) => {
                    if (err) { console.log(err); reject(err); }
                    resolve(raw);
                });
            });
        });
    }
    //Fix: This function will check for dates field type array and convert it into object. Converts array field to Object
    resolveDatesArray() {
        return new Promise((resolve, reject) => {
            let condition = { dates: { $type: "array" } };
            this.model.updateMany(condition, { dates: {} }, { upsert: true }, (err, raw) => {
                if (err) {
               console.log(err);
               reject(err);
            }
                resolve(raw);
            });            
        });
    }
    select2(query) {
        return new Promise((resolve, reject) => {
            this.model.aggregate([
                {
                    '$match': this._enforceScope({
                        name: {
                            '$regex': query,
                            '$options': 'i'
                        }
                    })
                },
                {
                    '$sort': {
                        name: 1
                    }
                },
                { '$limit': 25 },
                {
                    '$project': {
                        id: '$_id',
                        text: '$name'
                    }
                }
            ]).then((rows) => {
                resolve(rows);
            }).catch((err) => {
                reject(err);
            });
        });
    }


    assign(companies, user) {
        return new Promise((resolve, reject) => {
            let where = this._enforceScope({ _id: { $in: [] } });
            let update = { $set: {} };


            if (typeof user == 'undefined' || companies == 'undefined') {
                return reject('Invalid or missing parameters.');
            }


            let ids = [];
            for (let i in companies) {
                where._id['$in'].push(this._getId(companies[i]));
                ids.push(this._getId(companies[i]));
            }
            let pipeline = [{ $match: { _id: { $in: ids } } }, { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } }];
            this.model.aggregate(pipeline).then((beforeRows) => {




                update = {
                    $set: {
                        owner: this._getId(user),
                        account: global._user.account._id,//new added
                        active: true,//new added
                        'dates.assigned': new Date(moment().toISOString())// new added for reporting, pipeline target column display
                    }
                };                


                this.model.updateMany(where, update, (err, res) => {
                    if (err) {
                        reject(this.error('Invalid parameters provided.'));
                    } else {
                        let count = 0;
                        beforeRows.forEach((oldDoc) => {
                            pipeline = [{ $match: { _id: oldDoc._id } }, { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } }, { $limit: 1 }];
                            this.model.aggregate(pipeline).then(async (rows) => {
                                let newDoc = rows[0];
                                let meta = await this.jsonDiff(
                                    { owner: (oldDoc.owner.length > 0) ? '<a href="javascript:void(0);" class="user-info" data-user-id="' + oldDoc.owner[0]._id + '">' + oldDoc.owner[0].firstName + ' ' + oldDoc.owner[0].lastName + '</a>' : 'Unassigned' },
                                    { owner: (newDoc.owner.length > 0) ? '<a href="javascript:void(0);" class="user-info" data-user-id="' + newDoc.owner[0]._id + '">' + newDoc.owner[0].firstName + ' ' + newDoc.owner[0].lastName + '</a>' : 'Unassigned' }
                                );


                                let history = await this.addHistory('Owner change', newDoc._id, '', global._user._id, meta);
                                count = count + 1;
                                if (count = beforeRows.length) {
                                    resolve(this.success());
                                }
                            });


                        });
                    }
                });
            });
        });
    }


    unassign(companies) {
        return new Promise((resolve, reject) => {            
            let update = { $set: { owner: null } };
            let id;


            if (companies == 'undefined') {
                reject('Invalid or missing parameters.');
            }


            for (let i in companies) {
                id = this._getId(companies[i]);
                if (id) {
                    let pipeline = [
                        { $match: { _id: id } },
                        { $lookup: { from: "users", localField: "owner", foreignField: "_id", as: "owner" } },                        
                        { $limit: 1 }];
                    this.model.aggregate(pipeline).then((res) => {
                        if (res.length > 0) {                            
                            this.model.updateOne({ _id: id }, update, async(err, doc) => {
                                if (err) { console.log(err); }
                                if (typeof res[0].owner != 'undefined') {
                                    let meta = await this.jsonDiff(
                                        { owner: res[0].owner.length > 0 ? '<a href="javascript:void(0)" class="user-info" data-route="company" data-user-id="' + res[0].owner[0]._id + '">' + res[0].owner[0].firstName + " " + res[0].owner[0].lastName + '</a>' : "Unassigned" },
                                        { owner: 'Unassinged' }
                                    );
                                    await this.addHistory('Owner change', id, '', global._user._id, meta);
                                }                                
                                if ((parseInt(i)+1) === companies.length) {
                                    resolve(this.success());
                                }
                            });
                        }
                    }).catch((error) => { console.log(error); });
                }                
            }
        });
    }
    softDeleteItems(companies) {
        return new Promise((resolve, reject) => {
            if (typeof companies == 'undefined' || companies === 0) {
                return reject(Company.error('Please provide one or more company ID\'s.'));
            }            
            for (let i in companies) {
             let  id = this._getId(companies[i]);
                if (id) {
                    let pipeline = [
                        { $match: { _id: id } },
                        { $lookup: { from: "proposals", localField: "_id", foreignField: "company", as: "proposals" } },
                        { $limit: 1 }];
                    this.model.aggregate(pipeline).then((res) => {
                        if (res.length > 0) {
                            this.model.updateOne({ _id: id }, {$set: {deleted: true,active: false}}, async (err, doc) => {
                                if (err) { console.log(err); }
                                // delete Proposals
                                if (res[0].proposals.length > 0) {
                                    await Proposal.updateMany({ company: id }, { $set: { active: false } }, async (err, doc) => {
                                        if (err) { console.log(err);}
                                        // Todo nothing.
                                    });
                                }
                                let meta = await this.jsonDiff(
                                    { active: true },
                                    { active: false, deleted:true }
                                );
                                await this.addHistory('Company deleted', id, '', global._user._id, meta);


                                if ((parseInt(i) + 1) === companies.length) {
                                    resolve(this.success());
                                }
                            });
                        }
                    }).catch((error) => { console.log(error); });
                }
            }
        });
    }


    getActivity(companyId) {
        return new Promise((resolve, reject) => {
            const Activity = mongoose.model('Activity', ActivitySchema);
            //let pipeline = [
            //            {
            //                $match: {
            //                    account: global._user.account._id,
            //                    company: companyId
            //                }
            //            },
            //            {
            //                $sort: {
            //                    date: -1
            //                }
            //            },
            //            { $limit: 100 },
            //            {
            //                $lookup: {
            //                    from: 'users',
            //                    foreignField: '_id',
            //                    localField: 'user',
            //                    as: 'user'
            //                }
            //            },
            //            { $unwind: '$user' }
            //        ];
            //  Activity.aggregate(pipeline).then((rows) => {
            //  var activity = [];


            //  for (let i in rows) {
            //    // get the icon by type
            //    rows[i].icon = this.getIconByType(rows[i].type);


            //    // add it to the list
            //    activity.push(rows[i]);
            //  }


            //  resolve(activity);
            //}).catch((err) => {
            //  reject(err);
            //});
            let pipeline = [
                {
                    $match: {
                        account: global._user.account._id,
                        company: companyId
                    }
                },
                {
                    $lookup: {
                        from: 'users',
                        foreignField: '_id',
                        localField: 'user',
                        as: 'user'
                    }
                },
                { $unwind: '$user' },
                {
                    $group: {
                        '_id': {
                            year: { $year: "$date" },
                            month: { $month: "$date" },
                            day: { $dayOfMonth: "$date" }
                        },
                        activities: {
                            $push: {
                                _id: '$_id',
                                type: '$type',
                                company: '$company',
                                proposal: '$proposal',
                                user: { _id: '$user._id', 'firstName': '$user.firstName', 'lastName': '$user.lastName' },
                                date: '$date',
                                meta: '$meta'


                            }
                        }
                    }
                },
                { $project: { date: '$_id', activities: 1, _id: 0 } },
                { $sort: { "activities.date": -1 } }
            ];
            Activity.aggregate(pipeline).then((rows) => {
                var activity = [];


                for (let i in rows) {
                    for (let j in rows[i].activities) {
                        // get the icon by type
                  /*added some additional options for call, note and visit in order to display according to the date of the action
                  and not the documention
                  */
                  if(rows[i].activities[j].type =="call" || rows[i].activities[j]=="note" || rows[i].activities[j] == "visit") {
                     rows[i].activities[j].thePrettyDate = moment(rows[i].activities[j].meta.date).fromNow();
                     rows[i].activities[j].theReadableDate = moment(rows[i].activities[j].meta.date).format('MMM Do - LT');
                     rows[i].activities[j].theDoableDate = moment(rows[i].activities[j].meta.date).format('m/d/Y');
                     rows[i].activities[j].icon = this.getIconByType(rows[i].activities[j].type);                        
                     rows[i].activities[j].prettyDate = moment(rows[i].activities[j].date).fromNow();
                     rows[i].activities[j].readableDate = moment(rows[i].activities[j].date).format('MMM Do - LT');
                     rows[i].activities[j].doableDate = moment(rows[i].activities[j].date).format('m/d/Y');
                  }
                  else {
                     rows[i].activities[j].icon = this.getIconByType(rows[i].activities[j].type);                        
                     rows[i].activities[j].prettyDate = moment(rows[i].activities[j].date).fromNow();
                     rows[i].activities[j].readableDate = moment(rows[i].activities[j].date).format('MMM Do - LT');
                     rows[i].activities[j].doableDate = moment(rows[i].activities[j].date).format('m/d/Y');
                  }
                    }
                    // add it to the list
                    rows[i].prettyDate = moment.utc(rows[i].date.year + '-' + rows[i].date.month + '-' + rows[i].date.day).local().fromNow();
                    activity.push(rows[i]);


                }


                resolve(activity);
            }).catch((err) => {
                reject(err);
            });
        });
    }


    getFiles(companyId) {
        return new Promise((resolve, reject) => {
            const Proposal = mongoose.model('Proposal', ProposalSchema);


            Proposal.aggregate([
                {
                    $match: {
                        company: companyId,
                        files: {
                            $exists: true
                        }
                    }
                },
                { $unwind: '$files' },
                {
                    $project: {
                        proposal: '$_id',
                        name: '$name',
                        file: '$files'
                    }
                }
            ]).then((rows) => {
                resolve(rows);
            }).catch((err) => {
                console.log('Error: ', err);
                reject(err);
            });
        });
    }


    addActivity(companyId, type, data) {
        return new Promise(async(resolve, reject) => {
            if (typeof type != 'string' || ['call', 'visit', 'reminder', 'event'].indexOf(type.trim()) == -1) {
                return reject('Invalid type provided');
            }
            const Schema = mongoose.Schema;
            const Base = mongoose.model('Activity', ActivitySchema);
            // to track activity on each pipeline stage
            if (data.proposal != 'undefined') {
                if (data.proposal != 'bulk') {
                    if (data.proposal) {
                        await Proposal.findById(this._getId(data.proposal), (err, res) => {
                            if (err) { console.log(err); }
                            if (res) {
                                data.pipeline = res.pipeline;
                            }
                        });
                    }
                }
            }
                       
            if (type == 'event') {
                // define dynamic Schema
                const Event = Base.discriminator('event', new mongoose.Schema({meta: {start: Date,end: Date,subject: String,participants: String,location: String,details: String}}));
                let _data = {
                    company: new ObjectId(companyId),
                    type: type.trim(),
                    meta: {
                        start: data.start,
                        end: data.end,
                        subject: data.subject,
                        participants: data.participants,
                        location: data.location,
                        details: data.details
                    },
                    user: global._user._id,
                    account: global._user.account._id
                };
                if (data.proposal != 'undefined') {
                    if (data.proposal != 'bulk') {
                        if (data.proposal) {
                            _data.proposal = data.proposal;
                            _data.pipeline = data.pipeline;
                        }
                    }
                }
                Event.create(_data, (err, record) => {
                    if (err) {
                        console.log('Error: ', err);
                        reject('An unexpected error was encountered. Please try again.');
                    } else {
                        resolve(record._id);
                    }
                });
            } else {
                // define dynamic Schema
                //FIX: descriminator with name 'call' already exists.
                const ActivityModel = Base.discriminators ? Object.keys(Base.discriminators).indexOf(type.trim()) >= 0 ? Base.discriminators[type.trim()] : Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } })) : Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } }));
                //const ActivityModel = Base.discriminator(type.trim(), new mongoose.Schema({ meta: { date: Date, notes: String } }));
                let _data = {
                    company: new ObjectId(companyId),
                    type: type.trim(),
                    meta: {
                        date: data.date,
                        notes: data.notes
                    },
                    user: global._user._id,
                    account: global._user.account._id
                };
                if (data.proposal != 'undefined') {
                    if (data.proposal != 'bulk') {
                        if (data.proposal) {
                            _data.proposal = data.proposal;
                            _data.pipeline = data.pipeline;
                        }
                    }
                }
                ActivityModel.create(_data, (err, record) => {
                    if (err) {
                        console.log('Error: ', err);
                        reject('An unexpected error was encountered. Please try again.');
                    } else {
                        resolve(record._id);
                    }
                });
            }
        });
    }
   
   retrieveActivity(activityId) {
      
      
      }


    deleteActivity(activityId) {
        return new Promise((resolve, reject) => {
            let match = this._enforceScope({
                _id: new ObjectId(activityId)
            });


            const Activity = mongoose.model('Activity', ActivitySchema);


            Activity.deleteOne(match, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });
        });
    }


    exportToCSV(input) {
        return new Promise((resolve, reject) => {
            let config = this._getDataTablesFilters(input);
            let pipeline = [];
            let baseFilters = {
                account: global._user.account._id,
                active: true,
                deleted: {
                    $exists: false
                }
            };


            // add in the base filters
            config.filters = Util.merge(baseFilters, config.filters);


            // set the base pipeline where/match clause
            pipeline.push({ $match: this._enforceScope() });


            // lifecylce method to give the user the ability to inject setup stages to
            // the pipeline before we start adding in user-defined filters, limits and
            // sorting options
            pipeline = this._startPipeline(pipeline);


            // Search text      
            if (typeof input.search != 'undefined') {
                if (input.search.value) {


                    var searchQuery = this._getDataTablesSearch(input.search.value);
                    if (typeof searchQuery != 'undefined') {
                        pipeline.push({ $match: searchQuery });
                    }
                }
            }


            // set the filters pipeline where/match clause
            if (Object.keys(config.filters).length > 0) {
                pipeline.push({ $match: config.filters });
            }


            // add sorting
            if (Object.keys(config.sort).length > 0) {
                pipeline.push({ $sort: config.sort });
            }


            // we need to format the arrays - not sure what the heck is going on with
            // using $addresses.0.street in the projection stage below, but I had some
            // issues getting it to work
            pipeline.push({
                $addFields: {
                    _contact: {
                        $slice: ['$contacts', 1]
                    },
                    _address: {
                        $slice: ['$addresses', 1]
                    }
                }
            });


            pipeline.push({
                $unwind: {
                    path: '$owner',
                    preserveNullAndEmptyArrays: true
                }
            });


            pipeline.push({
                $unwind: {
                    path: '$_contact',
                    preserveNullAndEmptyArrays: true
                }
            });


            pipeline.push({
                $unwind: {
                    path: '$_address',
                    preserveNullAndEmptyArrays: true
                }
            });


            // add the project stage
            pipeline.push({
                $project: {
                    name: '$name',
                    owner: '$owner.name',
                    contact_name: '$_contact.name',
                    contact_email: '$_contact.email',
                    contact_phone: '$_contact.phone',
                    address_street: '$_address.street',
                    address_city: '$_address.city',
                    address_state: '$_address.state',
                    address_postal: '$_address.postal',
                    address_county: '$_address.county',
                    industry: '$meta.industry',
                    ftes: '$meta.ftes',
                    fteGrouping: '$meta.fteGrouping',
                    premium: '$meta.premium',
                    premiumPerFte: '$meta.premiumPerFte',
                    brokerCommissionTotal: '$meta.brokerCommissionTotal',
                    brokerFeesTotal: '$mata.brokerFeesTotal',
                    fundingType: '$meta.fundingType',
                    ein: '$meta.ein'
                }
            });


            // get the data
            this.model.aggregate(pipeline).then((rows) => {
                const papaparse = require('papaparse');
                console.log('Data: ', JSON.stringify(rows, undefined, 2));
                let csv = papaparse.unparse(rows);


                resolve(csv);
            }).catch((err) => {
                reject(err);
            });
        });
    }


    _startPipeline(pipeline) {
        let coreClone = this.corePipeline.slice(0);


        // remove the first stage of the core to add in the below projection
        coreClone.shift();


        // add in the owner's info
        coreClone.unshift({
            $lookup: {
                from: 'users',
                let: { 'ownerId': '$owner' },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $and: [
                                    { $eq: ["$_id", "$$ownerId"] }
                                ]
                            }
                        }
                    },
                    {
                        $project: {
                            name: {
                                $concat: ['$firstName', ' ', '$lastName']
                            }
                        }
                    }
                ],
                as: 'owner'
            }
        });


        return pipeline.concat(coreClone);
    }
    targetSelected(companies = [], user) {
        return new Promise(async (resolve, reject) => {
            try {
                if (companies.length > 0 && user.length > 0) {
                    let Targetpipelines = await this.getPipelineColumns();                    
                    var index = Targetpipelines.map(function (o) { return o.key; }).indexOf("target");
                    let Targetpipeline = Targetpipelines[index];
                    if (typeof Targetpipeline != 'undefined') {
                        let count = 0;
                        companies.forEach((company) => {
                            let targetProposal = {
                                name: '_target', owner: this._getId(user), company: this._getId(company), pipeline: Targetpipeline._id, active: true, services: [], files: [],
                                //dates: { target: new Date(moment().toISOString())},
                                _range: [new Date(moment().toISOString()), new Date(moment().toISOString())],
                                _pipelineDate: new Date(),
                                pipelineIndex: 0,
                                account: global._user.account._id,
                                pipelineDuration: [{
                                    pipelineFrom: Targetpipeline._id, fDate: new Date(moment().toISOString()),
                                    pipelineTo: Targetpipeline._id, tDate: new Date(moment().toISOString())
                                }]
                            };
                            targetProposal.dates = typeof targetProposal.dates == 'undefined' ? {} : targetProposal.dates;
                            targetProposal.dates[Targetpipeline._id] = new Date(moment().toISOString()), new Date(moment().toISOString());
                            Proposal.updateOne({ owner: this._getId(user), company: this._getId(company), name: '_target' }, targetProposal, { runValidators: true, upsert: true }, async(error, res) => {
                                if (error) {
                                    console.log(error);
                                }
                                let targetUser = await this.getUserbyID(user);//await User.getOne(this._getId(user));
                                if (targetUser) {
                                    let meta = { 'Target Selected to': "<a href='javascript:void(0);' class='user-info' data-user-id='" + targetUser._id + "' data-route='market'>" + targetUser.firstName + " " + targetUser.lastName + "</a>" };
                                    this.addHistory('Target selected', this._getId(company), '', global._user._id, meta);
                                }
                               


                                count = count + 1;
                                if (count == companies.length) {
                                    resolve(true);
                                }
                            });
                        });
                    } else {
                        reject('Pipeline Column is undefined.');
                    }
                } else {
                    reject('Invalid or undefined company id or user id provided.');
                }
            } catch (e) {
                console.log(e);
                reject(e);
            }
        });
    }
    getUserbyID(id) {
        return new Promise(async (resolve, reject) => {
            if (id) {
                userModel.findById(this._getId(id), (err, res) => {
                    if (err) { console.log(err); resolve(false);}
                    resolve(res);
                });
               
            } else {
                resolve(false);
            }
        });
    }
    ignoreTargetSelected(companies = []) {
        return new Promise(async (resolve, reject) => {
            try {
                if (companies.length > 0) {
                    let Targetpipelines = await this.getPipelineColumns();
                    var index = Targetpipelines.map(function (o) { return o.key; }).indexOf("target");
                    let Targetpipeline = Targetpipelines[index];
                    if (typeof Targetpipeline != 'undefined') {
                        let companyIds = [];
                        companies.forEach(async (company) => {
                            companyIds.push(this._getId(company));
                            await this.addHistory('Target ignored', this._getId(company), '', global._user._id, {});
                        });
                        Proposal.deleteMany({ company: { $in: companyIds }, name: '_target' }, (error) => {
                            if (error) { reject(error); }
                            resolve(true);
                        });


                    } else {
                        reject('Pipeline Column is undefined.');
                    }
                } else {
                    reject('Invalid or undefined company id provided.');
                }
            } catch (e) {
                console.log(e);
                reject(e);
            }
        });
    }


    getOneForHistory(id) {
        return new Promise((resolve, reject) => {
            id = this._getId(id);
            if (!id) {
                return reject('Invalid prospect ID provided.');
            }
            let pipeline = [{ $match: { _id: id } },
            {
                $lookup: {
                    from: "users",
                    let: { "ownerId": "$owner" },
                    pipeline: [
                        { $match: { $expr: { $eq: ["$_id", "$$ownerId"] } } },
                        {
                            $project: {
                                _id: 0,
                                assigned: { $concat: ["<a href='javascript:void(0)' class='user-info' data-user-id='", { $toString: "$_id" }, "'>", "$firstName", " ", "$lastName", "</a>"] }
                            }
                        }
                    ],
                    as: "owner"
                }
            },
            { $unwind: { path: "$owner", preserveNullAndEmptyArrays: true } },
            { $addFields: { owner: "$owner.assigned" } }
            ];




            this.model.aggregate(pipeline).then((data) => {
                if (data.length === 0) {
                    reject('Could not find record.');
                } else {
                    resolve(data[0]);
                }
            }).catch((err) => {
                reject(err);
            });
        });
    }
    getProposals(companyId) {
        return new Promise((resolve, reject) => {
            let scopedFilters = this._enforceScope();
            var pipeline = [
                {
                    $match: {
                        company: this._getId(companyId),
                        name: { "$ne": "_target" },// should not show _target proposals they are just 'Target Selected' pipeline
                        $or: [{ "active": { "$exists": false } }, { "active": true }]
                    }
                },
                {
                    $lookup: {
                        from: "pipelinecolumns",
                        localField: "pipeline",
                        foreignField: "_id",
                        as: "pipeline"
                    }
                },
                { $unwind: "$pipeline" },
                {
                    $lookup: {
                        from: "services",
                        localField: "services.service",
                        foreignField: "_id",
                        as: "products"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "owner",
                        foreignField: "_id",
                        as: "owner"
                    }
                },
                {
                    $project: {
                        "products.model": 0, "products.account": 0, "products.amount": 0,
                        "owner.settings": 0, "owner.password": 0, "owner.email": 0, "owner.mobile": 0, "owner.account": 0
                    }
                },
                {
                    $unwind: "$owner"
                }];


            Proposal.aggregate(pipeline, (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows);
                }
            });
        });
    }
    getService(serviceId) {
        return new Promise((resolve, reject) => {
            let pipeline = [{ $match: { "_id": serviceId } }];
            ProductsAndService.aggregate(pipeline, (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows[0]);
                }
            });
        });
    }
    heatmap(ids) {
        return new Promise((resolve, reject) => {
            let pipeline = [];


            let _ids = [];
            if (ids && ids.length > 0) {
                ids.forEach((id) => {
                    _ids.push(this._getId(id));
                });


                let match = { $match: this._enforceScope() };
                delete match['$match']['account'];
                match['$match']._id = { $in: _ids };
                pipeline.push(match);
                pipeline.push(
                    { $unwind: { path: "$addresses", preserveNullAndEmptyArrays: true } },
                    { "$addFields": { "company": { _id: "$_id", name: "$name" } } },
                    {
                        "$lookup": {
                            "from": "geo_locations", "let": { "addressId": "$addresses._id" }, "pipeline": [
                                { "$match": { "$and": [{ "$expr": { "$eq": ["$address", "$$addressId"] } }, { "$expr": { "$eq": ["$active", true] } }] } }], "as": "geo_locations"
                        }
                    },
                    { $unwind: { path: "$geo_locations", preserveNullAndEmptyArrays: true } },
                    {
                        "$project": {
                            "_id": 0,
                            "type": "Feature",
                            "properties": {
                                "name": '$name',
                                "popupContent": "$name",
                                "_id": "$_id", "street": "$addresses.street", "city": "$addresses.city", 'state': '$addresses.state', "postal": "$addresses.postal", "country": "$addresses.country", "county": "$addresses.county",
                                "addresses": "$addresses",
                                "company": "$company", "nonGeo": "$addresses.nonGeo"
                            },
                            "geometry": "$geo_locations.geo"
                        }
                    }
                );
                this.model.aggregate(pipeline).then(async (rows) => {
                    let count = 0;
                    rows.forEach(async (row, index) => {
                        if (row.geometry === undefined) {
                            row.properties.addresses = row.properties.addresses ? row.properties.addresses : {};
                            row.properties.addresses.company = row.properties.company._id;
                            let geoAddress = await this.getGeoAddress(row.properties.addresses);
                            rows[index].geometry = geoAddress.geo;
                            count = count + 1;
                        } else { count = count + 1; }
                        if (rows.length == count) {
                            resolve({ "type": "FeatureCollection", "features": rows });
                        }
                    });
                }).catch((err) => {
                    console.log('Aggregate Error: ', err);
                    reject(err);
                });
            } else {
                //reject('undefined parameter ids provided.');
                resolve({ "type": "FeatureCollection", "features": [] });
            }


        });
    }


    getGeoAddress(address = {}) {
        return new Promise(async (resolve, reject) => {
            try {
                if (typeof address.geo != 'undefined') {
                    resolve(address);
                } else {
                    var isValidAddress = false;                    
                    address.street = address.street ? address.street.trim() : address.street;
                    if (!address || address.street === '' || address.city === '' || address.state === '' || address.postal === '' || address.street === undefined || address.city === undefined || address.state === undefined || address.postal === undefined) {
                        isValidAddress = false;
                        address.error = 'invalid';
                        resolve(address);
                    }
                    else {
                        isValidAddress = true;
                    }
                    if (isValidAddress) {
                        let geoaddress = await CompanyAddress.getGeocode(address);
                        if (geoaddress) {
                            if (geoaddress.error_message) {
                                address.error = geoaddress.error_message;
                                resolve(address);
                            } else {
                                GeoLocations.model.updateOne(
                                    { address: address._id },//, account: global._user.account._id
                                    { $set: { address: address._id, company: address.company, geo: geoaddress.geo } },//account: global._user.account._id,
                                    { upsert: true, setDefaultsOnInsert: true }, (err) => {
                                        if (err) {
                                            resolve(address);
                                        } else {
                                            this.model.updateOne({ _id: address.company },
                                                {
                                                    $set: {
                                                        'addresses.$[i].street': geoaddress.street,
                                                        'addresses.$[i].city': geoaddress.city,
                                                        'addresses.$[i].state': geoaddress.state,
                                                        'addresses.$[i].postal': geoaddress.postal,
                                                        //'addresses.$[i].geo': geoaddress.geo,
                                                        'addresses.$[i].hash': geoaddress.hash,
                                                        'addresses.$[i].nonGeo': geoaddress.nonGeo
                                                    }
                                                },
                                                {
                                                    arrayFilters: [
                                                        {
                                                            "i._id": address._id
                                                        }]
                                                }
                                            ).then(response => {
                                                resolve(geoaddress);
                                            }).catch(err => {
                                                address.error = err.msg;
                                                resolve(address);
                                            });
                                        }
                                    });


                                //CompanyAddress.model.updateOne({ _id: address._id }, { '$set': { street: geoaddress.street, city: geoaddress.city, state: geoaddress.state, postal: geoaddress.postal, geo: geoaddress.geo, hash: geoaddress.hash, nonGeo: geoaddress.nonGeo } }, { runValidators: true }, (err) => {
                                //    if (err) {
                                //        address.error = err.msg;
                                //        resolve(address);
                                //    } else {
                                //        resolve(geoaddress);
                                //        //let ret = { _id: location._id, name: record.name, address: location.address, coordinates: location.address.geo.coordinates };
                                //        //resolve(ret);
                                //    }
                                //});
                            }
                        } else {
                            address.error = 'invalid';
                            resolve(address);
                        }
                    }
                }
            } catch (e) {
                // return reject(e);
                console.log(e);//console.log(e.message);
                resolve(address);
            }
        });
    }
   


}


module.exports = new Company();

Open in new window


Thanks, Chris!

Happy Friday!

OK,

Good amount of info to look through there. Just a few notes in general.

An AJAX call is asynchronous in nature, which means you can't use the results of that call outside of that call. A brief example:

Let someVar = "Chris";

$.get("getUser", response => {
    someVar = response.firstName;
}, 'json');

console.log(someVar);

Open in new window

Regardless of what the response is from getUser, the console will log "Chris". Why !! Because it's asynchronous. This means that as soon as you make the call to $.get(), that call get's pushed to the background and the code carries on running, firing the console.log(). The AJAX call will complete 'at some point in the future' and at that point, the success handler will fire and set the someVar variable to the response. Too late - you've already logged the output. You're effectively trying to use the response before you received the response.

What this means in your code, is that you can't make a $.get request to the server, and then later on use the results of that get request - you only get to use the response inside the success handler (or a continuation of it). So getting around that issue will be your first challenge. You can do this by either loading up the form in the success handler, or by passing the results of the call into another method:

let url = `/activities/${type}/${id}`

$.get(url, response => {
    // now you have a response
    var model = objectModels[type],
        fc = model.singular.substring(0, 1),
        config = {
            ...
            self.$el.find('#formit-notes').val(response.notes);
            self.$el.find('#formit-date').val(response.date);
        }
    
    formIt.show(config);
}, 'json')

Open in new window

Another challenge you'll face is that by setting your values like this, you're tightly coupling your method to an activity type of Notes. The method needs to be able to accomodate other types as well - Event, Email etc. Depending on the structure of your app, you may need to look into the logic surrounding that.

One other area I would suggest you look at is the loadData() method on the FormIt class. If I remember correctly there is method that conditionally tries to load data into a Form after it's been shown. The condition is whether the options passed in (the config object) has a loadDataFromUrl property set. It may be that instead of making the AJAX call in the showActivityForm method, you just set a property on config{} and let FormIt take care of it. Something along these lines:

this.displayActivityForm = function (companyId, proposalId, type, activityId) {

    var model = objectModels[type],
        fc = model.singular.substring(0, 1),
        config = {
            title: 'Add a' + ((fc == 'a' || fc == 'e' || fc == 'i' || fc == 'o' || fc == 'u') ? 'n' : '') + ' ' + ucwords(model.singular), 
            loadDataFromUrl : ` /activities/${type}/${id}`,
            fields: model.fields, 
            ...

Open in new window

When the Form is shown, it will check the loadDataFromUrl property, see that it's set and make an AJAX call to that URL. Worth investigating ?
I thought this:

 ajax: {
                    path: '/companies/edit-activity',
                    params: {
                        company: companyId,
                        proposal: proposalId,
                        type: type,
                    },
                    onComplete: function (resp, self) {
                        if (resp.error) {
                            self.addMsg(resp.msg);
                            return false;
                        }
                        companyId = (companyId == 'bulk' ? resp.data.id : companyId);
                        recordId = companyId;
                        $(window).trigger('open-company-details', [companyId, ((typeof route != 'undefined') ? route : '/companies/'), 'history']);
                    }
                }

Was something being appended to the form being built in formit.js. Are you saying that this is being used to display data when the user first accesses the form?
That code is passed into the FormIt class as part of the config object, but it's used for when the form is submitted (i.e. the Save button is clicked).
When you call formiit.show(config), the FormIt class goes through several methods - it's builds the HTML, it creates the fields, and then, it conditionally tries to load data into the form. The condition it checks to decide whether to load data in is to see if the config object passed in has a property called loadDataFromUrl - if it does then FormIt will make a request to that URL to retrieve some data, and then use that data to populate the fields on the form.
Alright, Chris, here's my plan:

I understand what you're talking about, as far as having to craft things in a way that accommodates the asynchronous dynamic, so here's what I want to try:

this.displayActivityForm = function (companyId, proposalId, type, activityId) {
   console.log(activityId);
   /*
   $.get('/companies/activities/:activityId', function (resp) {
      if (resp.error) {
         CAMS.alert('Error', resp.msg, 'error');
         return false;
      }
      WHAT DO I PUT HERE TO FUNNEL THE RESULTS TO MY FORMIT DYNAMIC BELOW?
      /*
      =========================================================
      put my formit dynamics here in the aftermath of a successful promise
      =========================================================
      */
      
      var model = objectModels[type],

      fc = model.singular.substring(0, 1),
      config = {
         title: 'Add a' + ((fc == 'a' || fc == 'e' || fc == 'i' || fc == 'o' || fc == 'u') ? 'n' : '') + ' ' + ucwords(model.singular),
         directionsText: 'Make your changes below and then click, "SAVE."',
         fields: model.fields,
         onShow: function (self) {
            // add in the additional events and plugins
            // add in datetime support
            self.$el.find('input.field-datetime').datepicker({
               autoClose: true,
               language: 'en',
               timepicker: true,
               dateFormat: 'mm/dd/yyyy',
               timeFormat: 'h:ii AA',
               showEvent: 'focus',
               minutesStep: 5
            });
            //RIGHT HERE IS WHERE MY "STUFF" HAS TO GO
            self.$el.find('#formit-notes').val("hello");
            self.$el.find('#formit-date').val("04/04/2020");
            self.$el.find('.form-control displayType').val("Call Note");
         

         },
         ajax: {
            path: '/companies/edit-activity',
            params: {
               company: companyId,
               proposal: proposalId,
               type: type,
            },
            onComplete: function (resp, self) {
               if (resp.error) {
                  self.addMsg(resp.msg);
                  return false;
               }
               companyId = (companyId == 'bulk' ? resp.data.id : companyId);
               recordId = companyId;
               $(window).trigger('open-company-details', [companyId, ((typeof route != 'undefined') ? route : '/companies/'), 'history']);
            }
         }
      };

      // show the form
      formIt.show(config);
               
      */
      =========================================================
      here's what happens if the route / info goes south
      =========================================================
      */

      $this.parents('.card').remove();
   }, 'json').fail(function () {
      CAMS.alert('Unexpected Error', 'We encountered an unexpected error while trying to process your request.', 'error');
   });

 };


Open in new window

So, my route is going to be this (and I'm just following my nose, here. I grabbed this from another part of the app. I know what I have in bold has to change...:

getOne(activityId) {
        return new Promise((resolve, reject) => {
            let activity_Id = this._getId(activityId); //this is on the "service.js" file. It's just cleaning up and clarifying the id type
            this.model.findOne({ _id: activity_Id }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                resolve(res.brokers[index]); //what do I need here?
            });
        });
    }

And here's the actual query as it exists in the "Activity" model...

const { ObjectId } = require('mongodb');
const { Util } = require('node-utils');
const moment = require('moment-timezone');
const Service = require('./service');

const mongoose = require('mongoose');
const ProposalSchema = require('../schemas/ProposalSchema');
const CompanySchema = require('../schemas/CompanySchema');
const UserSchema = require('../schemas/UserSchema');
const ActivitySchema = require('../schemas/ActivitySchema');

class Activity extends Service {

    constructor() {
        super();

        this.collection = 'activities';
        this.plural = 'activities';
        this.singular = 'activity';
        this.model = mongoose.model('Activity', ActivitySchema);        
        //this.fields = require('../lib/model-proposal');
    }  
   
      getOne(activityId) {
        return new Promise((resolve, reject) => {
            let activity_Id = this._getId(activityId);
            this.model.findOne({ _id: activity_Id }, (err, res) => {
                if (err) { console.log(err); reject(err); }
                resolve(res.brokers[index]);
            });
        });
    }
}

module.exports = new Activity();

I'll be hammering away at this tomorrow, Chris. If you're up for it, I'll be checking EE to see if you had any time this weekend to look at this.

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hey ,Chris!

The only time this method will fire is with a Note or something coming from that Model. It won't fire for any other variable. I'll pop the hood on this tomorrow.

Happy Easter!
Thanks for your help, Chris!

As a courtesy, I'm going to wrap up this question. I've got another problem that you'll see at https://www.experts-exchange.com/questions/29178471/Why-does-this-query-not-work.html#questionAdd . Feel free to weigh in there if you like.

Thanks, again!