@lyxa.ai/core 1.4.307 → 1.4.309
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types/README.md
CHANGED
package/dist/types/package.json
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { mongoose } from '@typegoose/typegoose';
|
|
2
|
+
type ObjectIdLike = mongoose.Types.ObjectId | string;
|
|
3
|
+
export declare function getEligibleShopIdsForNewUser(userId: ObjectIdLike, shopIds: ObjectIdLike[]): Promise<string[]>;
|
|
4
|
+
export declare function isNewUserEligibleAtShop(userId: ObjectIdLike, shopId: ObjectIdLike): Promise<boolean>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEligibleShopIdsForNewUser = getEligibleShopIdsForNewUser;
|
|
4
|
+
exports.isNewUserEligibleAtShop = isNewUserEligibleAtShop;
|
|
5
|
+
const models_1 = require("../libraries/mongo/models");
|
|
6
|
+
const enum_1 = require("./enum");
|
|
7
|
+
async function getDeviceLinkedUserIds(userId) {
|
|
8
|
+
const user = await models_1.UserModel.findById(userId);
|
|
9
|
+
if (!user)
|
|
10
|
+
return null;
|
|
11
|
+
const userIds = [user._id.toString()];
|
|
12
|
+
if (user.deviceId) {
|
|
13
|
+
const userModelWithDeleted = models_1.UserModel;
|
|
14
|
+
const sameDeviceUsers = await userModelWithDeleted.findWithDeleted({
|
|
15
|
+
deviceId: user.deviceId,
|
|
16
|
+
});
|
|
17
|
+
sameDeviceUsers.forEach(sameDeviceUser => {
|
|
18
|
+
const sameDeviceUserId = sameDeviceUser._id.toString();
|
|
19
|
+
if (!userIds.includes(sameDeviceUserId))
|
|
20
|
+
userIds.push(sameDeviceUserId);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return userIds;
|
|
24
|
+
}
|
|
25
|
+
async function getEligibleShopIdsForNewUser(userId, shopIds) {
|
|
26
|
+
const shopIdStrings = shopIds.map(shopId => shopId.toString());
|
|
27
|
+
const userIds = await getDeviceLinkedUserIds(userId);
|
|
28
|
+
if (!userIds)
|
|
29
|
+
return shopIdStrings;
|
|
30
|
+
const disqualifyingOrders = await models_1.RegularOrderModel.find({
|
|
31
|
+
user: { $in: userIds },
|
|
32
|
+
shop: { $in: shopIds },
|
|
33
|
+
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
34
|
+
}, { shop: 1 }).lean();
|
|
35
|
+
const disqualifiedShopIds = new Set(disqualifyingOrders.map(order => String(order.shop)));
|
|
36
|
+
return shopIdStrings.filter(shopId => !disqualifiedShopIds.has(shopId));
|
|
37
|
+
}
|
|
38
|
+
async function isNewUserEligibleAtShop(userId, shopId) {
|
|
39
|
+
return (await getEligibleShopIdsForNewUser(userId, [shopId])).length > 0;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=new-user-eligibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-user-eligibility.js","sourceRoot":"/","sources":["utilities/new-user-eligibility.ts"],"names":[],"mappings":";;AA4CA,oEAqBC;AAMD,0DAEC;AAxED,sDAA+E;AAE/E,iCAA4C;AAW5C,KAAK,UAAU,sBAAsB,CAAC,MAAoB;IACzD,MAAM,IAAI,GAAG,MAAM,kBAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEtC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,oBAAoB,GAAG,kBAAqD,CAAC;QACnF,MAAM,eAAe,GAAyB,MAAM,oBAAoB,CAAC,eAAe,CAAC;YACxF,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACvB,CAAC,CAAC;QACH,eAAe,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE;YACxC,MAAM,gBAAgB,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACvD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC;AAYM,KAAK,UAAU,4BAA4B,CACjD,MAAoB,EACpB,OAAuB;IAEvB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE/D,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,aAAa,CAAC;IAEnC,MAAM,mBAAmB,GAAG,MAAM,0BAAiB,CAAC,IAAI,CACvD;QACC,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;QACtB,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;QACtB,MAAM,EAAE,EAAE,GAAG,EAAE,yBAAkB,CAAC,SAAS,EAAE;KAC7C,EACD,EAAE,IAAI,EAAE,CAAC,EAAE,CACX,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE1F,OAAO,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACzE,CAAC;AAMM,KAAK,UAAU,uBAAuB,CAAC,MAAoB,EAAE,MAAoB;IACvF,OAAO,CAAC,MAAM,4BAA4B,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC1E,CAAC","sourcesContent":["import { DocumentType, mongoose } from '@typegoose/typegoose';\nimport { RegularOrderModel, User, UserModel } from '../libraries/mongo/models';\nimport { SoftDeleteModel } from '../libraries/mongo/plugins/soft-delete-plugin';\nimport { RegularOrderStatus } from './enum';\n\ntype ObjectIdLike = mongoose.Types.ObjectId | string;\n\n/**\n * Expands a user into the set of account ids that count as \"the same person\"\n * for New User Discount purposes: the account itself plus every account that\n * shares its `deviceId` (soft-deleted linked accounts included, so eligibility\n * cannot be reset by deleting an account). Returns `null` when the user does\n * not exist so callers can decide their own fail-open behaviour.\n */\nasync function getDeviceLinkedUserIds(userId: ObjectIdLike): Promise<string[] | null> {\n\tconst user = await UserModel.findById(userId);\n\tif (!user) return null;\n\n\tconst userIds = [user._id.toString()];\n\n\tif (user.deviceId) {\n\t\tconst userModelWithDeleted = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tconst sameDeviceUsers: DocumentType<User>[] = await userModelWithDeleted.findWithDeleted({\n\t\t\tdeviceId: user.deviceId,\n\t\t});\n\t\tsameDeviceUsers.forEach(sameDeviceUser => {\n\t\t\tconst sameDeviceUserId = sameDeviceUser._id.toString();\n\t\t\tif (!userIds.includes(sameDeviceUserId)) userIds.push(sameDeviceUserId);\n\t\t});\n\t}\n\n\treturn userIds;\n}\n\n/**\n * Filters a list of candidate shops down to the ones a user is still eligible\n * for a New User Discount at, using a single order lookup for the whole batch.\n *\n * Eligibility is evaluated across every account that shares the user's\n * `deviceId` (soft-deleted linked accounts included). A candidate shop is\n * dropped as soon as any of those accounts has a non-cancelled `RegularOrder`\n * there. Returned ids preserve the input order. If the user does not exist,\n * every candidate shop is returned (fail open to eligible).\n */\nexport async function getEligibleShopIdsForNewUser(\n\tuserId: ObjectIdLike,\n\tshopIds: ObjectIdLike[],\n): Promise<string[]> {\n\tconst shopIdStrings = shopIds.map(shopId => shopId.toString());\n\n\tconst userIds = await getDeviceLinkedUserIds(userId);\n\tif (!userIds) return shopIdStrings;\n\n\tconst disqualifyingOrders = await RegularOrderModel.find(\n\t\t{\n\t\t\tuser: { $in: userIds },\n\t\t\tshop: { $in: shopIds },\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t},\n\t\t{ shop: 1 },\n\t).lean();\n\n\tconst disqualifiedShopIds = new Set(disqualifyingOrders.map(order => String(order.shop)));\n\n\treturn shopIdStrings.filter(shopId => !disqualifiedShopIds.has(shopId));\n}\n\n/**\n * Determines whether a user is eligible for a shop's New User Discount. Thin\n * single-shop wrapper over {@link getEligibleShopIdsForNewUser}.\n */\nexport async function isNewUserEligibleAtShop(userId: ObjectIdLike, shopId: ObjectIdLike): Promise<boolean> {\n\treturn (await getEligibleShopIdsForNewUser(userId, [shopId])).length > 0;\n}\n"]}
|