Skip to content
Snippets Groups Projects
content.js 3.10 KiB
const HttpError = require('core/errors/HttpError')
const { Sequelize, sequelize, Metric } = require('database/models')
const { Op } = Sequelize
const moment = require('moment')

exports.postMetric = async ctx => {
	const allowedTypes = new Set(Metric.getSupportedMetricTypes())
	const { value, type, location, meta, batch } = ctx.request.body

	let metric
	let metrics

	if (batch) {
		metrics = []
		try {
			await sequelize.transaction(async t => {
				for (const m of batch) {
					const result = await save(m.value, m.type, m.location, m.meta, {
						allowedTypes,
						transaction: t,
						ctx,
					})

					metrics.push(result)
				}
			})
		} catch (e) {
			console.log(e)

			throw new HttpError({
				status: 400,
				code: 'MTR-001',
				title: 'Failed to save metric',
				description: 'Something went wrong trying to save the metric',
			})
		}

		ctx.body = {
			metrics: metrics.map(metric => metric.toJSON()),
		}
	} else {
		metric = await save(value, type, location, meta, { allowedTypes, ctx })
		ctx.body = { metric: metric.toJSON() }
	}
}

const save = async (
	value,
	type,
	location,
	meta,
	{ allowedTypes, transaction, ctx },
) => {
	if (
		location == null ||
		location.longitude == null ||
		location.latitude == null
	) {
		throw new HttpError({
			status: 400,
			code: 'MTR-001',
			title: 'Invalid Metric',
			description: 'A location must be provided for metrics',
		})
	}

	if (allowedTypes.has(type)) {
		return await ctx.services['data.metrics'].recordMetric(
			value,
			type,
			location,
			meta,
			transaction,
		)
	} else {
		throw new HttpError({
			status: 400,
			code: 'MTR-002',
			title: 'Invalid Metric',
			description: `${type} is not a supported type`,
		})
	}
}

function splitString(str) {
	return str
		.split(',')
		.map(s => s.trim())
		.filter(Boolean)
}

function pointFromString(str) {
	const parts = splitString(str).map(Number)

	return {
		latitude: parts[0],
		longitude: parts[1],
	}
}

exports.getWithin = async ctx => {
	const {
		point_from,
		point_to,
		date_from,
		date_to = moment.utc(),
		types = '',
		format = 'full',
	} = ctx.request.query

	const fromPoint = pointFromString(point_from)
	const toPoint = pointFromString(point_to)

	const fromDate = moment.utc(date_from)
	const toDate = moment.utc(date_to)

	const metricTypes = splitString(types)

	const minFromLong = Math.min(fromPoint.longitude, toPoint.longitude)
	const maxFromLong = Math.max(fromPoint.longitude, toPoint.longitude)
	const minFromLat = Math.min(fromPoint.latitude, toPoint.latitude)
	const maxFromLat = Math.max(fromPoint.latitude, toPoint.latitude)

	const pointBuffer = [
		[minFromLong, minFromLat],
		[minFromLong, maxFromLat],
		[maxFromLong, maxFromLat],
		[maxFromLong, minFromLat],
		[minFromLong, minFromLat],
	]
		.map(pb => pb.map(Number).join(' '))
		.join(',')

	const query =
		format === 'marker'
			? ctx.services['data.metrics'].queryAggregate
			: ctx.services['data.metrics'].queryAll

	const metrics = await query(
		pointBuffer,
		metricTypes,
		// fromDate.toISOString(),
		moment().subtract(12, 'months').toISOString(),
		toDate.toISOString(),
	)


	console.log(metrics)
	ctx.body = { metrics }
}