Skip to content

Commit e2958c6

Browse files
authored
Merge pull request #2292 from useautumn/charlie/fix-license-products-build
fix(licenses): resolve versioned license products
2 parents 73088e8 + c121c01 commit e2958c6

3 files changed

Lines changed: 78 additions & 0 deletions

File tree

server/src/internal/licenses/repos/planLicenseRepo.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,30 @@ const listCatalogByOrgEnv = async ({
178178
return rows.map(({ row }) => row);
179179
};
180180

181+
const listProductsByInternalIds = async ({
182+
db,
183+
orgId,
184+
env,
185+
internalProductIds,
186+
}: {
187+
db: DrizzleCli;
188+
orgId: string;
189+
env: AppEnv;
190+
internalProductIds: string[];
191+
}) => {
192+
if (internalProductIds.length === 0) return [];
193+
return await db
194+
.select({ id: products.id })
195+
.from(products)
196+
.where(
197+
and(
198+
eq(products.org_id, orgId),
199+
eq(products.env, env),
200+
inArray(products.internal_id, internalProductIds),
201+
),
202+
);
203+
};
204+
181205
const insertMany = async ({
182206
db,
183207
rows,
@@ -201,6 +225,7 @@ export const planLicenseRepo = {
201225
listCatalogByLicenseInternalProductIds,
202226
listWithLicensePlanIdByParents,
203227
listCatalogByOrgEnv,
228+
listProductsByInternalIds,
204229
insertMany,
205230
deleteByIds,
206231
} as const;

server/src/internal/products/internalHandlers/handleGetProducts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export const handleGetLicenseProducts = createRoute({
117117
// so versioned license plans still match the latest-version list below.
118118
const linkedProducts = await planLicenseRepo.listProductsByInternalIds({
119119
db,
120+
orgId: org.id,
121+
env,
120122
internalProductIds: linkedInternalIds,
121123
});
122124
const linkedExternalIds = new Set(
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* A parent pinned to an older license version must still expose the latest license in the catalog.
3+
*/
4+
import { expect, test } from "bun:test";
5+
import type { ProductV2 } from "@autumn/shared";
6+
import { items } from "@tests/utils/fixtures/items.js";
7+
import { itemsV2 } from "@tests/utils/fixtures/itemsV2.js";
8+
import { products } from "@tests/utils/fixtures/products.js";
9+
import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js";
10+
import chalk from "chalk";
11+
12+
test.concurrent(
13+
`${chalk.yellowBright("licenses: catalog includes latest license when parent remains pinned to v1")}`,
14+
async () => {
15+
const parent = products.base({
16+
id: "versioned-license-catalog-parent",
17+
items: [items.dashboard()],
18+
});
19+
const license = products.base({
20+
id: "versioned-license-catalog-seat",
21+
items: [items.monthlyMessages({ includedUsage: 25 })],
22+
});
23+
const { autumnV2_2 } = await initScenario({
24+
customerId: "versioned-license-catalog",
25+
setup: [
26+
s.customer({ testClock: false }),
27+
s.products({ list: [parent, license] }),
28+
],
29+
actions: [
30+
s.licenses.link({
31+
parentProductId: parent.id,
32+
licenseProductId: license.id,
33+
included: 0,
34+
}),
35+
],
36+
});
37+
38+
await autumnV2_2.post("/plans.update", {
39+
plan_id: license.id,
40+
force_version: true,
41+
items: [itemsV2.monthlyMessages({ included: 50 })],
42+
});
43+
44+
const { products: licenseProducts } = (await autumnV2_2.get(
45+
"/products/license_products",
46+
)) as { products: ProductV2[] };
47+
expect(licenseProducts).toContainEqual(
48+
expect.objectContaining({ id: license.id, version: 2 }),
49+
);
50+
},
51+
);

0 commit comments

Comments
 (0)