151 lines
5.0 KiB
JavaScript
151 lines
5.0 KiB
JavaScript
'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
|
|
} |