Skip to content

Commit

Permalink
feat(frequently-bought-together): compatibility patch
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdbrug committed Dec 3, 2024
1 parent 70c2e80 commit 5012fdb
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 0.0.2 (2024-12-03)

- Patched compatibility range to >= 2.2.0

# 0.0.1 (2024-12-02)

- Initial plugin setup
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pinelab/vendure-plugin-frequently-bought-together",
"version": "0.0.1",
"version": "0.0.2",
"description": "Increase average order value by suggesting frequently bought together products based on past orders. Also known as related products or product recommendations.",
"keywords": [
"frequently bought together",
Expand Down
50 changes: 50 additions & 0 deletions packages/vendure-plugin-frequently-bought-together/src/fpgrowth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { INestApplication } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { ID, OrderLine } from '@vendure/core';
import { FPGrowth, Itemset } from 'node-fpgrowth';

export async function getFrequentlyBoughtTogetherItemSets(
app: INestApplication
): Promise<void> {
const dataSource = app.get(DataSource);
const repository = await dataSource.getRepository(OrderLine);

const ordersSince = new Date();
ordersSince.setFullYear(ordersSince.getFullYear() - 5);
const channelId = 1;
const languageCode = 'nl';

const result = await repository
.createQueryBuilder('orderLine')
.innerJoinAndSelect('orderLine.productVariant', 'productVariant')
.innerJoinAndSelect('productVariant.translations', 'pvTranslations')
.innerJoin('orderLine.order', 'order')
.innerJoin('order.channels', 'channel')
.where('order.orderPlacedAt >= :ordersSince', { ordersSince })
.andWhere('channel.id = :channelId', { channelId })
.andWhere('productVariant.deletedAt IS NULL')
.andWhere('pvTranslations.languageCode = :languageCode', { languageCode })
.select(['orderLine.*', 'productVariant.id', 'pvTranslations.name'])
.getRawMany();

const identifyingField = 'pvTranslations_name'; // Use productVariant_id for production

const transactions = new Map<ID, string[]>();
result.forEach((orderLine) => {
const transactionsForOrder = transactions.get(orderLine.orderId) || [];
transactionsForOrder.push(orderLine[identifyingField]);
transactions.set(orderLine.orderId, transactionsForOrder);
});
const matrix = Array.from(transactions.values());
console.log('calculating frequent itemsets');
const fpgrowth = new FPGrowth<string>(0.001);
const itemSets = (await fpgrowth.exec(matrix))
// Only combinations allowed
.filter((is) => is.items.length > 1)
// Lowest support first, because if they make sense, the higher ones will too
.sort((a, b) => a.support - b.support)
.reverse();

console.log('frequent itemsets:', itemSets);
console.log('Total item sets', itemSets.length);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { PluginInitOptions } from './types';
});
return config;
},
compatibility: '>=2.3.0',
compatibility: '>=2.2.0',
// adminApiExtensions: {
// schema: adminApiExtensions,
// resolvers: [FrequentlyBoughtTogetherAdminResolver],
Expand Down

0 comments on commit 5012fdb

Please sign in to comment.