@timardex/cluemart-server-shared 1.0.284 → 1.0.289
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/{chunk-4FWW5CDC.mjs → chunk-KRG2CATM.mjs} +64 -32
- package/dist/chunk-KRG2CATM.mjs.map +1 -0
- package/dist/index.cjs +360 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.mjs +351 -116
- package/dist/index.mjs.map +1 -1
- package/dist/mongoose/index.cjs +61 -31
- package/dist/mongoose/index.cjs.map +1 -1
- package/dist/mongoose/index.mjs +1 -1
- package/dist/service/index.cjs +358 -120
- package/dist/service/index.cjs.map +1 -1
- package/dist/service/index.d.mts +40 -2
- package/dist/service/index.d.ts +40 -2
- package/dist/service/index.mjs +285 -78
- package/dist/service/index.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-4FWW5CDC.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -64,6 +64,7 @@ __export(index_exports, {
|
|
|
64
64
|
VerificationTokenModel: () => VerificationTokenModel,
|
|
65
65
|
activeAffiliateCodeExists: () => activeAffiliateCodeExists,
|
|
66
66
|
associatesSchema: () => associatesSchema,
|
|
67
|
+
awardAffiliateVendorSubscriptionRewards: () => awardAffiliateVendorSubscriptionRewards,
|
|
67
68
|
baseResourceFields: () => baseResourceFields,
|
|
68
69
|
connectToDatabase: () => connectToDatabase,
|
|
69
70
|
convertObjectIdsToStrings: () => convertObjectIdsToStrings,
|
|
@@ -73,9 +74,11 @@ __export(index_exports, {
|
|
|
73
74
|
express: () => import_express.default,
|
|
74
75
|
findAffiliateByPromoCode: () => findAffiliateByPromoCode,
|
|
75
76
|
findEventOrImportedMarketById: () => findEventOrImportedMarketById,
|
|
77
|
+
getSubscriptionRewardPeriodBounds: () => getSubscriptionRewardPeriodBounds,
|
|
76
78
|
locationGeoSchema: () => locationGeoSchema,
|
|
77
79
|
locationsSchema: () => locationsSchema,
|
|
78
|
-
|
|
80
|
+
mapVendorLicenceToSubscriptionRewardType: () => mapVendorLicenceToSubscriptionRewardType,
|
|
81
|
+
mongoose: () => import_mongoose37.default,
|
|
79
82
|
normalizeAffiliatePromoCodes: () => normalizeAffiliatePromoCodes,
|
|
80
83
|
normalizePromoCode: () => normalizePromoCode,
|
|
81
84
|
refundPolicySchema: () => refundPolicySchema,
|
|
@@ -3705,14 +3708,14 @@ var EnumGameType = /* @__PURE__ */ ((EnumGameType2) => {
|
|
|
3705
3708
|
EnumGameType2["ODD_ONE_OUT"] = "oddOneOut";
|
|
3706
3709
|
return EnumGameType2;
|
|
3707
3710
|
})(EnumGameType || {});
|
|
3708
|
-
var EnumAffiliateRewardType = /* @__PURE__ */ ((
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
return
|
|
3711
|
+
var EnumAffiliateRewardType = /* @__PURE__ */ ((EnumAffiliateRewardType22) => {
|
|
3712
|
+
EnumAffiliateRewardType22["ACTIVE_EVENT_WITH_VENDOR_REGISTRATIONS"] = "ACTIVE_EVENT_WITH_VENDOR_REGISTRATIONS";
|
|
3713
|
+
EnumAffiliateRewardType22["ACTIVE_VENDOR_BONUS_REWARD"] = "ACTIVE_VENDOR_BONUS_REWARD";
|
|
3714
|
+
EnumAffiliateRewardType22["ACTIVE_VENDOR_PRO_SUBSCRIPTION"] = "ACTIVE_VENDOR_PRO_SUBSCRIPTION";
|
|
3715
|
+
EnumAffiliateRewardType22["ACTIVE_VENDOR_STANDARD_SUBSCRIPTION"] = "ACTIVE_VENDOR_STANDARD_SUBSCRIPTION";
|
|
3716
|
+
EnumAffiliateRewardType22["NEW_EVENT_REGISTRATION"] = "NEW_EVENT_REGISTRATION";
|
|
3717
|
+
EnumAffiliateRewardType22["NEW_VENDOR_REGISTRATION"] = "NEW_VENDOR_REGISTRATION";
|
|
3718
|
+
return EnumAffiliateRewardType22;
|
|
3716
3719
|
})(EnumAffiliateRewardType || {});
|
|
3717
3720
|
var statusOptions = [
|
|
3718
3721
|
...Object.values(EnumInviteStatus).map((status) => ({
|
|
@@ -4751,29 +4754,6 @@ var tagOptions = availableTagTypes.map((tag) => ({
|
|
|
4751
4754
|
label: tag.label,
|
|
4752
4755
|
value: tag.label
|
|
4753
4756
|
}));
|
|
4754
|
-
var stallTypes = [
|
|
4755
|
-
"1.8m table only",
|
|
4756
|
-
"2x2m mini stall",
|
|
4757
|
-
"3x3m tent site",
|
|
4758
|
-
"Corner stall",
|
|
4759
|
-
"Craft stall with power",
|
|
4760
|
-
"Craft stall without power",
|
|
4761
|
-
"Double stall (6x3m)",
|
|
4762
|
-
"Food truck site",
|
|
4763
|
-
"Food vendor with power",
|
|
4764
|
-
"Food vendor without power",
|
|
4765
|
-
"Inside hall stall",
|
|
4766
|
-
"Non-profit/community stall",
|
|
4767
|
-
"Outdoor open area",
|
|
4768
|
-
"Shared table space",
|
|
4769
|
-
"Wall-based vendor",
|
|
4770
|
-
"Workshop/seating area"
|
|
4771
|
-
];
|
|
4772
|
-
var stallTypeOptions = stallTypes.map((type) => ({
|
|
4773
|
-
label: type,
|
|
4774
|
-
price: 0,
|
|
4775
|
-
stallCapacity: 0
|
|
4776
|
-
}));
|
|
4777
4757
|
var emailField = {
|
|
4778
4758
|
helperText: "Enter email address",
|
|
4779
4759
|
keyboardType: "email-address",
|
|
@@ -4798,6 +4778,51 @@ var companyContactFields = [
|
|
|
4798
4778
|
placeholder: "Landline Phone Number"
|
|
4799
4779
|
}
|
|
4800
4780
|
];
|
|
4781
|
+
var bankAccountDetailsFields = [
|
|
4782
|
+
{
|
|
4783
|
+
helperText: "Account holder name *",
|
|
4784
|
+
name: "accountHolderName",
|
|
4785
|
+
placeholder: "Account holder name"
|
|
4786
|
+
},
|
|
4787
|
+
{
|
|
4788
|
+
helperText: "Account number *",
|
|
4789
|
+
keyboardType: "number-pad",
|
|
4790
|
+
name: "accountNumber",
|
|
4791
|
+
placeholder: "Account number"
|
|
4792
|
+
}
|
|
4793
|
+
];
|
|
4794
|
+
var eventInfoPaymentInfo = [
|
|
4795
|
+
...bankAccountDetailsFields,
|
|
4796
|
+
{
|
|
4797
|
+
helperText: "Payment link, where applicants can pay *",
|
|
4798
|
+
keyboardType: "url",
|
|
4799
|
+
name: "link",
|
|
4800
|
+
placeholder: "Payment link"
|
|
4801
|
+
}
|
|
4802
|
+
];
|
|
4803
|
+
var stallTypes = [
|
|
4804
|
+
"1.8m table only",
|
|
4805
|
+
"2x2m mini stall",
|
|
4806
|
+
"3x3m tent site",
|
|
4807
|
+
"Corner stall",
|
|
4808
|
+
"Craft stall with power",
|
|
4809
|
+
"Craft stall without power",
|
|
4810
|
+
"Double stall (6x3m)",
|
|
4811
|
+
"Food truck site",
|
|
4812
|
+
"Food vendor with power",
|
|
4813
|
+
"Food vendor without power",
|
|
4814
|
+
"Inside hall stall",
|
|
4815
|
+
"Non-profit/community stall",
|
|
4816
|
+
"Outdoor open area",
|
|
4817
|
+
"Shared table space",
|
|
4818
|
+
"Wall-based vendor",
|
|
4819
|
+
"Workshop/seating area"
|
|
4820
|
+
];
|
|
4821
|
+
var stallTypeOptions = stallTypes.map((type) => ({
|
|
4822
|
+
label: type,
|
|
4823
|
+
price: 0,
|
|
4824
|
+
stallCapacity: 0
|
|
4825
|
+
}));
|
|
4801
4826
|
var loginFields = [
|
|
4802
4827
|
{
|
|
4803
4828
|
...emailField,
|
|
@@ -7569,8 +7594,10 @@ var AFFILIATE_FIELDS_FRAGMENT = gql`
|
|
|
7569
7594
|
}
|
|
7570
7595
|
createdAt
|
|
7571
7596
|
deletedAt
|
|
7572
|
-
|
|
7573
|
-
|
|
7597
|
+
redeemHistory {
|
|
7598
|
+
redeemedAt
|
|
7599
|
+
rewardValue
|
|
7600
|
+
}
|
|
7574
7601
|
overallPoints
|
|
7575
7602
|
owner {
|
|
7576
7603
|
...OwnerFields
|
|
@@ -9356,6 +9383,13 @@ var affiliateDetailsSchema = new MongooseSchema25(
|
|
|
9356
9383
|
},
|
|
9357
9384
|
{ _id: false }
|
|
9358
9385
|
);
|
|
9386
|
+
var redeemHistorySchema = new MongooseSchema25(
|
|
9387
|
+
{
|
|
9388
|
+
redeemedAt: { required: true, type: Date },
|
|
9389
|
+
rewardValue: { required: true, type: Number }
|
|
9390
|
+
},
|
|
9391
|
+
{ _id: false }
|
|
9392
|
+
);
|
|
9359
9393
|
var schema17 = new MongooseSchema25(
|
|
9360
9394
|
{
|
|
9361
9395
|
active: { default: false, required: true, type: Boolean },
|
|
@@ -9372,16 +9406,15 @@ var schema17 = new MongooseSchema25(
|
|
|
9372
9406
|
type: [affiliateResourceSchema]
|
|
9373
9407
|
},
|
|
9374
9408
|
deletedAt: { default: null, required: false, type: Date },
|
|
9375
|
-
lastRewardRedemptionAt: { default: null, required: false, type: Date },
|
|
9376
|
-
lastRewardRedemptionPoints: {
|
|
9377
|
-
default: null,
|
|
9378
|
-
required: false,
|
|
9379
|
-
type: Number
|
|
9380
|
-
},
|
|
9381
9409
|
overallPoints: { default: 0, required: true, type: Number },
|
|
9382
9410
|
owner: {
|
|
9383
9411
|
required: true,
|
|
9384
9412
|
type: OwnerTypeSchema
|
|
9413
|
+
},
|
|
9414
|
+
redeemHistory: {
|
|
9415
|
+
default: [],
|
|
9416
|
+
required: false,
|
|
9417
|
+
type: [redeemHistorySchema]
|
|
9385
9418
|
}
|
|
9386
9419
|
},
|
|
9387
9420
|
{ timestamps: true }
|
|
@@ -9410,89 +9443,12 @@ async function activeAffiliateCodeExists(affiliateCode) {
|
|
|
9410
9443
|
return existing !== null;
|
|
9411
9444
|
}
|
|
9412
9445
|
|
|
9413
|
-
// src/service/affiliate/createAffiliateReward.ts
|
|
9414
|
-
var AFFILIATE_REWARDS = {
|
|
9415
|
-
[EnumAffiliateRewardType.NEW_EVENT_REGISTRATION]: {
|
|
9416
|
-
description: "10 points for new event registration (one-time reward)",
|
|
9417
|
-
value: 10
|
|
9418
|
-
},
|
|
9419
|
-
[EnumAffiliateRewardType.NEW_VENDOR_REGISTRATION]: {
|
|
9420
|
-
description: "5 points for new vendor registration (one-time reward)",
|
|
9421
|
-
value: 5
|
|
9422
|
-
},
|
|
9423
|
-
[EnumAffiliateRewardType.ACTIVE_VENDOR_PRO_SUBSCRIPTION]: {
|
|
9424
|
-
description: "3 points for active vendor pro subscription (monthly reward)",
|
|
9425
|
-
value: 3
|
|
9426
|
-
},
|
|
9427
|
-
[EnumAffiliateRewardType.ACTIVE_VENDOR_STANDARD_SUBSCRIPTION]: {
|
|
9428
|
-
description: "1 point for active vendor standard subscription (monthly reward)",
|
|
9429
|
-
value: 1
|
|
9430
|
-
},
|
|
9431
|
-
[EnumAffiliateRewardType.ACTIVE_VENDOR_BONUS_REWARD]: {
|
|
9432
|
-
description: "5 bonus points for every 10th active vendor (one-time reward)",
|
|
9433
|
-
value: 5
|
|
9434
|
-
},
|
|
9435
|
-
[EnumAffiliateRewardType.ACTIVE_EVENT_WITH_VENDOR_REGISTRATIONS]: {
|
|
9436
|
-
description: "50 points for active event with vendor registrations (one-time reward)",
|
|
9437
|
-
value: 50
|
|
9438
|
-
}
|
|
9439
|
-
};
|
|
9440
|
-
function createAffiliateReward(rewardType, createdAt) {
|
|
9441
|
-
const reward = AFFILIATE_REWARDS[rewardType];
|
|
9442
|
-
return {
|
|
9443
|
-
createdAt,
|
|
9444
|
-
redeemedAt: null,
|
|
9445
|
-
rewardDescription: reward.description,
|
|
9446
|
-
rewardType,
|
|
9447
|
-
rewardValue: reward.value
|
|
9448
|
-
};
|
|
9449
|
-
}
|
|
9450
|
-
|
|
9451
|
-
// src/service/affiliate/findAffiliateByPromoCode.ts
|
|
9452
|
-
async function findAffiliateByPromoCode(promoCode) {
|
|
9453
|
-
return AffiliateModel.findOne({
|
|
9454
|
-
affiliateCode: promoCode,
|
|
9455
|
-
deletedAt: null
|
|
9456
|
-
}).exec();
|
|
9457
|
-
}
|
|
9458
|
-
|
|
9459
9446
|
// src/service/promoCode/normalizePromoCode.ts
|
|
9460
9447
|
function normalizePromoCode(decoratedPromoCode) {
|
|
9461
9448
|
const normalized = decoratedPromoCode?.trim().toUpperCase();
|
|
9462
9449
|
return normalized || null;
|
|
9463
9450
|
}
|
|
9464
9451
|
|
|
9465
|
-
// src/service/affiliate/normalizeAffiliatePromoCodes.ts
|
|
9466
|
-
function normalizeAffiliatePromoCodes(promoCodes) {
|
|
9467
|
-
const normalized = (promoCodes ?? []).map((code) => normalizePromoCode(code)).filter((code) => code !== null);
|
|
9468
|
-
return [...new Set(normalized)];
|
|
9469
|
-
}
|
|
9470
|
-
|
|
9471
|
-
// src/service/database.ts
|
|
9472
|
-
var import_mongoose28 = __toESM(require("mongoose"));
|
|
9473
|
-
var connectToDatabase = async ({
|
|
9474
|
-
appName,
|
|
9475
|
-
dbName,
|
|
9476
|
-
dbPassword,
|
|
9477
|
-
dbUser,
|
|
9478
|
-
mongodbUri
|
|
9479
|
-
}) => {
|
|
9480
|
-
try {
|
|
9481
|
-
const mongoUri = mongodbUri ? mongodbUri : (
|
|
9482
|
-
// Fallback to MongoDB Atlas connection string
|
|
9483
|
-
`mongodb+srv://${dbUser}:${dbPassword}@${dbName}.mongodb.net/?retryWrites=true&w=majority&appName=${appName}`
|
|
9484
|
-
);
|
|
9485
|
-
await import_mongoose28.default.connect(mongoUri);
|
|
9486
|
-
const connectionType = mongodbUri ? "Local MongoDB" : "MongoDB Atlas";
|
|
9487
|
-
console.log(
|
|
9488
|
-
`${connectionType} connected from server/src/service/database.ts`
|
|
9489
|
-
);
|
|
9490
|
-
} catch (err) {
|
|
9491
|
-
console.error("Error connecting to MongoDB:", err);
|
|
9492
|
-
throw err;
|
|
9493
|
-
}
|
|
9494
|
-
};
|
|
9495
|
-
|
|
9496
9452
|
// src/service/saveNotificationsInDb.ts
|
|
9497
9453
|
async function saveNotificationsInDb(payload) {
|
|
9498
9454
|
const { data, message, title, type, userIds } = payload;
|
|
@@ -9626,6 +9582,285 @@ async function sendPushNotifications({
|
|
|
9626
9582
|
}
|
|
9627
9583
|
}
|
|
9628
9584
|
|
|
9585
|
+
// src/service/affiliate/createAffiliateReward.ts
|
|
9586
|
+
var AFFILIATE_REWARDS = {
|
|
9587
|
+
[EnumAffiliateRewardType.NEW_EVENT_REGISTRATION]: {
|
|
9588
|
+
description: "10 points for new event registration (one-time reward)",
|
|
9589
|
+
value: 10
|
|
9590
|
+
},
|
|
9591
|
+
[EnumAffiliateRewardType.NEW_VENDOR_REGISTRATION]: {
|
|
9592
|
+
description: "5 points for new vendor registration (one-time reward)",
|
|
9593
|
+
value: 5
|
|
9594
|
+
},
|
|
9595
|
+
[EnumAffiliateRewardType.ACTIVE_VENDOR_PRO_SUBSCRIPTION]: {
|
|
9596
|
+
description: "3 points for active vendor pro subscription (monthly reward)",
|
|
9597
|
+
value: 3
|
|
9598
|
+
},
|
|
9599
|
+
[EnumAffiliateRewardType.ACTIVE_VENDOR_STANDARD_SUBSCRIPTION]: {
|
|
9600
|
+
description: "1 point for active vendor standard subscription (monthly reward)",
|
|
9601
|
+
value: 1
|
|
9602
|
+
},
|
|
9603
|
+
[EnumAffiliateRewardType.ACTIVE_VENDOR_BONUS_REWARD]: {
|
|
9604
|
+
description: "5 bonus points for every 10th active vendor (one-time reward)",
|
|
9605
|
+
value: 5
|
|
9606
|
+
},
|
|
9607
|
+
[EnumAffiliateRewardType.ACTIVE_EVENT_WITH_VENDOR_REGISTRATIONS]: {
|
|
9608
|
+
description: "50 points for active event with vendor registrations (one-time reward)",
|
|
9609
|
+
value: 50
|
|
9610
|
+
}
|
|
9611
|
+
};
|
|
9612
|
+
function createAffiliateReward(rewardType, createdAt) {
|
|
9613
|
+
const reward = AFFILIATE_REWARDS[rewardType];
|
|
9614
|
+
return {
|
|
9615
|
+
createdAt,
|
|
9616
|
+
redeemedAt: null,
|
|
9617
|
+
rewardDescription: reward.description,
|
|
9618
|
+
rewardType,
|
|
9619
|
+
rewardValue: reward.value
|
|
9620
|
+
};
|
|
9621
|
+
}
|
|
9622
|
+
|
|
9623
|
+
// src/service/affiliate/vendorSubscriptionRewards.ts
|
|
9624
|
+
function mapVendorLicenceToSubscriptionRewardType(licences, now = /* @__PURE__ */ new Date()) {
|
|
9625
|
+
const validTypes = new Set(
|
|
9626
|
+
(licences ?? []).filter(
|
|
9627
|
+
(licence) => new Date(licence.expiryDate).getTime() > now.getTime()
|
|
9628
|
+
).map((licence) => licence.licenceType)
|
|
9629
|
+
);
|
|
9630
|
+
if (validTypes.has(EnumUserLicence.PRO_VENDOR) || validTypes.has(EnumUserLicence.PRO_PLUS_VENDOR)) {
|
|
9631
|
+
return EnumAffiliateRewardType.ACTIVE_VENDOR_PRO_SUBSCRIPTION;
|
|
9632
|
+
}
|
|
9633
|
+
if (validTypes.has(EnumUserLicence.STANDARD_VENDOR)) {
|
|
9634
|
+
return EnumAffiliateRewardType.ACTIVE_VENDOR_STANDARD_SUBSCRIPTION;
|
|
9635
|
+
}
|
|
9636
|
+
return null;
|
|
9637
|
+
}
|
|
9638
|
+
function getSubscriptionRewardPeriodBounds(now = /* @__PURE__ */ new Date()) {
|
|
9639
|
+
const periodStart = new Date(
|
|
9640
|
+
Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)
|
|
9641
|
+
);
|
|
9642
|
+
const periodEnd = new Date(
|
|
9643
|
+
Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1)
|
|
9644
|
+
);
|
|
9645
|
+
return { periodEnd, periodStart };
|
|
9646
|
+
}
|
|
9647
|
+
|
|
9648
|
+
// src/service/affiliate/awardAffiliateVendorSubscriptionRewards.ts
|
|
9649
|
+
function isEligibleVendorResource(resource) {
|
|
9650
|
+
return resource.resourceType === EnumResourceType.VENDOR && resource.resourceActive === true && resource.resourceDeletedAt == null;
|
|
9651
|
+
}
|
|
9652
|
+
async function findAffiliatesWithActiveVendorReferrals() {
|
|
9653
|
+
return await AffiliateModel.find({
|
|
9654
|
+
affiliateResources: {
|
|
9655
|
+
$elemMatch: {
|
|
9656
|
+
resourceActive: true,
|
|
9657
|
+
resourceDeletedAt: null,
|
|
9658
|
+
resourceType: EnumResourceType.VENDOR
|
|
9659
|
+
}
|
|
9660
|
+
},
|
|
9661
|
+
deletedAt: null
|
|
9662
|
+
}).select("_id affiliateCode affiliateResources owner").lean().exec();
|
|
9663
|
+
}
|
|
9664
|
+
async function findEligibleReferredVendor(resourceId, affiliateCode) {
|
|
9665
|
+
return await VendorModel.findOne({
|
|
9666
|
+
_id: resourceId,
|
|
9667
|
+
active: true,
|
|
9668
|
+
deletedAt: null,
|
|
9669
|
+
promoCodes: affiliateCode
|
|
9670
|
+
}).select("_id name owner.userId").lean().exec();
|
|
9671
|
+
}
|
|
9672
|
+
async function resolveSubscriptionRewardTypeForVendorOwner(vendorOwnerUserId, now) {
|
|
9673
|
+
const vendorOwner = await UserModel.findById(vendorOwnerUserId).select("licences").lean().exec();
|
|
9674
|
+
return mapVendorLicenceToSubscriptionRewardType(vendorOwner?.licences, now);
|
|
9675
|
+
}
|
|
9676
|
+
async function notifyAffiliateOwnerOfSubscriptionReward({
|
|
9677
|
+
affiliateId,
|
|
9678
|
+
affiliateOwnerUserId,
|
|
9679
|
+
resourceName,
|
|
9680
|
+
rewardValue
|
|
9681
|
+
}) {
|
|
9682
|
+
const payload = {
|
|
9683
|
+
data: {
|
|
9684
|
+
resourceId: String(affiliateId),
|
|
9685
|
+
resourceName,
|
|
9686
|
+
resourceType: EnumNotificationResourceType.AFFILIATE_REWARD_RECEIVED
|
|
9687
|
+
},
|
|
9688
|
+
message: `You earned ${rewardValue} points! Your referred vendor "${resourceName}" has an active subscription.`,
|
|
9689
|
+
title: "Affiliate points earned",
|
|
9690
|
+
type: EnumNotificationType.SYSTEM,
|
|
9691
|
+
userIds: [affiliateOwnerUserId]
|
|
9692
|
+
};
|
|
9693
|
+
try {
|
|
9694
|
+
await saveNotificationsInDb(payload);
|
|
9695
|
+
await sendPushNotifications(payload);
|
|
9696
|
+
} catch (error) {
|
|
9697
|
+
console.error(
|
|
9698
|
+
`[affiliate] subscription reward notification failed for affiliate ${String(affiliateId)}:`,
|
|
9699
|
+
error instanceof Error ? error.message : error
|
|
9700
|
+
);
|
|
9701
|
+
}
|
|
9702
|
+
}
|
|
9703
|
+
async function tryAwardSubscriptionReward({
|
|
9704
|
+
affiliate,
|
|
9705
|
+
createdAt,
|
|
9706
|
+
period,
|
|
9707
|
+
resource,
|
|
9708
|
+
rewardType,
|
|
9709
|
+
vendor
|
|
9710
|
+
}) {
|
|
9711
|
+
const reward = createAffiliateReward(rewardType, createdAt);
|
|
9712
|
+
const updateResult = await AffiliateModel.updateOne(
|
|
9713
|
+
{
|
|
9714
|
+
_id: affiliate._id,
|
|
9715
|
+
affiliateResources: {
|
|
9716
|
+
$elemMatch: {
|
|
9717
|
+
resourceActive: true,
|
|
9718
|
+
resourceDeletedAt: null,
|
|
9719
|
+
resourceId: vendor._id,
|
|
9720
|
+
resourceType: EnumResourceType.VENDOR,
|
|
9721
|
+
rewards: {
|
|
9722
|
+
$not: {
|
|
9723
|
+
$elemMatch: {
|
|
9724
|
+
createdAt: {
|
|
9725
|
+
$gte: period.periodStart,
|
|
9726
|
+
$lt: period.periodEnd
|
|
9727
|
+
},
|
|
9728
|
+
rewardType
|
|
9729
|
+
}
|
|
9730
|
+
}
|
|
9731
|
+
}
|
|
9732
|
+
}
|
|
9733
|
+
},
|
|
9734
|
+
deletedAt: null
|
|
9735
|
+
},
|
|
9736
|
+
{
|
|
9737
|
+
$inc: { overallPoints: reward.rewardValue },
|
|
9738
|
+
$push: { "affiliateResources.$.rewards": reward }
|
|
9739
|
+
}
|
|
9740
|
+
).exec();
|
|
9741
|
+
if (updateResult.modifiedCount === 0) {
|
|
9742
|
+
return "skipped";
|
|
9743
|
+
}
|
|
9744
|
+
const affiliateOwnerUserId = affiliate.owner?.userId;
|
|
9745
|
+
if (affiliateOwnerUserId) {
|
|
9746
|
+
await notifyAffiliateOwnerOfSubscriptionReward({
|
|
9747
|
+
affiliateId: affiliate._id,
|
|
9748
|
+
affiliateOwnerUserId,
|
|
9749
|
+
resourceName: resource.resourceName || vendor.name || "vendor",
|
|
9750
|
+
rewardValue: reward.rewardValue
|
|
9751
|
+
});
|
|
9752
|
+
}
|
|
9753
|
+
return "awarded";
|
|
9754
|
+
}
|
|
9755
|
+
async function processAffiliateVendorReferral({
|
|
9756
|
+
affiliate,
|
|
9757
|
+
affiliateCode,
|
|
9758
|
+
createdAt,
|
|
9759
|
+
now,
|
|
9760
|
+
period,
|
|
9761
|
+
resource
|
|
9762
|
+
}) {
|
|
9763
|
+
const vendor = await findEligibleReferredVendor(
|
|
9764
|
+
resource.resourceId,
|
|
9765
|
+
affiliateCode
|
|
9766
|
+
);
|
|
9767
|
+
if (!vendor?.owner?.userId) {
|
|
9768
|
+
return "skipped";
|
|
9769
|
+
}
|
|
9770
|
+
const rewardType = await resolveSubscriptionRewardTypeForVendorOwner(
|
|
9771
|
+
vendor.owner.userId,
|
|
9772
|
+
now
|
|
9773
|
+
);
|
|
9774
|
+
if (!rewardType) {
|
|
9775
|
+
return "skipped";
|
|
9776
|
+
}
|
|
9777
|
+
return tryAwardSubscriptionReward({
|
|
9778
|
+
affiliate,
|
|
9779
|
+
createdAt,
|
|
9780
|
+
period,
|
|
9781
|
+
resource,
|
|
9782
|
+
rewardType,
|
|
9783
|
+
vendor
|
|
9784
|
+
});
|
|
9785
|
+
}
|
|
9786
|
+
async function awardAffiliateVendorSubscriptionRewards(now = /* @__PURE__ */ new Date()) {
|
|
9787
|
+
const period = getSubscriptionRewardPeriodBounds(now);
|
|
9788
|
+
const createdAt = now;
|
|
9789
|
+
const affiliates = await findAffiliatesWithActiveVendorReferrals();
|
|
9790
|
+
let awarded = 0;
|
|
9791
|
+
let skipped = 0;
|
|
9792
|
+
const seenPairs = /* @__PURE__ */ new Set();
|
|
9793
|
+
for (const affiliate of affiliates) {
|
|
9794
|
+
const affiliateCode = normalizePromoCode(affiliate.affiliateCode);
|
|
9795
|
+
if (!affiliateCode) {
|
|
9796
|
+
continue;
|
|
9797
|
+
}
|
|
9798
|
+
for (const resource of affiliate.affiliateResources) {
|
|
9799
|
+
if (!isEligibleVendorResource(resource)) {
|
|
9800
|
+
continue;
|
|
9801
|
+
}
|
|
9802
|
+
const pairKey = `${String(affiliate._id)}:${String(resource.resourceId)}`;
|
|
9803
|
+
if (seenPairs.has(pairKey)) {
|
|
9804
|
+
continue;
|
|
9805
|
+
}
|
|
9806
|
+
seenPairs.add(pairKey);
|
|
9807
|
+
const outcome = await processAffiliateVendorReferral({
|
|
9808
|
+
affiliate,
|
|
9809
|
+
affiliateCode,
|
|
9810
|
+
createdAt,
|
|
9811
|
+
now,
|
|
9812
|
+
period,
|
|
9813
|
+
resource
|
|
9814
|
+
});
|
|
9815
|
+
if (outcome === "awarded") {
|
|
9816
|
+
awarded += 1;
|
|
9817
|
+
} else {
|
|
9818
|
+
skipped += 1;
|
|
9819
|
+
}
|
|
9820
|
+
}
|
|
9821
|
+
}
|
|
9822
|
+
return { awarded, skipped };
|
|
9823
|
+
}
|
|
9824
|
+
|
|
9825
|
+
// src/service/affiliate/findAffiliateByPromoCode.ts
|
|
9826
|
+
async function findAffiliateByPromoCode(promoCode) {
|
|
9827
|
+
return AffiliateModel.findOne({
|
|
9828
|
+
affiliateCode: promoCode,
|
|
9829
|
+
deletedAt: null
|
|
9830
|
+
}).exec();
|
|
9831
|
+
}
|
|
9832
|
+
|
|
9833
|
+
// src/service/affiliate/normalizeAffiliatePromoCodes.ts
|
|
9834
|
+
function normalizeAffiliatePromoCodes(promoCodes) {
|
|
9835
|
+
const normalized = (promoCodes ?? []).map((code) => normalizePromoCode(code)).filter((code) => code !== null);
|
|
9836
|
+
return [...new Set(normalized)];
|
|
9837
|
+
}
|
|
9838
|
+
|
|
9839
|
+
// src/service/database.ts
|
|
9840
|
+
var import_mongoose29 = __toESM(require("mongoose"));
|
|
9841
|
+
var connectToDatabase = async ({
|
|
9842
|
+
appName,
|
|
9843
|
+
dbName,
|
|
9844
|
+
dbPassword,
|
|
9845
|
+
dbUser,
|
|
9846
|
+
mongodbUri
|
|
9847
|
+
}) => {
|
|
9848
|
+
try {
|
|
9849
|
+
const mongoUri = mongodbUri ? mongodbUri : (
|
|
9850
|
+
// Fallback to MongoDB Atlas connection string
|
|
9851
|
+
`mongodb+srv://${dbUser}:${dbPassword}@${dbName}.mongodb.net/?retryWrites=true&w=majority&appName=${appName}`
|
|
9852
|
+
);
|
|
9853
|
+
await import_mongoose29.default.connect(mongoUri);
|
|
9854
|
+
const connectionType = mongodbUri ? "Local MongoDB" : "MongoDB Atlas";
|
|
9855
|
+
console.log(
|
|
9856
|
+
`${connectionType} connected from server/src/service/database.ts`
|
|
9857
|
+
);
|
|
9858
|
+
} catch (err) {
|
|
9859
|
+
console.error("Error connecting to MongoDB:", err);
|
|
9860
|
+
throw err;
|
|
9861
|
+
}
|
|
9862
|
+
};
|
|
9863
|
+
|
|
9629
9864
|
// src/service/updateAdStatus.ts
|
|
9630
9865
|
async function updateAdStatuses() {
|
|
9631
9866
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -9662,9 +9897,9 @@ async function updateAdStatuses() {
|
|
|
9662
9897
|
}
|
|
9663
9898
|
|
|
9664
9899
|
// src/service/associate.ts
|
|
9665
|
-
var
|
|
9900
|
+
var import_mongoose31 = __toESM(require("mongoose"));
|
|
9666
9901
|
function normalizeObjectId(id) {
|
|
9667
|
-
return typeof id === "string" ? new
|
|
9902
|
+
return typeof id === "string" ? new import_mongoose31.default.Types.ObjectId(id) : id;
|
|
9668
9903
|
}
|
|
9669
9904
|
async function getAssociateEmailsForResource({
|
|
9670
9905
|
normalizedResourceId,
|
|
@@ -9816,12 +10051,12 @@ async function updateVendorBasedOnUserLicense(userId, licenceType) {
|
|
|
9816
10051
|
}
|
|
9817
10052
|
|
|
9818
10053
|
// src/service/objectIdToString.ts
|
|
9819
|
-
var
|
|
10054
|
+
var import_mongoose34 = __toESM(require("mongoose"));
|
|
9820
10055
|
function convertObjectIdsToStrings(obj) {
|
|
9821
10056
|
if (obj === null || obj === void 0) {
|
|
9822
10057
|
return obj;
|
|
9823
10058
|
}
|
|
9824
|
-
if (obj instanceof
|
|
10059
|
+
if (obj instanceof import_mongoose34.default.Types.ObjectId) {
|
|
9825
10060
|
return obj.toString();
|
|
9826
10061
|
}
|
|
9827
10062
|
if (obj instanceof Date) {
|
|
@@ -10005,7 +10240,7 @@ function updateRelationDatesToUnavailable(relationDates, eventDateTime) {
|
|
|
10005
10240
|
|
|
10006
10241
|
// src/types/index.ts
|
|
10007
10242
|
var import_express = __toESM(require("express"));
|
|
10008
|
-
var
|
|
10243
|
+
var import_mongoose37 = __toESM(require("mongoose"));
|
|
10009
10244
|
var EnumPubSubEvents = /* @__PURE__ */ ((EnumPubSubEvents2) => {
|
|
10010
10245
|
EnumPubSubEvents2["GET_CHAT_MESSAGE"] = "GET_CHAT_MESSAGE";
|
|
10011
10246
|
EnumPubSubEvents2["GET_NOTIFICATIONS"] = "GET_NOTIFICATIONS";
|
|
@@ -10049,6 +10284,7 @@ var EnumPubSubEvents = /* @__PURE__ */ ((EnumPubSubEvents2) => {
|
|
|
10049
10284
|
VerificationTokenModel,
|
|
10050
10285
|
activeAffiliateCodeExists,
|
|
10051
10286
|
associatesSchema,
|
|
10287
|
+
awardAffiliateVendorSubscriptionRewards,
|
|
10052
10288
|
baseResourceFields,
|
|
10053
10289
|
connectToDatabase,
|
|
10054
10290
|
convertObjectIdsToStrings,
|
|
@@ -10058,8 +10294,10 @@ var EnumPubSubEvents = /* @__PURE__ */ ((EnumPubSubEvents2) => {
|
|
|
10058
10294
|
express,
|
|
10059
10295
|
findAffiliateByPromoCode,
|
|
10060
10296
|
findEventOrImportedMarketById,
|
|
10297
|
+
getSubscriptionRewardPeriodBounds,
|
|
10061
10298
|
locationGeoSchema,
|
|
10062
10299
|
locationsSchema,
|
|
10300
|
+
mapVendorLicenceToSubscriptionRewardType,
|
|
10063
10301
|
mongoose,
|
|
10064
10302
|
normalizeAffiliatePromoCodes,
|
|
10065
10303
|
normalizePromoCode,
|