'use strict'; const ObjectId = require('mongodb').ObjectId, Job = require('../model/job'), utils = require('./utils'), env = require('../helpers/env'), { SubType } = require('../model/subscription'), { Errors, TrialTypes } = require('./constants'), { AppError, AppMembershipError, AppParamError } = require('./app_error'), assert = require('assert'), moment = require('moment'); const stripe = require('stripe')(env.STRIPE_SEC_KEY, { apiVersion: env.STRIPE_API_VERSION, appInfo: { // For sample support and debugging, not required for production: name: 'AG-NAV AgMission Stripe Intergration', version: '2.10.13', url: 'https://agmission.agnav.com' } }) function _createFilterObj(uid, fromTS, toTS) { const filterOps = { byPuid: uid, markedDelete: { $ne: true } } if (fromTS || toTS) filterOps.createdAt = {}; if (fromTS) filterOps.createdAt.$gte = new Date(fromTS * 1e3); if (toTS) filterOps.createdAt.$lte = new Date(toTS * 1e3); return filterOps; } async function calcTotalAreaByUser(uid, fromTS, toTS) { if (!uid || !ObjectId.isValid(uid)) return 0; const filterOps = _createFilterObj(uid, fromTS, toTS); const pipeline = [ { $match: filterOps }, { $group: { "_id": "null", "ttSprayAreas": { $sum: "$ttSprArea" } } }, { $project: { '_id': false, ttSprayAreas: { $round: ["$ttSprayAreas", 2] } } }]; const res = await Job.aggregate(pipeline); return res && res.length ? res[0].ttSprayAreas : 0; } async function getJobUsageByTime(byPuid, fromTS, toTS) { if (!ObjectId.isValid(byPuid)) return null; const filterOps = _createFilterObj(byPuid, fromTS, toTS); const pipeline = [ { $match: filterOps }, { $lookup: { from: 'applications', localField: '_id', foreignField: 'jobId', as: 'jobs_apps' } }, { $unwind: { path: '$jobs_apps', preserveNullAndEmptyArrays: true } }, { $group: { '_id': { '_id': '$_id', 'createdAt': '$createdAt', }, ttSprArea: { $first: "$ttSprArea" }, totalSprayed: { $sum: '$jobs_apps.totalSprayed' }, updateDate: { $max: '$jobs_apps.updateDate' } } }, // { $match: { totalSprayed: { $gt: 0 } } }, { $replaceRoot: { newRoot: { $mergeObjects: ['$$ROOT', '$_id'] } } }, { $project: { _id: false, jobId: '$_id', ttSprArea: 1, totalSprayed: { $round: ['$totalSprayed', 2] }, updateDate: 1, createdAt: 1 } } ]; const res = await Job.aggregate(pipeline); return res; } function getPkgSubfromUserInfo(userInfo) { if (!userInfo || !userInfo.membership || utils.isEmptyArray(userInfo.membership.subscriptions)) AppMembershipError.throw(); let pkgSub = userInfo.membership.subscriptions.filter(sub => sub.type === SubType.PACKAGE); if (!utils.isEmptyArray(pkgSub)) { pkgSub = pkgSub[0]; } else { AppMembershipError.throw(Errors.PKG_SUBSCRIPTION_NOT_FOUND); } return pkgSub; } function getSubMetaField(pkgSub, metaField) { return pkgSub && !utils.isEmptyArray(pkgSub.items) && (pkgSub.items[0].metadata && pkgSub.items[0].metadata[metaField]); } function validateTrial(trials, errorCode = Errors.INVALID_PARAM) { if (!trials) return; if (TrialTypes.BY_DATE === trials.type && trials.byDate) { const byDateMoment = moment.utc(trials.byDate); assert(byDateMoment.isValid(), AppError.create(Errors.INVALID_PARAM)); assert(moment.utc(byDateMoment).diff(moment.utc(), "days") > 1, AppError.create(errorCode)); } else if (TrialTypes.DAYS === trials.type && trials.trialDays > 0) { const endTrialDate = (trials.startDate ? moment.utc(trials.startDate) : moment.utc()).add(trials.trialDays, "days"); assert(endTrialDate.diff(moment.utc(), "days") > 1, AppError.create(errorCode)); } } function timeToQueryRange(byTime, fieldName) { let qRange; if (!byTime || !fieldName) return qRange; const m = byTime.match(/^(\d{1,3})(?