bulltrackers-module 1.0.512 → 1.0.514

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.
@@ -232,10 +232,10 @@ async function handleComputationTask(message, config, dependencies) {
232
232
  await db.doc(ledgerPath).update({ status: 'COMPLETED', completedAt: new Date() });
233
233
  await recordRunAttempt(db, { date, computation, pass }, 'SUCCESS', null, metrics, triggerReason, resourceTier);
234
234
 
235
+ const { notifyComputationComplete, getComputationDisplayName } = require('../../generic-api/user-api/helpers/notifications/notification_helpers');
235
236
  // Send notification if this was an on-demand computation
236
237
  if (metadata?.onDemand && metadata?.requestId && metadata?.requestingUserCid) {
237
238
  try {
238
- const { notifyComputationComplete, getComputationDisplayName } = require('../../generic-api/user-api/helpers/notification_helpers');
239
239
  await notifyComputationComplete(
240
240
  dependencies.db,
241
241
  dependencies.logger,
@@ -283,7 +283,6 @@ async function handleComputationTask(message, config, dependencies) {
283
283
  // Send error notification if this was an on-demand computation
284
284
  if (metadata?.onDemand && metadata?.requestId && metadata?.requestingUserCid) {
285
285
  try {
286
- const { notifyComputationComplete, getComputationDisplayName } = require('../../generic-api/user-api/helpers/notification_helpers');
287
286
  await notifyComputationComplete(
288
287
  db,
289
288
  dependencies.logger,
@@ -74,25 +74,95 @@ async function requestUserSync(req, res, dependencies, config) {
74
74
  // Determine user type (PI or signed-in user)
75
75
  // Check if user is in rankings (PI) or has signed-in user data
76
76
  const { checkIfUserIsPI } = require('../data_helpers');
77
- const isPI = await checkIfUserIsPI(db, targetCidNum, config, logger);
77
+ let isPI = await checkIfUserIsPI(db, targetCidNum, config, logger);
78
+
79
+ // Fallback: If not found in rankings, check if they have PI data (portfolio, history, or social)
80
+ // This handles cases where a PI might not be in the latest rankings but has historical data
81
+ if (!isPI) {
82
+ try {
83
+ const today = new Date().toISOString().split('T')[0];
84
+ let hasPiData = false;
85
+
86
+ // Check if they have PI portfolio data (any date in last 7 days)
87
+ for (let i = 0; i <= 7; i++) {
88
+ const checkDate = new Date();
89
+ checkDate.setDate(checkDate.getDate() - i);
90
+ const dateStr = checkDate.toISOString().split('T')[0];
91
+
92
+ // Check portfolio data
93
+ const portfolioRef = db.collection('PopularInvestorPortfolioData')
94
+ .doc(dateStr)
95
+ .collection(String(targetCidNum))
96
+ .doc(String(targetCidNum));
97
+ const portfolioDoc = await portfolioRef.get();
98
+
99
+ if (portfolioDoc.exists) {
100
+ logger.log('INFO', `[requestUserSync] User ${targetCidNum} has PI portfolio data from ${dateStr}, treating as PI`);
101
+ hasPiData = true;
102
+ break;
103
+ }
104
+
105
+ // Check trade history data
106
+ const historyRef = db.collection('PopularInvestorTradeHistoryData')
107
+ .doc(dateStr)
108
+ .collection(String(targetCidNum))
109
+ .doc(String(targetCidNum));
110
+ const historyDoc = await historyRef.get();
111
+
112
+ if (historyDoc.exists) {
113
+ logger.log('INFO', `[requestUserSync] User ${targetCidNum} has PI trade history data from ${dateStr}, treating as PI`);
114
+ hasPiData = true;
115
+ break;
116
+ }
117
+
118
+ // Check social posts data
119
+ const socialRef = db.collection('PopularInvestorSocialPostData')
120
+ .doc(dateStr)
121
+ .collection(String(targetCidNum))
122
+ .doc(String(targetCidNum));
123
+ const socialDoc = await socialRef.get();
124
+
125
+ if (socialDoc.exists) {
126
+ logger.log('INFO', `[requestUserSync] User ${targetCidNum} has PI social posts data from ${dateStr}, treating as PI`);
127
+ hasPiData = true;
128
+ break;
129
+ }
130
+ }
131
+
132
+ if (hasPiData) {
133
+ isPI = { CustomerId: targetCidNum, UserName: null }; // Fake ranking entry
134
+ } else {
135
+ logger.log('INFO', `[requestUserSync] User ${targetCidNum} not found in rankings and no PI data found, treating as signed-in user`);
136
+ }
137
+ } catch (fallbackErr) {
138
+ logger.log('WARN', `[requestUserSync] Error checking PI data fallback for ${targetCidNum}:`, fallbackErr.message);
139
+ }
140
+ } else {
141
+ logger.log('INFO', `[requestUserSync] User ${targetCidNum} found in rankings as PI`);
142
+ }
78
143
 
79
144
  // Get username - for PIs, get from rankings; for signed-in users, we'll need to fetch from their profile
80
145
  let username = null;
81
146
  if (isPI) {
82
- // Get PI username from rankings
83
- const { findLatestRankingsDate } = require('../data_helpers');
84
- const rankingsCollection = config.popularInvestorRankingsCollection || 'popular_investor_rankings';
85
- const rankingsDate = await findLatestRankingsDate(db, rankingsCollection, 30);
86
-
87
- if (rankingsDate) {
88
- const rankingsRef = db.collection(rankingsCollection).doc(rankingsDate);
89
- const rankingsDoc = await rankingsRef.get();
90
- if (rankingsDoc.exists) {
91
- const rankingsData = rankingsDoc.data();
92
- const rankingsItems = rankingsData.Items || [];
93
- const rankingEntry = rankingsItems.find(item => Number(item.CustomerId) === targetCidNum);
94
- if (rankingEntry) {
95
- username = rankingEntry.UserName || rankingEntry.username || null;
147
+ // Get PI username from rankings (if available)
148
+ if (isPI.UserName || isPI.username) {
149
+ username = isPI.UserName || isPI.username;
150
+ } else {
151
+ // Try to get from rankings if we have a fake entry
152
+ const { findLatestRankingsDate } = require('../data_helpers');
153
+ const rankingsCollection = config.popularInvestorRankingsCollection || 'popular_investor_rankings';
154
+ const rankingsDate = await findLatestRankingsDate(db, rankingsCollection, 30);
155
+
156
+ if (rankingsDate) {
157
+ const rankingsRef = db.collection(rankingsCollection).doc(rankingsDate);
158
+ const rankingsDoc = await rankingsRef.get();
159
+ if (rankingsDoc.exists) {
160
+ const rankingsData = rankingsDoc.data();
161
+ const rankingsItems = rankingsData.Items || [];
162
+ const rankingEntry = rankingsItems.find(item => Number(item.CustomerId) === targetCidNum);
163
+ if (rankingEntry) {
164
+ username = rankingEntry.UserName || rankingEntry.username || null;
165
+ }
96
166
  }
97
167
  }
98
168
  }
@@ -172,7 +242,8 @@ async function requestUserSync(req, res, dependencies, config) {
172
242
  targetCid: targetCidNum, // Target specific user for optimization
173
243
  requestedAt: now.toISOString(),
174
244
  isImpersonating: isImpersonating || false,
175
- requestingUserCid: Number(requestingUserCid) // Store for notifications
245
+ requestingUserCid: Number(requestingUserCid), // Store for notifications
246
+ userType: isPI ? 'POPULAR_INVESTOR' : 'SIGNED_IN_USER' // Explicitly set userType in metadata
176
247
  }
177
248
  };
178
249
 
@@ -40,9 +40,9 @@ async function storeSignedInUserPortfolio({ db, logger, collectionRegistry, cid,
40
40
  if (!getCollectionPath) {
41
41
  throw new Error('collectionRegistry.getCollectionPath is required');
42
42
  }
43
- const userLatestRef = db.collection(
44
- getCollectionPath('signedInUsers', 'portfolio', { cid })
45
- ).doc('latest');
43
+ // Path is already a document path: SignedInUsers/{cid}/portfolio/latest (4 segments)
44
+ const userLatestPath = getCollectionPath('signedInUsers', 'portfolio', { cid });
45
+ const userLatestRef = db.doc(userLatestPath);
46
46
 
47
47
  await userLatestRef.set({
48
48
  ...portfolioData,
@@ -84,9 +84,9 @@ async function storeSignedInUserTradeHistory({ db, logger, collectionRegistry, c
84
84
  if (!getCollectionPath) {
85
85
  throw new Error('collectionRegistry.getCollectionPath is required');
86
86
  }
87
- const userLatestRef = db.collection(
88
- getCollectionPath('signedInUsers', 'tradeHistory', { cid })
89
- ).doc('latest');
87
+ // Path is already a document path: SignedInUsers/{cid}/tradeHistory/latest (4 segments)
88
+ const userLatestPath = getCollectionPath('signedInUsers', 'tradeHistory', { cid });
89
+ const userLatestRef = db.doc(userLatestPath);
90
90
 
91
91
  await userLatestRef.set({
92
92
  ...historyData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.512",
3
+ "version": "1.0.514",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [