37980-vm/backend/src/services/analytics.js
2026-01-31 16:42:33 +00:00

78 lines
2.7 KiB
JavaScript

const db = require('../db/models');
const Sequelize = db.Sequelize;
const Op = Sequelize.Op;
module.exports = class AnalyticsService {
static async recordView(data, req) {
return await db.page_views.create({
productId: data.productId || null,
categoryId: data.categoryId || null,
userId: req.user ? req.user.id : null,
ipAddress: req.ip,
userAgent: req.headers['user-agent']
});
}
static async getTopProducts(limit = 5) {
// Use a simpler query to avoid complex group by issues with nested includes
const topViewedIds = await db.page_views.findAll({
attributes: [
'productId',
[Sequelize.fn('COUNT', Sequelize.col('productId')), 'viewCount']
],
where: {
productId: { [Op.ne]: null }
},
group: ['productId'],
order: [[Sequelize.literal('"viewCount"'), 'DESC']],
limit: Number(limit),
raw: true
});
if (topViewedIds.length === 0) return [];
const productIds = topViewedIds.map(v => v.productId);
const products = await db.products.findAll({
where: { id: { [Op.in]: productIds } },
include: [{ model: db.file, as: 'images' }]
});
// Map counts back to products
return products.map(p => {
const viewData = topViewedIds.find(v => v.productId === p.id);
return {
...p.get({ plain: true }),
viewCount: viewData ? parseInt(viewData.viewCount) : 0
};
}).sort((a, b) => b.viewCount - a.viewCount);
}
static async getViewStats() {
const totalViews = await db.page_views.count();
const productViews = await db.page_views.count({ where: { productId: { [Op.ne]: null } } });
const categoryViews = await db.page_views.count({ where: { categoryId: { [Op.ne]: null } } });
// Last 7 days views
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const dailyViews = await db.page_views.findAll({
attributes: [
[Sequelize.fn('DATE', Sequelize.col('createdAt')), 'date'],
[Sequelize.fn('COUNT', Sequelize.col('id')), 'count']
],
where: {
createdAt: { [Op.gte]: sevenDaysAgo }
},
group: [Sequelize.fn('DATE', Sequelize.col('createdAt'))],
order: [[Sequelize.fn('DATE', Sequelize.col('createdAt')), 'ASC']]
});
return {
totalViews,
productViews,
categoryViews,
dailyViews
};
}
};