From b6fcc46bde300d0e4aa870839d653dadfea4df8a Mon Sep 17 00:00:00 2001
From: Louis Capitanchik <contact@louiscap.co>
Date: Tue, 20 Apr 2021 22:54:34 +0100
Subject: [PATCH] Store analytics in database

---
 .../20210000000000-create-analytics-table.js  | 21 ++-----
 src/http/controllers/api/analytics.js         | 58 +++++++++++++++++++
 src/http/routes.js                            |  7 +--
 3 files changed, 64 insertions(+), 22 deletions(-)
 create mode 100644 src/http/controllers/api/analytics.js

diff --git a/database/migrations/20210000000000-create-analytics-table.js b/database/migrations/20210000000000-create-analytics-table.js
index cf5b5a1..05336c7 100644
--- a/database/migrations/20210000000000-create-analytics-table.js
+++ b/database/migrations/20210000000000-create-analytics-table.js
@@ -14,7 +14,11 @@ module.exports = {
 						type: Types.UUID,
 						allowNull: true,
 					},
-					type: {
+					action: {
+						type: Types.TEXT,
+						allowNull: false,
+					},
+					event: {
 						type: Types.TEXT,
 						allowNull: false,
 					},
@@ -58,21 +62,6 @@ module.exports = {
 				},
 				{ transaction: t },
 			)
-			// await migration.addColumn(
-			// 	'analytics',
-			// 	'parent_id',
-			// 	{
-			// 		type: Types.UUID,
-			// 		allowNull: true,
-			// 		references: {
-			// 			model: 'analytics',
-			// 			key: 'id',
-			// 		},
-			// 		onDelete: 'CASCADE',
-			// 		onUpdate: 'CASCADE',
-			// 	},
-			// 	{ transaction: t },
-			// )
 			await migration.sequelize.query(
 				'CREATE INDEX analytics_session_id_idx ON analytics(session_id)',
 				{ transaction: t },
diff --git a/src/http/controllers/api/analytics.js b/src/http/controllers/api/analytics.js
new file mode 100644
index 0000000..e1b500d
--- /dev/null
+++ b/src/http/controllers/api/analytics.js
@@ -0,0 +1,58 @@
+const { sequelize } = require('database/models')
+const { QueryTypes } = require('sequelize')
+const moment = require('moment')
+const { v4: uuid } = require('uuid')
+
+exports.track = async ctx => {
+	const { events } = ctx.request.body
+	const device = ctx.request.device
+
+	const results = await ctx.profile('user.event', 'Track app event', () =>
+		sequelize.transaction(async t => {
+			let succ = 0
+			for (const event of events) {
+				const {
+					session,
+					action,
+					event: eventType,
+					timestamp,
+					start_time,
+					end_time,
+					data,
+					properties,
+				} = event
+
+				const replacements = {
+					id: uuid(),
+					session,
+					action,
+					event: eventType,
+					start_time: timestamp
+						? moment(timestamp).toISOString()
+						: start_time ?? null,
+					end_time: end_time ?? null,
+					properties: JSON.stringify(properties ?? data ?? {}),
+					location: null,
+					device: device ? JSON.stringify(device) : null,
+				}
+
+				const [_, idx] = await sequelize.query(
+					`INSERT INTO 
+					analytics (id, session_id, action, event, start_time, end_time, parent_id, properties, location, device) 
+				VALUES 
+				   (:id, :session, :action, :event, :start_time, :end_time, null, :properties, :location, :device)`,
+					{
+						replacements,
+						type: QueryTypes.INSERT,
+						transaction: t,
+					},
+				)
+
+				succ += idx
+			}
+			return succ
+		}),
+	)
+
+	ctx.status = results === events.length ? 201 : 500
+}
diff --git a/src/http/routes.js b/src/http/routes.js
index de30add..648d4c5 100644
--- a/src/http/routes.js
+++ b/src/http/routes.js
@@ -151,12 +151,7 @@ function mount(api) {
 	api.put('/self/:property', controller('api/user', 'updateOne'))
 
 	api.post('/an/id', async ctx => {})
-	api.post('/an/ev', async ctx => {
-		console.log(ctx.request.body)
-		ctx.body = {
-			foo: true,
-		}
-	})
+	api.post('/an/ev', controller('api/analytics', 'track'))
 
 	api.post('/feedback', controller('api/feedback', 'send'))
 }
-- 
GitLab