agmission/Development/server/controllers/customer.js

182 lines
5.8 KiB
JavaScript

'use strict';
const { User } = require('../model');
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', // Reference the Job collection
localField: '_id',
foreignField: 'byPuid',
as: 'cust_jobs'
}
},
{ $unwind: { path: '$cust_jobs', preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: 'partners', // Reference the Partner collection
localField: 'partner',
foreignField: '_id',
as: 'partner_info',
},
},
{
$group: {
'_id': {
_id: '$_id',
name: '$name',
contact: '$contact',
email: '$email',
active: '$active',
billable: '$billable',
premium: '$premium',
createdAt: '$createdAt',
username: '$username',
partner: {
$arrayElemAt: [
{
$map: {
input: '$partner_info',
as: 'partner',
in: {
_id: '$$partner._id',
name: '$$partner.name',
active: '$$partner.active',
},
},
},
0,
],
}, // Include only _id, name, and active fields for partner
selfSignup: '$selfSignup'
},
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' })
.populate({ path: 'partner', select: 'name description' });
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;
}
// Note: 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
}