'use strict'; const Customer = require('../model/customer'), cache = require('../helpers/mem_cache'), ObjectId = require('mongodb').ObjectId, utils = require('../helpers/utils'), { UserTypes, TrialTypes } = require('../helpers/constants'), { AppParamError } = require('../helpers/app_error'), { validateTrial } = require('../helpers/subscription_util'), moment = require('moment'), debug = require('debug')('agm:controllers-customer'); async function getCustomers_get(req, res) { const customers = await Customer.aggregate( [ { $match: { kind: UserTypes.APP, markedDelete: { $ne: true } } }, { $lookup: { from: 'jobs', localField: '_id', foreignField: 'byPuid', as: 'cust_jobs' } }, { $unwind: { path: '$cust_jobs', preserveNullAndEmptyArrays: true } }, { $group: { '_id': { '_id': '$_id', 'name': '$name', 'contact': '$contact', 'email': '$email', 'active': '$active', 'billable': '$billable', 'premium': '$premium', 'createdAt': '$createdAt', 'username': '$username' }, 'totalJobs': { $sum: { $cond: [{ $gte: ['$cust_jobs', null] }, 1, 0] } } } }, { $replaceRoot: { newRoot: { $mergeObjects: ['$$ROOT', '$_id'] } } }, ]).allowDiskUse(true); res.json(customers); } async function createCustomer_post(req, res) { const _customer = req.body; if (!_customer || !_customer.username || !_customer.password) AppParamError.throw(); if (_customer.membership && _customer.membership.trials) { validateTrial(_customer.membership.trials); } delete _customer._id; const newCustomer = new Customer(Customer.toUser(_customer)); const theUser = await newCustomer.createOne(); res.json(theUser); } async function getCustomer_get(req, res) { const cId = req.params.customer_id; if (!ObjectId.isValid(cId)) AppParamError.throw(); const customer = await Customer.findOne({ _id: ObjectId(cId) }, null, { lean: true }).populate({ path: 'Country', select: 'code name -_id' }); res.json(customer); } async function updateCustomer_put(req, res) { const _customer = req.body; if (!_customer || !utils.isObjectId(_customer._id)) AppParamError.throw(); if (utils.isBlank(_customer.username) && !utils.isBlank(_customer.password)) _customer.password = undefined; if (!_customer.hasOwnProperty('active')) _customer.active = true; let customer = await Customer.findOne({ _id: ObjectId(_customer._id) }); if (customer) { if (!utils.isEmptyObj(_customer.membership)) { if (!utils.isEmptyObj(_customer.membership.trials)) { const custTrials = customer.membership && customer.membership.trials; const curMoment = moment.utc(); if (custTrials && custTrials.lasStartDate && custTrials.lastEndDate) { if (curMoment.isBetween(moment.utc(custTrials.lastStartDate), moment.utc(custTrials.lastEndDate))) { // Ignore updating trials if the customer is being in the middle of trial period delete _customer.membership.trials; } } // For days trial, if startDate not mentioned (and it is not in the trial period), infer and set the trial startDate from today UTC if (_customer.membership.trials.type === TrialTypes.DAYS && !_customer.membership.trials.startDate) { _customer.membership.trials.startDate = curMoment.toDate(); } validateTrial(_customer.membership.trials); } else { delete _customer.membership.trials; } // Never try to update any subscriptions, customer must follow the sub. change process or changed made in Stripe dashboard only. delete _customer.membership.subscription; } customer = await Customer.findOneAndUpdate({ _id: ObjectId(_customer._id) }, _customer, { runValidators: true, new: true, lean: true }); // Update related cached user info if the applicator premium changed // TODO: Later, may be improving this logic using hash or independant cached when needed. const uiList = cache.filterByKind(customer._id.toHexString()); let uiValue; for (let i = 0; i < uiList.length; i++) { uiValue = uiList[i]; if (uiValue) { if (customer.premium !== uiValue[1]['premium']) uiValue[1].premium = customer.premium; } } } res.json(customer); } async function deleteCustomer(req, res) { const _id = req.params.customer_id; if (!utils.isObjectId(_id)) AppParamError.throw(); const customer = await Customer.findById(ObjectId(_id)); if (customer) await customer.removeFull(); // Remove all related logged user sessions const uiList = cache.filterByKind(_id); if (uiList) { for (const u of uiList) cache.delete(u[0]); } cache.delete(_id); res.json({ message: 'deleted' }); } module.exports = { getCustomers_get, createCustomer_post, getCustomer_get, updateCustomer_put, deleteCustomer }