diff --git a/server/src/_luaScripts/deductionLuaScripts/batchDeduction.lua b/server/src/_luaScripts/deductionLuaScripts/batchDeduction.lua index 4874d7bf3..be7ff10ad 100644 --- a/server/src/_luaScripts/deductionLuaScripts/batchDeduction.lua +++ b/server/src/_luaScripts/deductionLuaScripts/batchDeduction.lua @@ -998,6 +998,9 @@ local function processRequest(request, loadedCusFeatures, entityFeatureStates) remainingAmount = result.remaining else -- Unlimited feature covers everything + -- Mark as "changed" so balance gets returned + customerChanged = true + changedCustomerFeatureIds[cusFeature.id] = true remainingAmount = 0 end else @@ -1026,6 +1029,13 @@ local function processRequest(request, loadedCusFeatures, entityFeatureStates) remainingAmount = result.remaining else + -- Unlimited entity feature covers everything + -- Mark as "changed" so balance gets returned + changedEntityIds[entityId] = true + if not changedEntityFeatureIds[entityId] then + changedEntityFeatureIds[entityId] = {} + end + changedEntityFeatureIds[entityId][entityFeature.id] = true remainingAmount = 0 end end @@ -1061,6 +1071,13 @@ local function processRequest(request, loadedCusFeatures, entityFeatureStates) totalDeducted = totalDeducted + (amount - result.remaining) remainingAmount = result.remaining else + -- Unlimited entity feature covers everything + -- Mark as "changed" so balance gets returned + changedEntityIds[entId] = true + if not changedEntityFeatureIds[entId] then + changedEntityFeatureIds[entId] = {} + end + changedEntityFeatureIds[entId][entityFeature.id] = true remainingAmount = 0 break end @@ -1118,6 +1135,9 @@ local function processRequest(request, loadedCusFeatures, entityFeatureStates) end else -- Unlimited credit system covers everything + -- Mark as "changed" so balance gets returned + customerChanged = true + changedCustomerFeatureIds[otherCusFeature.id] = true remainingAmount = 0 end break diff --git a/server/tests/_temp/temp1.test.ts b/server/tests/_temp/temp1.test.ts index 860c33ceb..1419305f1 100644 --- a/server/tests/_temp/temp1.test.ts +++ b/server/tests/_temp/temp1.test.ts @@ -15,13 +15,18 @@ const pro = constructProduct({ isDefault: true, items: [ + // constructFeatureItem({ + // featureId: TestFeature.Action1, + // includedUsage: 5, + // }), constructFeatureItem({ - featureId: TestFeature.Workflows, - includedUsage: 5, + featureId: TestFeature.Credits, + // includedUsage: 200, + unlimited: true, }), constructFeatureItem({ - featureId: TestFeature.Messages, - includedUsage: 200, + featureId: TestFeature.Words, + unlimited: true, }), ], }); diff --git a/server/tests/balances/check/send-event/send-event3.test.ts b/server/tests/balances/check/send-event/send-event3.test.ts index 733eb76e9..c0087c38e 100644 --- a/server/tests/balances/check/send-event/send-event3.test.ts +++ b/server/tests/balances/check/send-event/send-event3.test.ts @@ -83,6 +83,7 @@ describe(`${chalk.yellowBright("send-event3: Testing check with track, credit sy granted_balance: 10, }); }); + return; test("should check with track and deduct from action1 first, then credits", async () => { const checkRes = (await autumnV2.check({ diff --git a/server/tests/balances/check/send-event/send-event4.test.ts b/server/tests/balances/check/send-event/send-event4.test.ts new file mode 100644 index 000000000..42f881231 --- /dev/null +++ b/server/tests/balances/check/send-event/send-event4.test.ts @@ -0,0 +1,104 @@ +import { beforeAll, describe, expect, test } from "bun:test"; +import { ApiVersion } from "@autumn/shared"; +import { TestFeature } from "@tests/setup/v2Features.js"; +import ctx from "@tests/utils/testInitUtils/createTestContext.js"; +import chalk from "chalk"; +import { AutumnInt } from "@/external/autumn/autumnCli.js"; +import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js"; +import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js"; +import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js"; +import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js"; +import { getCreditCost } from "../../../../src/internal/features/creditSystemUtils"; + +// UNCOMMENT FROM HERE +const pro = constructProduct({ + type: "free", + isDefault: true, + + items: [ + constructFeatureItem({ + featureId: TestFeature.Credits, + unlimited: true, + }), + constructFeatureItem({ + featureId: TestFeature.Messages, + unlimited: true, + }), + ], +}); + +describe(`${chalk.yellowBright("send-event4: Testing check with track, unlimited feature")}`, () => { + const customerId = "send-event4"; + const autumnV2: AutumnInt = new AutumnInt({ version: ApiVersion.V2_0 }); + const autumnV1: AutumnInt = new AutumnInt({ version: ApiVersion.V1_2 }); + beforeAll(async () => { + await initCustomerV3({ + ctx, + customerId, + customerData: {}, + attachPm: "success", + withTestClock: true, + }); + + await initProductsV0({ + ctx, + products: [pro], + prefix: customerId, + }); + + await autumnV2.attach({ + customer_id: customerId, + product_id: pro.id, + }); + }); + + test("should check with track messages and have correct response", async () => { + const checkRes = await autumnV2.check({ + customer_id: customerId, + feature_id: TestFeature.Messages, + required_balance: 1000, + send_event: true, + }); + + expect(checkRes).toMatchObject({ + allowed: true, + customer_id: customerId, + required_balance: 1000, + }); + + expect(checkRes.balance).toMatchObject({ + feature_id: TestFeature.Messages, + current_balance: 0, + usage: 0, + granted_balance: 0, + }); + }); + + test("should check with track action1 and have correct response", async () => { + const checkRes = await autumnV2.check({ + customer_id: customerId, + feature_id: TestFeature.Action1, + required_balance: 1000, + send_event: true, + }); + + const requiredBalance = getCreditCost({ + featureId: TestFeature.Action1, + creditSystem: ctx.features.find((f) => f.id === TestFeature.Credits)!, + amount: 1000, + }); + + expect(checkRes).toMatchObject({ + allowed: true, + customer_id: customerId, + required_balance: requiredBalance, + }); + + expect(checkRes.balance).toMatchObject({ + feature_id: TestFeature.Credits, + current_balance: 0, + usage: 0, + granted_balance: 0, + }); + }); +}); diff --git a/server/tests/balances/track/basic/track-basic7.test.ts b/server/tests/balances/track/basic/track-basic7.test.ts index 20a1b0c8b..27810cb2c 100644 --- a/server/tests/balances/track/basic/track-basic7.test.ts +++ b/server/tests/balances/track/basic/track-basic7.test.ts @@ -1,8 +1,8 @@ import { beforeAll, describe, expect, test } from "bun:test"; import { ApiVersion, type TrackResponseV2 } from "@autumn/shared"; -import chalk from "chalk"; import { TestFeature } from "@tests/setup/v2Features.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; +import chalk from "chalk"; import { AutumnInt } from "@/external/autumn/autumnCli.js"; import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js"; import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js"; @@ -60,7 +60,13 @@ describe(`${chalk.yellowBright("track-basic7: track with unlimited balance")}`, feature_id: TestFeature.Messages, }); - expect(trackRes.balance).toBeNull(); + expect(trackRes.balance).toMatchObject({ + feature_id: TestFeature.Messages, + unlimited: true, + current_balance: 0, + usage: 0, + granted_balance: 0, + }); expect(trackRes.value).toBe(1); const customer = await autumnV1.customers.get(customerId);