@lyxa.ai/core 1.4.19 → 1.4.20
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/index.js.map +1 -1
- package/dist/libraries/cash-settlement/providers/bob.d.ts +3 -0
- package/dist/libraries/cash-settlement/providers/bob.js +112 -30
- package/dist/libraries/cash-settlement/providers/bob.js.map +1 -1
- package/dist/libraries/trpc/middlewares/auth.d.ts +1 -1
- package/dist/libraries/trpc/middlewares/createRoleProtectedProcedure.d.ts +1 -1
- package/dist/libraries/trpc/middlewares/phone-verified.d.ts +1 -1
- package/dist/libraries/trpc/middlewares/publicUserDecoder.d.ts +1 -1
- package/dist/types/README.md +1 -1
- package/dist/types/package.json +1 -1
- package/dist/types/utilities/validation/common-validation.d.ts +12 -12
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["// Apply the soft delete plugin globally before any connections or models\nimport { applySoftDeletePlugin } from './libraries/mongo/plugins/soft-delete-plugin';\napplySoftDeletePlugin();\nimport { LibraryManager } from './libraries';\nimport { Container } from 'typedi';\nimport { ConfigurationOptions, ConfigurationService } from './libraries/configuration';\nimport { LyxaLogger } from './libraries/logger';\nimport { RedisService } from './libraries/redis';\nimport { initGlobalConnection, initLyxaMongoDbConnection } from './libraries/mongo';\nimport { SecretManagerService } from './libraries/secrets';\nimport { MicroServiceDispatcher } from './libraries/dispatcher';\nimport { TwilioService } from './libraries/twilio';\nimport { FirebaseService } from './libraries/firebase';\nimport { initEventBus, subscribeToEvent } from './libraries/event';\nimport { SubscriptionRegistry } from './libraries/event/registry/SubscriptionRegistry';\nimport { GoogleMapsService, MapService } from './libraries/map';\nimport { CachedSettingsService } from './libraries/cache/settings';\nimport {\n\tFCMService,\n\tFCMServiceForCpanel,\n\tFCMServiceForRider,\n\tFCMServiceForShop,\n\tFCMServiceForUser,\n} from './libraries/firebase/fcmService';\nimport { BullMQService } from './libraries/bullmq/bull-mq-service';\nimport { BOBSecrets, BOBService, CashSettlementService } from './libraries/cash-settlement';\nimport { EnvironmentConfigurationType } from './libraries/configuration/types/EnvironmentConfigurationType';\nimport { OsrmMapService } from './libraries/map/providers/osrm';\nimport { RabbitMQUrlMap } from './utilities/environment/rabbitmq-environments';\nimport { disconnectAllEntitiesFromInstance } from './libraries/socket/connections/instance-disconnect';\nimport { LyxaLoggerKit } from './libraries/logger-kit';\n\n\n\nexport { ConfigurationOptions } from './libraries/configuration';\nexport { EnvironmentConfigurationType } from './libraries/configuration/types/EnvironmentConfigurationType';\nexport { initGlobalConnection } from './libraries/mongo';\n\nexport async function bootstrapCore(options?: ConfigurationOptions) {\n\ttry {\n\t\tawait registerLibraries(options);\n\t\tgetLibraries().getLogger().logger.info('Successfully bootstrapped lyxa-core.');\n\n\t\tconst gracefulShutdown = async () => {\n\t\t\tgetLibraries().getLogger().logger.info('Received shutdown signal, shutting down gracefully...');\n\t\t\tif (options?.instanceType == 'socket') await disconnectAllEntitiesFromInstance();\n\t\t\tprocess.exit();\n\t\t};\n\n\t\tprocess.on('SIGTERM', gracefulShutdown);\n\t\tprocess.on('SIGINT', gracefulShutdown);\n\t\tprocess.on('uncaughtException', err => {\n\t\t\tconsole.log('err', err);\n\t\t\tgetLibraries().getLogger().logger.error('Uncaught exception, shutting down...', err);\n\t\t\tgracefulShutdown();\n\t\t});\n\t\tprocess.on('exit', code => {\n\t\t\tgetLibraries().getLogger().logger.info(`Exiting with code: ${code}`);\n\t\t});\n\n\t\tconsole.log('Created hooks.');\n\t} catch (e) {\n\t\tconsole.error(e);\n\t}\n}\n\nexport async function registerLibraries(options?: ConfigurationOptions) {\n\t// Setup configuration.\n\tconst configurationInstance = new ConfigurationService(options);\n\tContainer.set(ConfigurationService, configurationInstance);\n\n\t// Setup redis.\n\tconst redisInstance = new RedisService(configurationInstance.redisURL);\n\tContainer.set(RedisService, redisInstance);\n\n\t// Setup secret\n\tconst secretInstance = new SecretManagerService(configurationInstance, redisInstance);\n\tContainer.set(SecretManagerService, secretInstance);\n\n\t// Setup BullMQ\n\tconst bullMQInstance = new BullMQService(redisInstance);\n\tContainer.set(BullMQService, bullMQInstance);\n\n\tconst mongoUrl = options?.mongoDbUrl\n\t\t? options.mongoDbUrl\n\t\t: await getLibraries().getSecretsService().getKey('MONGO_URL');\n\n\tawait initLyxaMongoDbConnection(mongoUrl!, options);\n\tawait initGlobalConnection(mongoUrl!, options!.environment);\n\n\tconst loggerInstance = new LyxaLogger(options!.instanceType!, mongoUrl!);\n\tContainer.set(LyxaLogger, loggerInstance);\n\n\tconst loggerKit = new LyxaLoggerKit({ instanceType: options!.instanceType! });\n\tContainer.set(LyxaLoggerKit, loggerKit);\n\t\n\t// Setup firebase\n\tconst firebaseInstance = new FirebaseService(configurationInstance!);\n\tContainer.set(FirebaseService, firebaseInstance);\n\n\t// Setup microservice dispatcher\n\tconst microserviceDispatcherInstance = new MicroServiceDispatcher(secretInstance);\n\tContainer.set(MicroServiceDispatcher, microserviceDispatcherInstance);\n\n\t// Setup twilio\n\tconst twilioServiceInstance = new TwilioService();\n\tContainer.set(TwilioService, twilioServiceInstance);\n\n\t// Setup map service\n\tconst googleMapsKey = await getLibraries().getSecretsService().getKey('GOOGLE_MAPS_API_KEY');\n\tconst googleMapService = new GoogleMapsService(redisInstance, googleMapsKey as string);\n\tconst osrmMapService = new OsrmMapService();\n\tconst mapServiceInstance = new MapService(googleMapService, osrmMapService);\n\tContainer.set(MapService, mapServiceInstance);\n\n\t// Setup cash settlement service\n\tconst bobUsername = await getLibraries().getSecretsService().getKey('BOB_USER_NAME');\n\tconst bobPassword = await getLibraries().getSecretsService().getKey('BOB_PASSWORD');\n\tconst bobURL = await getLibraries().getSecretsService().getKey('BOB_URL');\n\n\tconst bobService = new BOBService({\n\t\tBOB_USER_NAME: bobUsername,\n\t\tBOB_PASSWORD: bobPassword,\n\t\tBOB_URL: bobURL,\n\t} as BOBSecrets);\n\tconst cashSettlementServiceInstance = new CashSettlementService(bobService);\n\tContainer.set(CashSettlementService, cashSettlementServiceInstance);\n\tContainer.set(BOBService, bobService);\n\n\tconst settingsServiceInstance = new CachedSettingsService(redisInstance);\n\tContainer.set(CachedSettingsService, settingsServiceInstance);\n\n\ttry {\n\t\tconst settings = await settingsServiceInstance.getSettings();\n\t\tconst { _setTimezone } = await import('./utilities/dayjs/dayjs');\n\t\t_setTimezone(settings?.timezone || 'Asia/Beirut');\n\t\tconsole.log('Timezone initialized:', settings?.timezone || 'Asia/Beirut');\n\t} catch (error) {\n\t\tconsole.error('Failed to initialize timezone:', error);\n\t}\n\n\t// Setup fcm service\n\tconst firebaseService = getLibraries().getFirebaseService();\n\tconst fcmServiceInstance = new FCMService(firebaseService.superApp);\n\tconst fcmServiceInstanceForUser = new FCMService(firebaseService.userApp);\n\tconst fcmServiceInstanceForRider = new FCMService(firebaseService.riderApp);\n\tconst fcmServiceInstanceForShop = new FCMService(firebaseService.shopApp);\n\tconst fcmServiceInstanceForCpanel = new FCMService(firebaseService.cpanelApp);\n\tContainer.set(FCMService, fcmServiceInstance);\n\tContainer.set(FCMServiceForUser, fcmServiceInstanceForUser);\n\tContainer.set(FCMServiceForRider, fcmServiceInstanceForRider);\n\tContainer.set(FCMServiceForShop, fcmServiceInstanceForShop);\n\tContainer.set(FCMServiceForCpanel, fcmServiceInstanceForCpanel);\n\n\tconsole.log('Initialized everything');\n\n\tawait initEventBus(RabbitMQUrlMap[options?.environment ?? EnvironmentConfigurationType.DEV]);\n\n\tconst allSubscriptions = SubscriptionRegistry.getAllSubscriptions();\n\n\tconst instantiatedServices = new Map<Function, any>();\n\n\tfor (const { eventId, targetConstructor, methodName, opts } of allSubscriptions) {\n\t\tlet instance = instantiatedServices.get(targetConstructor);\n\t\tif (!instance) {\n\t\t\tinstance = Container.get(targetConstructor as any);\n\t\t\tinstantiatedServices.set(targetConstructor, instance);\n\t\t}\n\n\t\tawait subscribeToEvent(\n\t\t\teventId,\n\t\t\tasync payload => {\n\t\t\t\treturn instance[methodName](payload);\n\t\t\t},\n\t\t\topts\n\t\t);\n\t}\n}\n\nexport function getLibraries(): LibraryManager {\n\treturn Container.get(LibraryManager);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["// Apply the soft delete plugin globally before any connections or models\nimport { applySoftDeletePlugin } from './libraries/mongo/plugins/soft-delete-plugin';\napplySoftDeletePlugin();\nimport { LibraryManager } from './libraries';\nimport { Container } from 'typedi';\nimport { ConfigurationOptions, ConfigurationService } from './libraries/configuration';\nimport { LyxaLogger } from './libraries/logger';\nimport { RedisService } from './libraries/redis';\nimport { initGlobalConnection, initLyxaMongoDbConnection } from './libraries/mongo';\nimport { SecretManagerService } from './libraries/secrets';\nimport { MicroServiceDispatcher } from './libraries/dispatcher';\nimport { TwilioService } from './libraries/twilio';\nimport { FirebaseService } from './libraries/firebase';\nimport { initEventBus, subscribeToEvent } from './libraries/event';\nimport { SubscriptionRegistry } from './libraries/event/registry/SubscriptionRegistry';\nimport { GoogleMapsService, MapService } from './libraries/map';\nimport { CachedSettingsService } from './libraries/cache/settings';\nimport {\n\tFCMService,\n\tFCMServiceForCpanel,\n\tFCMServiceForRider,\n\tFCMServiceForShop,\n\tFCMServiceForUser,\n} from './libraries/firebase/fcmService';\nimport { BullMQService } from './libraries/bullmq/bull-mq-service';\nimport { BOBSecrets, BOBService, CashSettlementService } from './libraries/cash-settlement';\nimport { EnvironmentConfigurationType } from './libraries/configuration/types/EnvironmentConfigurationType';\nimport { OsrmMapService } from './libraries/map/providers/osrm';\nimport { RabbitMQUrlMap } from './utilities/environment/rabbitmq-environments';\nimport { disconnectAllEntitiesFromInstance } from './libraries/socket/connections/instance-disconnect';\nimport { LyxaLoggerKit } from './libraries/logger-kit';\n\nexport { ConfigurationOptions } from './libraries/configuration';\nexport { EnvironmentConfigurationType } from './libraries/configuration/types/EnvironmentConfigurationType';\nexport { initGlobalConnection } from './libraries/mongo';\n\nexport async function bootstrapCore(options?: ConfigurationOptions) {\n\ttry {\n\t\tawait registerLibraries(options);\n\t\tgetLibraries().getLogger().logger.info('Successfully bootstrapped lyxa-core.');\n\n\t\tconst gracefulShutdown = async () => {\n\t\t\tgetLibraries().getLogger().logger.info('Received shutdown signal, shutting down gracefully...');\n\t\t\tif (options?.instanceType == 'socket') await disconnectAllEntitiesFromInstance();\n\t\t\tprocess.exit();\n\t\t};\n\n\t\tprocess.on('SIGTERM', gracefulShutdown);\n\t\tprocess.on('SIGINT', gracefulShutdown);\n\t\tprocess.on('uncaughtException', err => {\n\t\t\tconsole.log('err', err);\n\t\t\tgetLibraries().getLogger().logger.error('Uncaught exception, shutting down...', err);\n\t\t\tgracefulShutdown();\n\t\t});\n\t\tprocess.on('exit', code => {\n\t\t\tgetLibraries().getLogger().logger.info(`Exiting with code: ${code}`);\n\t\t});\n\n\t\tconsole.log('Created hooks.');\n\t} catch (e) {\n\t\tconsole.error(e);\n\t}\n}\n\nexport async function registerLibraries(options?: ConfigurationOptions) {\n\t// Setup configuration.\n\tconst configurationInstance = new ConfigurationService(options);\n\tContainer.set(ConfigurationService, configurationInstance);\n\n\t// Setup redis.\n\tconst redisInstance = new RedisService(configurationInstance.redisURL);\n\tContainer.set(RedisService, redisInstance);\n\n\t// Setup secret\n\tconst secretInstance = new SecretManagerService(configurationInstance, redisInstance);\n\tContainer.set(SecretManagerService, secretInstance);\n\n\t// Setup BullMQ\n\tconst bullMQInstance = new BullMQService(redisInstance);\n\tContainer.set(BullMQService, bullMQInstance);\n\n\tconst mongoUrl = options?.mongoDbUrl\n\t\t? options.mongoDbUrl\n\t\t: await getLibraries().getSecretsService().getKey('MONGO_URL');\n\n\tawait initLyxaMongoDbConnection(mongoUrl!, options);\n\tawait initGlobalConnection(mongoUrl!, options!.environment);\n\n\tconst loggerInstance = new LyxaLogger(options!.instanceType!, mongoUrl!);\n\tContainer.set(LyxaLogger, loggerInstance);\n\n\tconst loggerKit = new LyxaLoggerKit({ instanceType: options!.instanceType! });\n\tContainer.set(LyxaLoggerKit, loggerKit);\n\n\t// Setup firebase\n\tconst firebaseInstance = new FirebaseService(configurationInstance!);\n\tContainer.set(FirebaseService, firebaseInstance);\n\n\t// Setup microservice dispatcher\n\tconst microserviceDispatcherInstance = new MicroServiceDispatcher(secretInstance);\n\tContainer.set(MicroServiceDispatcher, microserviceDispatcherInstance);\n\n\t// Setup twilio\n\tconst twilioServiceInstance = new TwilioService();\n\tContainer.set(TwilioService, twilioServiceInstance);\n\n\t// Setup map service\n\tconst googleMapsKey = await getLibraries().getSecretsService().getKey('GOOGLE_MAPS_API_KEY');\n\tconst googleMapService = new GoogleMapsService(redisInstance, googleMapsKey as string);\n\tconst osrmMapService = new OsrmMapService();\n\tconst mapServiceInstance = new MapService(googleMapService, osrmMapService);\n\tContainer.set(MapService, mapServiceInstance);\n\n\t// Setup cash settlement service\n\tconst bobUsername = await getLibraries().getSecretsService().getKey('BOB_USER_NAME');\n\tconst bobPassword = await getLibraries().getSecretsService().getKey('BOB_PASSWORD');\n\tconst bobURL = await getLibraries().getSecretsService().getKey('BOB_URL');\n\n\tconst bobService = new BOBService({\n\t\tBOB_USER_NAME: bobUsername,\n\t\tBOB_PASSWORD: bobPassword,\n\t\tBOB_URL: bobURL,\n\t} as BOBSecrets);\n\tconst cashSettlementServiceInstance = new CashSettlementService(bobService);\n\tContainer.set(CashSettlementService, cashSettlementServiceInstance);\n\tContainer.set(BOBService, bobService);\n\n\tconst settingsServiceInstance = new CachedSettingsService(redisInstance);\n\tContainer.set(CachedSettingsService, settingsServiceInstance);\n\n\ttry {\n\t\tconst settings = await settingsServiceInstance.getSettings();\n\t\tconst { _setTimezone } = await import('./utilities/dayjs/dayjs');\n\t\t_setTimezone(settings?.timezone || 'Asia/Beirut');\n\t\tconsole.log('Timezone initialized:', settings?.timezone || 'Asia/Beirut');\n\t} catch (error) {\n\t\tconsole.error('Failed to initialize timezone:', error);\n\t}\n\n\t// Setup fcm service\n\tconst firebaseService = getLibraries().getFirebaseService();\n\tconst fcmServiceInstance = new FCMService(firebaseService.superApp);\n\tconst fcmServiceInstanceForUser = new FCMService(firebaseService.userApp);\n\tconst fcmServiceInstanceForRider = new FCMService(firebaseService.riderApp);\n\tconst fcmServiceInstanceForShop = new FCMService(firebaseService.shopApp);\n\tconst fcmServiceInstanceForCpanel = new FCMService(firebaseService.cpanelApp);\n\tContainer.set(FCMService, fcmServiceInstance);\n\tContainer.set(FCMServiceForUser, fcmServiceInstanceForUser);\n\tContainer.set(FCMServiceForRider, fcmServiceInstanceForRider);\n\tContainer.set(FCMServiceForShop, fcmServiceInstanceForShop);\n\tContainer.set(FCMServiceForCpanel, fcmServiceInstanceForCpanel);\n\n\tconsole.log('Initialized everything');\n\n\tawait initEventBus(RabbitMQUrlMap[options?.environment ?? EnvironmentConfigurationType.DEV]);\n\n\tconst allSubscriptions = SubscriptionRegistry.getAllSubscriptions();\n\n\tconst instantiatedServices = new Map<Function, any>();\n\n\tfor (const { eventId, targetConstructor, methodName, opts } of allSubscriptions) {\n\t\tlet instance = instantiatedServices.get(targetConstructor);\n\t\tif (!instance) {\n\t\t\tinstance = Container.get(targetConstructor as any);\n\t\t\tinstantiatedServices.set(targetConstructor, instance);\n\t\t}\n\n\t\tawait subscribeToEvent(\n\t\t\teventId,\n\t\t\tasync payload => {\n\t\t\t\treturn instance[methodName](payload);\n\t\t\t},\n\t\t\topts\n\t\t);\n\t}\n}\n\nexport function getLibraries(): LibraryManager {\n\treturn Container.get(LibraryManager);\n}\n"]}
|
|
@@ -30,5 +30,8 @@ export declare class BOBService implements ICashSettlementService {
|
|
|
30
30
|
hasPendingRiderSettlements(riderId: mongoose.Types.ObjectId): Promise<boolean>;
|
|
31
31
|
getLastSettlement(reference: string): Promise<ISettlementInfo | null>;
|
|
32
32
|
getLastRiderSettlement(rider: mongoose.Types.ObjectId): Promise<ISettlementInfo | null>;
|
|
33
|
+
private getTransfers;
|
|
33
34
|
private decompressResponse;
|
|
35
|
+
private hasUnpaidTransfer;
|
|
36
|
+
checkAllPendingTransfers(): Promise<void>;
|
|
34
37
|
}
|
|
@@ -23,6 +23,7 @@ const enum_1 = require("../../../utilities/enum");
|
|
|
23
23
|
const __1 = require("../../..");
|
|
24
24
|
const error_common_1 = require("../../../utilities/error-common");
|
|
25
25
|
const currency_1 = require("../../../utilities/shared/currency");
|
|
26
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
26
27
|
var BOBTransferStatus;
|
|
27
28
|
(function (BOBTransferStatus) {
|
|
28
29
|
BOBTransferStatus["NOT_PAID"] = "NOT PAID";
|
|
@@ -108,7 +109,6 @@ let BOBService = class BOBService {
|
|
|
108
109
|
bobModel: enum_1.BobModel.C2B,
|
|
109
110
|
bobType: enum_1.BobType.INWARD,
|
|
110
111
|
});
|
|
111
|
-
await this.createBullMQJobForStatusCheck(crmNumber);
|
|
112
112
|
return true;
|
|
113
113
|
}
|
|
114
114
|
async createBullMQJobForStatusCheck(crmNumber) {
|
|
@@ -130,38 +130,14 @@ let BOBService = class BOBService {
|
|
|
130
130
|
console.log(`Removed job scheduler: ${schedulerId}`);
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
|
-
const
|
|
134
|
-
ChannelType: enum_1.BobChannelType.CO,
|
|
135
|
-
Credentials: {
|
|
136
|
-
User: this.BOB_USER_NAME,
|
|
137
|
-
Password: this.BOB_PASSWORD,
|
|
138
|
-
},
|
|
139
|
-
Model: enum_1.BobModel.C2B,
|
|
140
|
-
CRMNumber: job.data.crmNumber,
|
|
141
|
-
};
|
|
142
|
-
const { data } = await axios_1.default.post(`${this.BOB_URL}GetTransferStatus`, bobData, {
|
|
143
|
-
httpsAgent: new https_1.default.Agent({ rejectUnauthorized: false }),
|
|
144
|
-
});
|
|
145
|
-
if (data.ErrorCode != 100) {
|
|
146
|
-
console.error(`Error in BOB getTransferStatus: ${data.ErrorDescription}`);
|
|
147
|
-
throw new server_1.TRPCError({
|
|
148
|
-
code: 'INTERNAL_SERVER_ERROR',
|
|
149
|
-
message: 'Failed to post data to BOB API.',
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
const responseObject = await this.decompressResponse(data.Response);
|
|
153
|
-
if (!responseObject) {
|
|
154
|
-
console.error('Failed to get settlement status in BOB');
|
|
155
|
-
throw new server_1.TRPCError({
|
|
156
|
-
code: 'INTERNAL_SERVER_ERROR',
|
|
157
|
-
message: 'Failed to get settlement status in BOB.',
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
const hasUnpaidTransfer = responseObject.some((item) => item.CRMNumber == crmNumber && item.Status == BOBTransferStatus.NOT_PAID);
|
|
133
|
+
const hasUnpaidTransfer = await this.hasUnpaidTransfer(job.data.crmNumber);
|
|
161
134
|
if (!hasUnpaidTransfer) {
|
|
162
135
|
this.settlePayment(settlement);
|
|
163
136
|
}
|
|
164
|
-
console.log(`🔥 [${new Date().toISOString()}]
|
|
137
|
+
console.log(`🔥 [${new Date().toISOString()}] Checking settlement status for ${job.data.crmNumber}:`, {
|
|
138
|
+
settlement,
|
|
139
|
+
hasUnpaidTransfer,
|
|
140
|
+
});
|
|
165
141
|
});
|
|
166
142
|
worker.on('completed', (job) => {
|
|
167
143
|
console.log(`✅ Job completed: ${job.id}`);
|
|
@@ -363,6 +339,39 @@ let BOBService = class BOBService {
|
|
|
363
339
|
updatedAt: lastSettlement.updatedAt ?? new Date(),
|
|
364
340
|
};
|
|
365
341
|
}
|
|
342
|
+
async getTransfers(timeframe) {
|
|
343
|
+
const DateTimeFrom = new Date(timeframe.startDate).toISOString().split('.')[0] + 'Z';
|
|
344
|
+
const DateTimeTo = new Date(timeframe.endDate).toISOString().split('.')[0] + 'Z';
|
|
345
|
+
const bobData = {
|
|
346
|
+
ChannelType: enum_1.BobChannelType.CO,
|
|
347
|
+
Credentials: {
|
|
348
|
+
User: this.BOB_USER_NAME,
|
|
349
|
+
Password: this.BOB_PASSWORD,
|
|
350
|
+
},
|
|
351
|
+
Model: enum_1.BobModel.C2B,
|
|
352
|
+
DateTimeFrom,
|
|
353
|
+
DateTimeTo,
|
|
354
|
+
};
|
|
355
|
+
const { data } = await axios_1.default.post(`${this.BOB_URL}GetTransfers`, bobData, {
|
|
356
|
+
httpsAgent: new https_1.default.Agent({ rejectUnauthorized: false }),
|
|
357
|
+
});
|
|
358
|
+
if (data.ErrorCode != 100) {
|
|
359
|
+
console.error(`Error in BOB getTransfers: ${data.ErrorDescription}`);
|
|
360
|
+
throw new server_1.TRPCError({
|
|
361
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
362
|
+
message: 'Failed to post data to BOB API.',
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const responseObject = await this.decompressResponse(data.Response);
|
|
366
|
+
if (!responseObject) {
|
|
367
|
+
console.error('Failed to get transfers in BOB');
|
|
368
|
+
throw new server_1.TRPCError({
|
|
369
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
370
|
+
message: 'Failed to get transfers in BOB.',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return responseObject;
|
|
374
|
+
}
|
|
366
375
|
async decompressResponse(response) {
|
|
367
376
|
return new Promise((resolve, reject) => {
|
|
368
377
|
const decodedBuffer = Buffer.from(response, 'base64');
|
|
@@ -382,6 +391,79 @@ let BOBService = class BOBService {
|
|
|
382
391
|
});
|
|
383
392
|
});
|
|
384
393
|
}
|
|
394
|
+
async hasUnpaidTransfer(crmNumber) {
|
|
395
|
+
const bobData = {
|
|
396
|
+
ChannelType: enum_1.BobChannelType.CO,
|
|
397
|
+
Credentials: {
|
|
398
|
+
User: this.BOB_USER_NAME,
|
|
399
|
+
Password: this.BOB_PASSWORD,
|
|
400
|
+
},
|
|
401
|
+
Model: enum_1.BobModel.C2B,
|
|
402
|
+
CRMNumber: crmNumber,
|
|
403
|
+
};
|
|
404
|
+
const { data } = await axios_1.default.post(`${this.BOB_URL}GetTransferStatus`, bobData, {
|
|
405
|
+
httpsAgent: new https_1.default.Agent({ rejectUnauthorized: false }),
|
|
406
|
+
});
|
|
407
|
+
if (data.ErrorCode != 100) {
|
|
408
|
+
console.error(`Error in BOB getTransferStatus: ${data.ErrorDescription}`);
|
|
409
|
+
throw new server_1.TRPCError({
|
|
410
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
411
|
+
message: 'Failed to post data to BOB API.',
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
const responseObject = await this.decompressResponse(data.Response);
|
|
415
|
+
if (!responseObject) {
|
|
416
|
+
console.error('Failed to get settlement status in BOB');
|
|
417
|
+
throw new server_1.TRPCError({
|
|
418
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
419
|
+
message: 'Failed to get settlement status in BOB.',
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
const hasUnpaidTransfer = responseObject.some((item) => item.CRMNumber == crmNumber && item.Status == BOBTransferStatus.NOT_PAID);
|
|
423
|
+
return hasUnpaidTransfer;
|
|
424
|
+
}
|
|
425
|
+
async checkAllPendingTransfers() {
|
|
426
|
+
console.log(`🔥 [${new Date().toISOString()}] Checking pending BOB transfers`);
|
|
427
|
+
const notPaidSettlements = await this.model.find({
|
|
428
|
+
status: enum_1.BobSettlementStatus.NOT_PAID,
|
|
429
|
+
});
|
|
430
|
+
if (!notPaidSettlements.length) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
let maxDate = (0, dayjs_1.default)();
|
|
434
|
+
let minDate = (0, dayjs_1.default)();
|
|
435
|
+
const createdAtDates = notPaidSettlements.map(item => (0, dayjs_1.default)(item.createdAt));
|
|
436
|
+
if (createdAtDates.length > 0) {
|
|
437
|
+
maxDate = dayjs_1.default.max(...createdAtDates);
|
|
438
|
+
minDate = dayjs_1.default.min(...createdAtDates);
|
|
439
|
+
}
|
|
440
|
+
const maxDatePlusOneDay = maxDate.add(1, 'day').toDate();
|
|
441
|
+
const minDateMinusOneDay = minDate.add(1, 'day').toDate();
|
|
442
|
+
const transfers = await this.getTransfers({
|
|
443
|
+
startDate: minDateMinusOneDay,
|
|
444
|
+
endDate: maxDatePlusOneDay,
|
|
445
|
+
});
|
|
446
|
+
if (!transfers || transfers.length === 0) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const transferStatusMap = new Map();
|
|
450
|
+
for (const trx of transfers) {
|
|
451
|
+
transferStatusMap.set(trx.ReferenceNumber, trx.Status);
|
|
452
|
+
}
|
|
453
|
+
await Promise.all(notPaidSettlements.map(async (settlement) => {
|
|
454
|
+
try {
|
|
455
|
+
const status = transferStatusMap.get(settlement.crmNumber);
|
|
456
|
+
const isStillUnpaid = status === BOBTransferStatus.NOT_PAID;
|
|
457
|
+
if (!isStillUnpaid) {
|
|
458
|
+
await this.settlePayment(settlement);
|
|
459
|
+
}
|
|
460
|
+
console.log(`🔥 Settlement ${settlement.crmNumber}`, { status });
|
|
461
|
+
}
|
|
462
|
+
catch (err) {
|
|
463
|
+
console.error(`❌ Failed settlement ${settlement.crmNumber}`, err);
|
|
464
|
+
}
|
|
465
|
+
}));
|
|
466
|
+
}
|
|
385
467
|
};
|
|
386
468
|
exports.BOBService = BOBService;
|
|
387
469
|
exports.BOBService = BOBService = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bob.js","sourceRoot":"/","sources":["libraries/cash-settlement/providers/bob.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,kDAA0B;AAG1B,+CAU4B;AAC5B,mCAAiC;AACjC,kDAA0B;AAC1B,gDAAwB;AACxB,yCAAyC;AACzC,kDASiC;AAEjC,gCAAwC;AACxC,kEAAiF;AACjF,iEAA+F;AAQ/F,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC5B,0CAAqB,CAAA;IACrB,kCAAa,CAAA;AACd,CAAC,EAHW,iBAAiB,iCAAjB,iBAAiB,QAG5B;AAGM,IAAM,UAAU,GAAhB,MAAM,UAAU;IACd,KAAK,CAAuD;IAC5D,UAAU,CAA6C;IACvD,sBAAsB,CAAqE;IAE3F,aAAa,CAAS;IACtB,YAAY,CAAS;IACrB,OAAO,CAAS;IAExB,YAAY,OAAmB;QAC9B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAE/B,IAAI,CAAC,KAAK,GAAG,wBAAuE,CAAC;QACrF,IAAI,CAAC,UAAU,GAAG,mBAAwD,CAAC;QAC3E,IAAI,CAAC,sBAAsB,GAAG,+BACK,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,uBAAuB;QACpC,OAAO,MAAM,qBAAY,CAAC,gBAAgB,CACzC,EAAE,WAAW,EAAE,kBAAW,CAAC,UAAU,EAAE,EACvC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EACtB,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAC3B,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,GAAW;QAEtC,MAAM,OAAO,GAAG,4BAA4B,CAAC;QAC7C,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;QAErC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,GAAG,aAAa,CAAC;QACvE,MAAM,eAAe,GAAG,GAAG,GAAG,aAAa,CAAC;QAE5C,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC;QACzB,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAChG,CAAC;IAcM,KAAK,CAAC,kBAAkB,CAC9B,MAAc,EACd,QAAgB,EAChB,SAAiB,EACjB,SAAiB,EACjB,QAAgB,EAChB,OAAgC,EAChC,QAAiB;QAGjB,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;YACvB,IAAA,8BAAe,EAAC,+CAA+C,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,mDAAmD;aAC5D,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG;YACf,WAAW,EAAE,qBAAc,CAAC,EAAE;YAC9B,WAAW,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,aAAa;gBACxB,QAAQ,EAAE,IAAI,CAAC,YAAY;aAC3B;YACD,KAAK,EAAE,eAAQ,CAAC,GAAG;YACnB,SAAS,EAAE,SAAS;YACpB,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;YACtB,QAAQ,EAAE,QAAQ;SAClB,CAAC;QAEF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,oBAAoB,EAAE,OAAO,EAAE;YAC/E,UAAU,EAAE,IAAI,eAAK,CAAC,KAAK,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;SAC1D,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,oCAAoC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;YAC3E,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,iCAAiC;aAC1C,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpE,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtD,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,uCAAuC;aAChD,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YAC7C,MAAM,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvC,eAAe,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;YAChD,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,QAAQ;YACrB,MAAM,EAAE,0BAAmB,CAAC,QAAQ;YACpC,cAAc,EAAE,wBAAiB,CAAC,WAAW;YAC7C,QAAQ,EAAE,eAAQ,CAAC,GAAG;YACtB,OAAO,EAAE,cAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,6BAA6B,CAAC,SAAS,CAAC,CAAC;QAEpD,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,6BAA6B,CAAC,SAAiB;QAC5D,MAAM,MAAM,GAAG,IAAA,gBAAY,GAAE,CAAC,gBAAgB,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,yCAAyC,SAAS,EAAE,CAAC;QACrE,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,uCAAuC,SAAS,EAAE,CAAC;QACnE,MAAM,WAAW,GAAG,6CAA6C,SAAS,EAAE,CAAC;QAE7E,MAAM,KAAK,CAAC,kBAAkB,CAC7B,WAAW,EACX,EAAE,OAAO,EAAE,WAAW,EAAE,EACxB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,CACtC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,GAAQ,EAAE,EAAE;YAC9D,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,kBAAkB,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAEnF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;gBAC3C,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS;gBAC7B,MAAM,EAAE,0BAAmB,CAAC,QAAQ;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,8BAA8B,GAAG,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,CAAC;gBAC3E,MAAM,KAAK,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;gBACrD,OAAO;YACR,CAAC;YAED,MAAM,OAAO,GAAG;gBACf,WAAW,EAAE,qBAAc,CAAC,EAAE;gBAC9B,WAAW,EAAE;oBACZ,IAAI,EAAE,IAAI,CAAC,aAAa;oBACxB,QAAQ,EAAE,IAAI,CAAC,YAAY;iBAC3B;gBACD,KAAK,EAAE,eAAQ,CAAC,GAAG;gBACnB,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS;aAC7B,CAAC;YACF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,mBAAmB,EAAE,OAAO,EAAE;gBAC9E,UAAU,EAAE,IAAI,eAAK,CAAC,KAAK,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;aAC1D,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,mCAAmC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;gBAC1E,MAAM,IAAI,kBAAS,CAAC;oBACnB,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,iCAAiC;iBAC1C,CAAC,CAAC;YACJ,CAAC;YAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEpE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBACxD,MAAM,IAAI,kBAAS,CAAC;oBACnB,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,yCAAyC;iBAClD,CAAC,CAAC;YACJ,CAAC;YAED,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,CAC5C,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,iBAAiB,CAAC,QAAQ,CACvF,CAAC;YAEF,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACxB,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YAChC,CAAC;YAED,OAAO,CAAC,GAAG,CACV,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,2BAA2B,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,EAC/E,cAAc,CACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,GAAQ,EAAE,EAAE;YACnC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAQ,EAAE,GAAQ,EAAE,EAAE;YAC1C,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACJ,CAAC;IAQM,KAAK,CAAC,oBAAoB,CAAC,YAAqC;QACtE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAE3D,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5C,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,uBAAuB;aAChC,CAAC,CAAC;QACJ,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,0BAAmB,CAAC,IAAI,EAAE,CAAC;YACpD,OAAO,CAAC,KAAK,CAAC,sBAAsB,YAAY,6BAA6B,CAAC,CAAC;YAC/E,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,uCAAuC;aAChD,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAErC,IAAI,UAAU,CAAC,MAAM,KAAK,0BAAmB,CAAC,QAAQ,EAAE,CAAC;YACxD,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,UAAoC;QAC/D,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CACjC,UAAU,CAAC,GAAG,EACd,EAAE,MAAM,EAAE,0BAAmB,CAAC,IAAI,EAAE,EACpC,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAClC,CAAC;QAEF,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC;YACxC,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,eAAe,EAAE,UAAU,CAAC,eAAe;YAC3C,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,cAAc,EAAE,qBAAc,CAAC,iBAAiB;YAChD,WAAW,EAAE,kBAAW,CAAC,KAAK;SAC9B,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,iBAAiB,UAAU,CAAC,KAAK,aAAa,CAAC,CAAC;YAC9D,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,kBAAkB;aAC3B,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAY,CAAC,MAAM,IAAA,gBAAY,GAAE,CAAC,wBAAwB,EAAE,CAAC,WAAW,EAAE,CAAY,CAAC;QACrG,MAAM,YAAY,GAAG,QAAQ,EAAE,eAAe,EAAE,YAAY,IAAI,CAAC,CAAC;QAElE,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC;QAC/C,MAAM,wBAAwB,GAAG,UAAU,CAAC,eAAe,IAAI,CAAC,CAAC;QAEjE,IAAI,eAAe,GAAG,eAAe,CAAC;QACtC,IAAI,iBAAiB,GAAG,wBAAwB,CAAC;QAEjD,IAAI,gBAAgB,GAAG,KAAK,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC,CAAC;QACrD,IAAI,kBAAkB,GAAG,KAAK,CAAC,UAAU,EAAE,eAAe,IAAI,CAAC,CAAC;QAGhE,IAAI,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;QAClE,eAAe,IAAI,eAAe,CAAC;QACnC,gBAAgB,IAAI,eAAe,CAAC;QAGpC,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,eAAe,GAAG,IAAA,iCAAsB,EAAC,eAAe,GAAG,YAAY,CAAC,CAAC;YAE/E,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;YAExE,iBAAiB,IAAI,iBAAiB,CAAC;YACvC,kBAAkB,IAAI,iBAAiB,CAAC;YAExC,eAAe,GAAG,CAAC,CAAC;QACrB,CAAC;QAGD,IAAI,uBAAuB,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;QACrF,iBAAiB,GAAG,uBAAuB,CAAC;QAC5C,kBAAkB,IAAI,uBAAuB,CAAC;QAE9C,MAAM,kBAAkB,GAAG,wBAAwB,GAAG,uBAAuB,CAAC;QAG9E,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,aAAa,GAAG,IAAA,4BAAiB,EAAC,kBAAkB,GAAG,YAAY,CAAC,CAAC;YAE3E,MAAM,uBAAuB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;YAE1E,eAAe,IAAI,uBAAuB,CAAC;YAC3C,gBAAgB,IAAI,uBAAuB,CAAC;QAC7C,CAAC;QAED,MAAM,YAAY,GAAG,CAAC,eAAe,CAAC;QACtC,MAAM,cAAc,GAAG,CAAC,iBAAiB,CAAC;QAE1C,MAAM,IAAI,CAAC,UAAU,CAAC,iBAAiB,CACtC,KAAK,CAAC,GAAG,EACT;YACC,IAAI,EAAE;gBACL,4BAA4B,EAAE,cAAc;gBAC5C,mBAAmB,EAAE,YAAY;aACjC;SACD,EACD,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAClC,CAAC;IACH,CAAC;IAQM,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QAC9C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;YAC3C,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,0BAAmB,CAAC,QAAQ;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,6BAA6B,SAAS,aAAa,CAAC,CAAC;YACnE,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,uBAAuB;aAChC,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAErC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAC/C;YACC,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,0BAAmB,CAAC,QAAQ;SACpC,EACD;YACC,MAAM,EAAE,0BAAmB,CAAC,OAAO;SACnC,EACD,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAClC,CAAC;QAEF,OAAO,IAAI,CAAC;IACb,CAAC;IAQM,KAAK,CAAC,sBAAsB,CAAC,KAA8B;QACjE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACzC,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,0BAAmB,CAAC,QAAQ;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YACzB,IAAA,4BAAa,EAAC,8BAA8B,CAAC,CAAC;QAC/C,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACtC,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,UAAU,CAAC,GAAG,EAAE;gBAClD,MAAM,EAAE,0BAAmB,CAAC,OAAO;aACnC,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,SAAiB;QAC7C,MAAM,OAAO,GAAG;YACf,WAAW,EAAE,qBAAc,CAAC,EAAE;YAC9B,WAAW,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,aAAa;gBACxB,QAAQ,EAAE,IAAI,CAAC,YAAY;aAC3B;YACD,KAAK,EAAE,eAAQ,CAAC,GAAG;YACnB,SAAS,EAAE,SAAS;SACpB,CAAC;QAEF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,gBAAgB,EAAE,OAAO,EAAE;YAC3E,UAAU,EAAE,IAAI,eAAK,CAAC,KAAK,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;SAC1D,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YAE3B,OAAO;QACR,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACvE,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,iCAAiC;aAC1C,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEpE,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,mCAAmC;aAC5C,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAQM,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QACnD,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAChD,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,0BAAmB,CAAC,QAAQ;SACpC,CAAC,CAAC;QACH,OAAO,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,CAAC;IAQM,KAAK,CAAC,0BAA0B,CAAC,OAAgC;QACvE,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAChD,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,0BAAmB,CAAC,QAAQ;SACpC,CAAC,CAAC;QACH,OAAO,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,CAAC;IAQM,KAAK,CAAC,iBAAiB,CAAC,SAAiB;QAC/C,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,KAAK;aACzC,OAAO,CAAC;YACR,SAAS,EAAE,SAAS;SACpB,CAAC;aACD,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAE1B,IAAI,CAAC,kBAAkB;YAAE,OAAO,IAAI,CAAC;QAErC,OAAO;YACN,MAAM,EAAE,kBAAkB,CAAC,MAAM,IAAI,kBAAkB,CAAC,eAAe,IAAI,CAAC;YAC5E,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;YACnD,eAAe,EAAE,kBAAkB,CAAC,SAAS;YAC7C,MAAM,EAAE,CAAC,kBAAkB,CAAC,MAAM,IAAI,0BAAmB,CAAC,QAAQ,CAAiC;YACnG,SAAS,EAAE,kBAAkB,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;YACrD,SAAS,EAAE,kBAAkB,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;SACrD,CAAC;IACH,CAAC;IAQM,KAAK,CAAC,sBAAsB,CAAC,KAA8B;QACjE,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK;aACrC,OAAO,CAAC;YACR,KAAK,EAAE,KAAK;SACZ,CAAC;aACD,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAE1B,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAC;QAEjC,OAAO;YACN,MAAM,EAAE,cAAc,CAAC,MAAM,IAAI,cAAc,CAAC,eAAe,IAAI,CAAC;YACpE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;YAC/C,eAAe,EAAE,cAAc,CAAC,SAAS;YACzC,MAAM,EAAE,CAAC,cAAc,CAAC,MAAM,IAAI,0BAAmB,CAAC,QAAQ,CAAiC;YAC/F,SAAS,EAAE,cAAc,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;YACjD,SAAS,EAAE,cAAc,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;SACjD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAChD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAEtC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAGtD,cAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,kBAAkB,EAAE,EAAE;gBACtD,IAAI,GAAG,EAAE,CAAC;oBACT,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;oBAChD,MAAM,IAAI,kBAAS,CAAC;wBACnB,IAAI,EAAE,uBAAuB;wBAC7B,OAAO,EAAE,yCAAyC;qBAClD,CAAC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBAEP,MAAM,aAAa,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAG3D,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;oBAEjD,OAAO,CAAC,cAAc,CAAC,CAAC;gBACzB,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;CACD,CAAA;AArhBY,gCAAU;qBAAV,UAAU;IADtB,IAAA,gBAAO,GAAE;;GACG,UAAU,CAqhBtB","sourcesContent":["import axios from 'axios';\nimport { ICashSettlementService, ISettlementInfo, ISettlementStatus } from '../interfaces/ICashSettlement';\nimport { SoftDeleteModel } from '../../mongo/plugins/soft-delete-plugin';\nimport {\n\tBOBFinance,\n\tBOBFinanceModel,\n\tCounter,\n\tCounterModel,\n\tFinanceSettlement,\n\tFinanceSettlementModel,\n\tRider,\n\tRiderModel,\n\tSetting,\n} from '../../mongo/models';\nimport { Service } from 'typedi';\nimport https from 'https';\nimport zlib from 'zlib';\nimport { TRPCError } from '@trpc/server';\nimport {\n\tAccountType,\n\tBobChannelType,\n\tBobModel,\n\tBobSettlementStatus,\n\tBobSettlementType,\n\tBobType,\n\tCounterType,\n\tSettlementType,\n} from '../../../utilities/enum';\nimport { DocumentType, mongoose } from '@typegoose/typegoose';\nimport { getLibraries } from '../../..';\nimport { badRequestError, notFoundError } from '../../../utilities/error-common';\nimport { roundBaseCurrency, roundSecondaryCurrency } from '../../../utilities/shared/currency';\n\nexport type BOBSecrets = {\n\tBOB_USER_NAME: string;\n\tBOB_PASSWORD: string;\n\tBOB_URL: string;\n};\n\nexport enum BOBTransferStatus {\n\tNOT_PAID = 'NOT PAID',\n\tPAID = 'PAID',\n}\n\n@Service()\nexport class BOBService implements ICashSettlementService {\n\tprivate model: typeof BOBFinanceModel & SoftDeleteModel<BOBFinance>;\n\tprivate riderModel: typeof RiderModel & SoftDeleteModel<Rider>;\n\tprivate financeSettlementModel: typeof FinanceSettlementModel & SoftDeleteModel<FinanceSettlement>;\n\n\tprivate BOB_USER_NAME: string;\n\tprivate BOB_PASSWORD: string;\n\tprivate BOB_URL: string;\n\n\tconstructor(secrets: BOBSecrets) {\n\t\tthis.BOB_USER_NAME = secrets.BOB_USER_NAME;\n\t\tthis.BOB_PASSWORD = secrets.BOB_PASSWORD;\n\t\tthis.BOB_URL = secrets.BOB_URL;\n\n\t\tthis.model = BOBFinanceModel as typeof BOBFinanceModel & SoftDeleteModel<BOBFinance>;\n\t\tthis.riderModel = RiderModel as typeof RiderModel & SoftDeleteModel<Rider>;\n\t\tthis.financeSettlementModel = FinanceSettlementModel as typeof FinanceSettlementModel &\n\t\t\tSoftDeleteModel<FinanceSettlement>;\n\t}\n\n\tprivate async autoIncrementCRMCounter(): Promise<DocumentType<Counter>> {\n\t\treturn await CounterModel.findOneAndUpdate(\n\t\t\t{ counterType: CounterType.CRM_NUMBER },\n\t\t\t{ $inc: { value: 1 } },\n\t\t\t{ new: true, upsert: true }\n\t\t);\n\t}\n\n\tprivate convertNumberToCode(num: number): string {\n\t\t// convert a number to a code (e.g. 0 -> aa00)\n\t\tconst letters = 'abcdefghijklmnopqrstuvwxyz';\n\t\tconst lettersLength = letters.length;\n\n\t\tconst firstCharIndex = Math.floor(num / lettersLength) % lettersLength;\n\t\tconst secondCharIndex = num % lettersLength;\n\n\t\tconst digits = num % 100; // Ensures two digits (00 to 99)\n\t\treturn digits.toString().padStart(2, '0') + letters[firstCharIndex] + letters[secondCharIndex];\n\t}\n\n\t/**\n\t * Initiates a cash settlement process\n\t *\n\t * @param amount - The amount to be settled\n\t * @param currency - The currency of the amount\n\t * @param reference - A unique reference for the settlement\n\t * @param firstName - The first name of the settler\n\t * @param lastName - The last name of the settler\n\t * @param riderId - The ID of the rider associated with the settlement\n\t * @param location - Optional location of the settler\n\t * @returns Confirmation of the settlement initiation\n\t */\n\tpublic async initiateSettlement(\n\t\tamount: number,\n\t\tcurrency: string,\n\t\treference: string,\n\t\tfirstName: string,\n\t\tlastName: string,\n\t\triderId: mongoose.Types.ObjectId,\n\t\tlocation?: string\n\t): Promise<boolean> {\n\t\t// BOB cannot handle amount > 20000000\n\t\tif (amount > 20000000) {\n\t\t\tbadRequestError('Please provide a value between 0 and 20000000');\n\t\t}\n\n\t\tconst crmCounter = await this.autoIncrementCRMCounter();\n\t\tconst crmNumber = this.convertNumberToCode(crmCounter.value);\n\t\tif (!crmNumber) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to generate CRM number for BOB settlement.',\n\t\t\t});\n\t\t}\n\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tFirstName: firstName,\n\t\t\tLastName: lastName,\n\t\t\tCRMNumber: crmNumber,\n\t\t\tAmount: String(amount),\n\t\t\tCurrency: currency,\n\t\t};\n\n\t\tconst { data } = await axios.post(`${this.BOB_URL}InsertTransferData`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB initiateSettlement: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject || !responseObject.isSuccess) {\n\t\t\tconsole.error('Failed to initiate settlement in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to initiate settlement in BOB.',\n\t\t\t});\n\t\t}\n\n\t\tconst bobSettlement = await this.model.create({\n\t\t\tamount: currency === 'USD' ? amount : 0,\n\t\t\tsecondaryAmount: currency === 'USD' ? 0 : amount,\n\t\t\tcrmNumber: crmNumber,\n\t\t\trider: riderId,\n\t\t\tbobLocation: location,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\tsettlementType: BobSettlementType.SETTLE_CASH,\n\t\t\tbobModel: BobModel.C2B,\n\t\t\tbobType: BobType.INWARD,\n\t\t});\n\n\t\tawait this.createBullMQJobForStatusCheck(crmNumber);\n\n\t\treturn true;\n\t}\n\n\tprivate async createBullMQJobForStatusCheck(crmNumber: string) {\n\t\tconst bullmq = getLibraries().getBullMQService();\n\t\tconst queueId = `bob-settlement-status-check-queue-crm-${crmNumber}`;\n\t\tconst queue = bullmq.createQueue(queueId);\n\t\tconst jobName = `bob-settlement-status-check-job-crm-${crmNumber}`;\n\t\tconst schedulerId = `bob-settlement-status-check-scheduler-crm-${crmNumber}`;\n\n\t\tawait queue.upsertJobScheduler(\n\t\t\tschedulerId,\n\t\t\t{ pattern: '* * * * *' },\n\t\t\t{ name: jobName, data: { crmNumber } }\n\t\t);\n\n\t\tconst worker = bullmq.createWorker(queueId, async (job: any) => {\n\t\t\tconsole.log(`🔥 [${new Date().toISOString()}] Job triggered:`, job.name, job.data);\n\n\t\t\tconst settlement = await this.model.findOne({\n\t\t\t\tcrmNumber: job.data.crmNumber,\n\t\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\t});\n\n\t\t\tif (!settlement) {\n\t\t\t\tconsole.log(`Settlement with CRM number ${job.data.crmNumber} not found.`);\n\t\t\t\tawait queue.removeJobScheduler(schedulerId);\n\t\t\t\tconsole.log(`Removed job scheduler: ${schedulerId}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bobData = {\n\t\t\t\tChannelType: BobChannelType.CO,\n\t\t\t\tCredentials: {\n\t\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t\t},\n\t\t\t\tModel: BobModel.C2B,\n\t\t\t\tCRMNumber: job.data.crmNumber,\n\t\t\t};\n\t\t\tconst { data } = await axios.post(`${this.BOB_URL}GetTransferStatus`, bobData, {\n\t\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t\t});\n\n\t\t\tif (data.ErrorCode != 100) {\n\t\t\t\tconsole.error(`Error in BOB getTransferStatus: ${data.ErrorDescription}`);\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\t\tif (!responseObject) {\n\t\t\t\tconsole.error('Failed to get settlement status in BOB');\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t\tmessage: 'Failed to get settlement status in BOB.',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst hasUnpaidTransfer = responseObject.some(\n\t\t\t\t(item: any) => item.CRMNumber == crmNumber && item.Status == BOBTransferStatus.NOT_PAID\n\t\t\t);\n\n\t\t\tif (!hasUnpaidTransfer) {\n\t\t\t\tthis.settlePayment(settlement);\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`🔥 [${new Date().toISOString()}] Settlement status for ${job.data.crmNumber}:`,\n\t\t\t\tresponseObject\n\t\t\t);\n\t\t});\n\n\t\tworker.on('completed', (job: any) => {\n\t\t\tconsole.log(`✅ Job completed: ${job.id}`);\n\t\t});\n\n\t\tworker.on('failed', (job: any, err: any) => {\n\t\t\tconsole.error(`❌ Job failed: ${job?.id} -`, err);\n\t\t});\n\t}\n\n\t/**\n\t * Mark a settlement as paid\n\t *\n\t * @param settlementId - The ID of the settlement to update\n\t * @returns Confirmation of the update\n\t */\n\tpublic async markSettlementAsPaid(settlementId: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst settlement = await this.model.findById(settlementId);\n\n\t\tif (!settlement) {\n\t\t\tconsole.error(`Settlement with not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Settlement not found.',\n\t\t\t});\n\t\t}\n\n\t\tif (settlement.status === BobSettlementStatus.PAID) {\n\t\t\tconsole.error(`Settlement with ID ${settlementId} is already marked as paid.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\tmessage: 'Settlement is already marked as paid.',\n\t\t\t});\n\t\t}\n\n\t\tawait this.settlePayment(settlement);\n\n\t\tif (settlement.status === BobSettlementStatus.NOT_PAID) {\n\t\t\tawait this.removeTransfer(settlement.crmNumber); // Remove the transfer from BOB so future settlements with the same reference do not fail\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate async settlePayment(settlement: DocumentType<BOBFinance>) {\n\t\tawait this.model.findByIdAndUpdate(\n\t\t\tsettlement._id,\n\t\t\t{ status: BobSettlementStatus.PAID },\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\tawait this.financeSettlementModel.create({\n\t\t\tamount: settlement.amount,\n\t\t\tsecondaryAmount: settlement.secondaryAmount,\n\t\t\trider: settlement.rider,\n\t\t\tsettlementType: SettlementType.RIDER_SETTLE_CASH,\n\t\t\taccountType: AccountType.RIDER,\n\t\t});\n\n\t\tconst rider = await this.riderModel.findById(settlement.rider);\n\t\tif (!rider) {\n\t\t\tconsole.error(`Rider with ID ${settlement.rider} not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Rider not found.',\n\t\t\t});\n\t\t}\n\n\t\tconst settings: Setting = (await getLibraries().getCachedSettingsService().getSettings()) as Setting;\n\t\tconst exchangeRate = settings?.currencySetting?.exchangeRate || 1;\n\n\t\tconst totalSettlement = settlement.amount || 0;\n\t\tconst totalSecondarySettlement = settlement.secondaryAmount || 0;\n\n\t\tlet primaryToDeduct = totalSettlement;\n\t\tlet secondaryToDeduct = totalSecondarySettlement;\n\n\t\tlet availablePrimary = rider.cashInHand?.amount || 0;\n\t\tlet availableSecondary = rider.cashInHand?.secondaryAmount || 0;\n\n\t\t// 1. Handle primary settlement\n\t\tlet deductedPrimary = Math.min(availablePrimary, primaryToDeduct);\n\t\tprimaryToDeduct -= deductedPrimary;\n\t\tavailablePrimary -= deductedPrimary;\n\n\t\t// fallback to secondary if needed\n\t\tif (primaryToDeduct > 0) {\n\t\t\tconst neededSecondary = roundSecondaryCurrency(primaryToDeduct * exchangeRate);\n\n\t\t\tconst deductedSecondary = Math.min(availableSecondary, neededSecondary);\n\n\t\t\tsecondaryToDeduct += deductedSecondary; // accumulate deduction\n\t\t\tavailableSecondary -= deductedSecondary;\n\n\t\t\tprimaryToDeduct = 0;\n\t\t}\n\n\t\t// 2. Handle secondary settlement\n\t\tlet deductedSecondaryDirect = Math.min(availableSecondary, totalSecondarySettlement);\n\t\tsecondaryToDeduct = deductedSecondaryDirect;\n\t\tavailableSecondary -= deductedSecondaryDirect;\n\n\t\tconst remainingSecondary = totalSecondarySettlement - deductedSecondaryDirect;\n\n\t\t// fallback to primary\n\t\tif (remainingSecondary > 0) {\n\t\t\tconst neededPrimary = roundBaseCurrency(remainingSecondary / exchangeRate);\n\n\t\t\tconst deductedPrimaryFallback = Math.min(availablePrimary, neededPrimary);\n\n\t\t\tdeductedPrimary += deductedPrimaryFallback;\n\t\t\tavailablePrimary -= deductedPrimaryFallback;\n\t\t}\n\n\t\tconst deltaPrimary = -deductedPrimary;\n\t\tconst deltaSecondary = -secondaryToDeduct;\n\n\t\tawait this.riderModel.findByIdAndUpdate(\n\t\t\trider._id,\n\t\t\t{\n\t\t\t\t$inc: {\n\t\t\t\t\t'cashInHand.secondaryAmount': deltaSecondary,\n\t\t\t\t\t'cashInHand.amount': deltaPrimary,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\t}\n\n\t/**\n\t * Revokes a cash settlement\n\t *\n\t * @param reference - The reference ID of the settlement to revoke\n\t * @returns Confirmation of the revocation\n\t */\n\tpublic async revokeSettlement(reference: string): Promise<boolean> {\n\t\tconst settlement = await this.model.findOne({\n\t\t\tcrmNumber: reference,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\n\t\tif (!settlement) {\n\t\t\tconsole.error(`Settlement with reference ${reference} not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Settlement not found.',\n\t\t\t});\n\t\t}\n\n\t\tawait this.removeTransfer(reference);\n\n\t\tconst result = await this.model.findOneAndUpdate(\n\t\t\t{\n\t\t\t\tcrmNumber: reference,\n\t\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\t},\n\t\t\t{\n\t\t\t\tstatus: BobSettlementStatus.REVOKED,\n\t\t\t},\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Revokes a cash settlement\n\t *\n\t * @param reference - The reference ID of the settlement to revoke\n\t * @returns Confirmation of the revocation\n\t */\n\tpublic async revokeRiderSettlements(rider: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst settlements = await this.model.find({\n\t\t\trider: rider,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\n\t\tif (!settlements.length) {\n\t\t\tnotFoundError('No unpaid settlements found.');\n\t\t}\n\n\t\tfor (const settlement of settlements) {\n\t\t\tawait this.removeTransfer(settlement.crmNumber);\n\t\t\tawait this.model.findByIdAndUpdate(settlement._id, {\n\t\t\t\tstatus: BobSettlementStatus.REVOKED,\n\t\t\t});\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate async removeTransfer(crmNumber: string) {\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tCRMNumber: crmNumber,\n\t\t};\n\n\t\tconst { data } = await axios.post(`${this.BOB_URL}RemoveTransfer`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode == 213) {\n\t\t\t// Record does not exist\n\t\t\treturn;\n\t\t}\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB removeTransfer: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject || !responseObject.isSuccess) {\n\t\t\tconsole.error('Failed to remove transfer in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to remove transfer in BOB.',\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Check if there are pending settlements\n\t *\n\t * @param reference - The reference ID of the settlement to check\n\t * @returns true if there are pending settlements, false otherwise\n\t */\n\tpublic async hasPendingSettlements(reference: string): Promise<boolean> {\n\t\tconst pendingSettlements = await this.model.find({\n\t\t\tcrmNumber: reference,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\t\treturn pendingSettlements.length > 0;\n\t}\n\n\t/**\n\t * Check if there are pending settlements\n\t *\n\t * @param riderId - The ID of the rider to check\n\t * @returns true if there are pending settlements, false otherwise\n\t */\n\tpublic async hasPendingRiderSettlements(riderId: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst pendingSettlements = await this.model.find({\n\t\t\trider: riderId,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\t\treturn pendingSettlements.length > 0;\n\t}\n\n\t/**\n\t * Get latest settlement info\n\t *\n\t * @param reference - The reference ID of the settlement to check\n\t * @returns the latest settlement if it exists, null otherwise\n\t */\n\tpublic async getLastSettlement(reference: string): Promise<ISettlementInfo | null> {\n\t\tconst pendingSettlements = await this.model\n\t\t\t.findOne({\n\t\t\t\tcrmNumber: reference,\n\t\t\t})\n\t\t\t.sort({ createdAt: -1 });\n\n\t\tif (!pendingSettlements) return null;\n\n\t\treturn {\n\t\t\tamount: pendingSettlements.amount || pendingSettlements.secondaryAmount || 0,\n\t\t\tcurrency: pendingSettlements.amount ? 'USD' : 'LBP',\n\t\t\treferenceNumber: pendingSettlements.crmNumber,\n\t\t\tstatus: (pendingSettlements.status ?? BobSettlementStatus.NOT_PAID) as unknown as ISettlementStatus,\n\t\t\tcreatedAt: pendingSettlements.createdAt ?? new Date(),\n\t\t\tupdatedAt: pendingSettlements.createdAt ?? new Date(),\n\t\t};\n\t}\n\n\t/**\n\t * Get latest settlement info\n\t *\n\t * @param riderId - The ID of the rider to check\n\t * @returns the latest settlement if it exists, null otherwise\n\t */\n\tpublic async getLastRiderSettlement(rider: mongoose.Types.ObjectId): Promise<ISettlementInfo | null> {\n\t\tconst lastSettlement = await this.model\n\t\t\t.findOne({\n\t\t\t\trider: rider,\n\t\t\t})\n\t\t\t.sort({ createdAt: -1 });\n\n\t\tif (!lastSettlement) return null;\n\n\t\treturn {\n\t\t\tamount: lastSettlement.amount || lastSettlement.secondaryAmount || 0,\n\t\t\tcurrency: lastSettlement.amount ? 'USD' : 'LBP',\n\t\t\treferenceNumber: lastSettlement.crmNumber,\n\t\t\tstatus: (lastSettlement.status ?? BobSettlementStatus.NOT_PAID) as unknown as ISettlementStatus,\n\t\t\tcreatedAt: lastSettlement.createdAt ?? new Date(),\n\t\t\tupdatedAt: lastSettlement.updatedAt ?? new Date(),\n\t\t};\n\t}\n\n\tprivate async decompressResponse(response: string): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Step 1: Decode Base64\n\t\t\tconst decodedBuffer = Buffer.from(response, 'base64');\n\n\t\t\t// Step 2: Decompress GZIP\n\t\t\tzlib.gunzip(decodedBuffer, (err, decompressedBuffer) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tconsole.error('Error decompressing GZIP:', err);\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t\t\tmessage: 'Failed to decompress data from BOB API.',\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Step 3: Convert decompressed buffer to string\n\t\t\t\t\tconst decodedString = decompressedBuffer.toString('utf-8');\n\n\t\t\t\t\t// Step 4: Parse the JSON string to a JavaScript object\n\t\t\t\t\tconst responseObject = JSON.parse(decodedString);\n\n\t\t\t\t\tresolve(responseObject);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bob.js","sourceRoot":"/","sources":["libraries/cash-settlement/providers/bob.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport { ICashSettlementService, ISettlementInfo, ISettlementStatus } from '../interfaces/ICashSettlement';\nimport { SoftDeleteModel } from '../../mongo/plugins/soft-delete-plugin';\nimport {\n\tBOBFinance,\n\tBOBFinanceModel,\n\tCounter,\n\tCounterModel,\n\tFinanceSettlement,\n\tFinanceSettlementModel,\n\tRider,\n\tRiderModel,\n\tSetting,\n} from '../../mongo/models';\nimport { Service } from 'typedi';\nimport https from 'https';\nimport zlib from 'zlib';\nimport { TRPCError } from '@trpc/server';\nimport {\n\tAccountType,\n\tBobChannelType,\n\tBobModel,\n\tBobSettlementStatus,\n\tBobSettlementType,\n\tBobType,\n\tCounterType,\n\tSettlementType,\n} from '../../../utilities/enum';\nimport { DocumentType, mongoose } from '@typegoose/typegoose';\nimport { getLibraries } from '../../..';\nimport { badRequestError, notFoundError } from '../../../utilities/error-common';\nimport { roundBaseCurrency, roundSecondaryCurrency } from '../../../utilities/shared/currency';\nimport dayjs from 'dayjs';\n\nexport type BOBSecrets = {\n\tBOB_USER_NAME: string;\n\tBOB_PASSWORD: string;\n\tBOB_URL: string;\n};\n\nexport enum BOBTransferStatus {\n\tNOT_PAID = 'NOT PAID',\n\tPAID = 'PAID',\n}\n\n@Service()\nexport class BOBService implements ICashSettlementService {\n\tprivate model: typeof BOBFinanceModel & SoftDeleteModel<BOBFinance>;\n\tprivate riderModel: typeof RiderModel & SoftDeleteModel<Rider>;\n\tprivate financeSettlementModel: typeof FinanceSettlementModel & SoftDeleteModel<FinanceSettlement>;\n\n\tprivate BOB_USER_NAME: string;\n\tprivate BOB_PASSWORD: string;\n\tprivate BOB_URL: string;\n\n\tconstructor(secrets: BOBSecrets) {\n\t\tthis.BOB_USER_NAME = secrets.BOB_USER_NAME;\n\t\tthis.BOB_PASSWORD = secrets.BOB_PASSWORD;\n\t\tthis.BOB_URL = secrets.BOB_URL;\n\n\t\tthis.model = BOBFinanceModel as typeof BOBFinanceModel & SoftDeleteModel<BOBFinance>;\n\t\tthis.riderModel = RiderModel as typeof RiderModel & SoftDeleteModel<Rider>;\n\t\tthis.financeSettlementModel = FinanceSettlementModel as typeof FinanceSettlementModel &\n\t\t\tSoftDeleteModel<FinanceSettlement>;\n\t}\n\n\tprivate async autoIncrementCRMCounter(): Promise<DocumentType<Counter>> {\n\t\treturn await CounterModel.findOneAndUpdate(\n\t\t\t{ counterType: CounterType.CRM_NUMBER },\n\t\t\t{ $inc: { value: 1 } },\n\t\t\t{ new: true, upsert: true }\n\t\t);\n\t}\n\n\tprivate convertNumberToCode(num: number): string {\n\t\t// convert a number to a code (e.g. 0 -> aa00)\n\t\tconst letters = 'abcdefghijklmnopqrstuvwxyz';\n\t\tconst lettersLength = letters.length;\n\n\t\tconst firstCharIndex = Math.floor(num / lettersLength) % lettersLength;\n\t\tconst secondCharIndex = num % lettersLength;\n\n\t\tconst digits = num % 100; // Ensures two digits (00 to 99)\n\t\treturn digits.toString().padStart(2, '0') + letters[firstCharIndex] + letters[secondCharIndex];\n\t}\n\n\t/**\n\t * Initiates a cash settlement process\n\t *\n\t * @param amount - The amount to be settled\n\t * @param currency - The currency of the amount\n\t * @param reference - A unique reference for the settlement\n\t * @param firstName - The first name of the settler\n\t * @param lastName - The last name of the settler\n\t * @param riderId - The ID of the rider associated with the settlement\n\t * @param location - Optional location of the settler\n\t * @returns Confirmation of the settlement initiation\n\t */\n\tpublic async initiateSettlement(\n\t\tamount: number,\n\t\tcurrency: string,\n\t\treference: string,\n\t\tfirstName: string,\n\t\tlastName: string,\n\t\triderId: mongoose.Types.ObjectId,\n\t\tlocation?: string\n\t): Promise<boolean> {\n\t\t// BOB cannot handle amount > 20000000\n\t\tif (amount > 20000000) {\n\t\t\tbadRequestError('Please provide a value between 0 and 20000000');\n\t\t}\n\n\t\tconst crmCounter = await this.autoIncrementCRMCounter();\n\t\tconst crmNumber = this.convertNumberToCode(crmCounter.value);\n\t\tif (!crmNumber) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to generate CRM number for BOB settlement.',\n\t\t\t});\n\t\t}\n\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tFirstName: firstName,\n\t\t\tLastName: lastName,\n\t\t\tCRMNumber: crmNumber,\n\t\t\tAmount: String(amount),\n\t\t\tCurrency: currency,\n\t\t};\n\n\t\tconst { data } = await axios.post(`${this.BOB_URL}InsertTransferData`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB initiateSettlement: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject || !responseObject.isSuccess) {\n\t\t\tconsole.error('Failed to initiate settlement in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to initiate settlement in BOB.',\n\t\t\t});\n\t\t}\n\n\t\tconst bobSettlement = await this.model.create({\n\t\t\tamount: currency === 'USD' ? amount : 0,\n\t\t\tsecondaryAmount: currency === 'USD' ? 0 : amount,\n\t\t\tcrmNumber: crmNumber,\n\t\t\trider: riderId,\n\t\t\tbobLocation: location,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\tsettlementType: BobSettlementType.SETTLE_CASH,\n\t\t\tbobModel: BobModel.C2B,\n\t\t\tbobType: BobType.INWARD,\n\t\t});\n\n\t\treturn true;\n\t}\n\n\tprivate async createBullMQJobForStatusCheck(crmNumber: string) {\n\t\tconst bullmq = getLibraries().getBullMQService();\n\t\tconst queueId = `bob-settlement-status-check-queue-crm-${crmNumber}`;\n\t\tconst queue = bullmq.createQueue(queueId);\n\t\tconst jobName = `bob-settlement-status-check-job-crm-${crmNumber}`;\n\t\tconst schedulerId = `bob-settlement-status-check-scheduler-crm-${crmNumber}`;\n\n\t\tawait queue.upsertJobScheduler(\n\t\t\tschedulerId,\n\t\t\t{ pattern: '* * * * *' },\n\t\t\t{ name: jobName, data: { crmNumber } }\n\t\t);\n\n\t\tconst worker = bullmq.createWorker(queueId, async (job: any) => {\n\t\t\tconsole.log(`🔥 [${new Date().toISOString()}] Job triggered:`, job.name, job.data);\n\n\t\t\tconst settlement = await this.model.findOne({\n\t\t\t\tcrmNumber: job.data.crmNumber,\n\t\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\t});\n\n\t\t\tif (!settlement) {\n\t\t\t\tconsole.log(`Settlement with CRM number ${job.data.crmNumber} not found.`);\n\t\t\t\tawait queue.removeJobScheduler(schedulerId);\n\t\t\t\tconsole.log(`Removed job scheduler: ${schedulerId}`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst hasUnpaidTransfer = await this.hasUnpaidTransfer(job.data.crmNumber);\n\n\t\t\tif (!hasUnpaidTransfer) {\n\t\t\t\tthis.settlePayment(settlement);\n\t\t\t}\n\n\t\t\tconsole.log(`🔥 [${new Date().toISOString()}] Checking settlement status for ${job.data.crmNumber}:`, {\n\t\t\t\tsettlement,\n\t\t\t\thasUnpaidTransfer,\n\t\t\t});\n\t\t});\n\n\t\tworker.on('completed', (job: any) => {\n\t\t\tconsole.log(`✅ Job completed: ${job.id}`);\n\t\t});\n\n\t\tworker.on('failed', (job: any, err: any) => {\n\t\t\tconsole.error(`❌ Job failed: ${job?.id} -`, err);\n\t\t});\n\t}\n\n\t/**\n\t * Mark a settlement as paid\n\t *\n\t * @param settlementId - The ID of the settlement to update\n\t * @returns Confirmation of the update\n\t */\n\tpublic async markSettlementAsPaid(settlementId: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst settlement = await this.model.findById(settlementId);\n\n\t\tif (!settlement) {\n\t\t\tconsole.error(`Settlement with not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Settlement not found.',\n\t\t\t});\n\t\t}\n\n\t\tif (settlement.status === BobSettlementStatus.PAID) {\n\t\t\tconsole.error(`Settlement with ID ${settlementId} is already marked as paid.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\tmessage: 'Settlement is already marked as paid.',\n\t\t\t});\n\t\t}\n\n\t\tawait this.settlePayment(settlement);\n\n\t\tif (settlement.status === BobSettlementStatus.NOT_PAID) {\n\t\t\tawait this.removeTransfer(settlement.crmNumber); // Remove the transfer from BOB so future settlements with the same reference do not fail\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate async settlePayment(settlement: DocumentType<BOBFinance>) {\n\t\tawait this.model.findByIdAndUpdate(\n\t\t\tsettlement._id,\n\t\t\t{ status: BobSettlementStatus.PAID },\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\tawait this.financeSettlementModel.create({\n\t\t\tamount: settlement.amount,\n\t\t\tsecondaryAmount: settlement.secondaryAmount,\n\t\t\trider: settlement.rider,\n\t\t\tsettlementType: SettlementType.RIDER_SETTLE_CASH,\n\t\t\taccountType: AccountType.RIDER,\n\t\t});\n\n\t\tconst rider = await this.riderModel.findById(settlement.rider);\n\t\tif (!rider) {\n\t\t\tconsole.error(`Rider with ID ${settlement.rider} not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Rider not found.',\n\t\t\t});\n\t\t}\n\n\t\tconst settings: Setting = (await getLibraries().getCachedSettingsService().getSettings()) as Setting;\n\t\tconst exchangeRate = settings?.currencySetting?.exchangeRate || 1;\n\n\t\tconst totalSettlement = settlement.amount || 0;\n\t\tconst totalSecondarySettlement = settlement.secondaryAmount || 0;\n\n\t\tlet primaryToDeduct = totalSettlement;\n\t\tlet secondaryToDeduct = totalSecondarySettlement;\n\n\t\tlet availablePrimary = rider.cashInHand?.amount || 0;\n\t\tlet availableSecondary = rider.cashInHand?.secondaryAmount || 0;\n\n\t\t// 1. Handle primary settlement\n\t\tlet deductedPrimary = Math.min(availablePrimary, primaryToDeduct);\n\t\tprimaryToDeduct -= deductedPrimary;\n\t\tavailablePrimary -= deductedPrimary;\n\n\t\t// fallback to secondary if needed\n\t\tif (primaryToDeduct > 0) {\n\t\t\tconst neededSecondary = roundSecondaryCurrency(primaryToDeduct * exchangeRate);\n\n\t\t\tconst deductedSecondary = Math.min(availableSecondary, neededSecondary);\n\n\t\t\tsecondaryToDeduct += deductedSecondary; // accumulate deduction\n\t\t\tavailableSecondary -= deductedSecondary;\n\n\t\t\tprimaryToDeduct = 0;\n\t\t}\n\n\t\t// 2. Handle secondary settlement\n\t\tlet deductedSecondaryDirect = Math.min(availableSecondary, totalSecondarySettlement);\n\t\tsecondaryToDeduct = deductedSecondaryDirect;\n\t\tavailableSecondary -= deductedSecondaryDirect;\n\n\t\tconst remainingSecondary = totalSecondarySettlement - deductedSecondaryDirect;\n\n\t\t// fallback to primary\n\t\tif (remainingSecondary > 0) {\n\t\t\tconst neededPrimary = roundBaseCurrency(remainingSecondary / exchangeRate);\n\n\t\t\tconst deductedPrimaryFallback = Math.min(availablePrimary, neededPrimary);\n\n\t\t\tdeductedPrimary += deductedPrimaryFallback;\n\t\t\tavailablePrimary -= deductedPrimaryFallback;\n\t\t}\n\n\t\tconst deltaPrimary = -deductedPrimary;\n\t\tconst deltaSecondary = -secondaryToDeduct;\n\n\t\tawait this.riderModel.findByIdAndUpdate(\n\t\t\trider._id,\n\t\t\t{\n\t\t\t\t$inc: {\n\t\t\t\t\t'cashInHand.secondaryAmount': deltaSecondary,\n\t\t\t\t\t'cashInHand.amount': deltaPrimary,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\t}\n\n\t/**\n\t * Revokes a cash settlement\n\t *\n\t * @param reference - The reference ID of the settlement to revoke\n\t * @returns Confirmation of the revocation\n\t */\n\tpublic async revokeSettlement(reference: string): Promise<boolean> {\n\t\tconst settlement = await this.model.findOne({\n\t\t\tcrmNumber: reference,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\n\t\tif (!settlement) {\n\t\t\tconsole.error(`Settlement with reference ${reference} not found.`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Settlement not found.',\n\t\t\t});\n\t\t}\n\n\t\tawait this.removeTransfer(reference);\n\n\t\tconst result = await this.model.findOneAndUpdate(\n\t\t\t{\n\t\t\t\tcrmNumber: reference,\n\t\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t\t},\n\t\t\t{\n\t\t\t\tstatus: BobSettlementStatus.REVOKED,\n\t\t\t},\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Revokes a cash settlement\n\t *\n\t * @param reference - The reference ID of the settlement to revoke\n\t * @returns Confirmation of the revocation\n\t */\n\tpublic async revokeRiderSettlements(rider: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst settlements = await this.model.find({\n\t\t\trider: rider,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\n\t\tif (!settlements.length) {\n\t\t\tnotFoundError('No unpaid settlements found.');\n\t\t}\n\n\t\tfor (const settlement of settlements) {\n\t\t\tawait this.removeTransfer(settlement.crmNumber);\n\t\t\tawait this.model.findByIdAndUpdate(settlement._id, {\n\t\t\t\tstatus: BobSettlementStatus.REVOKED,\n\t\t\t});\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate async removeTransfer(crmNumber: string) {\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tCRMNumber: crmNumber,\n\t\t};\n\n\t\tconst { data } = await axios.post(`${this.BOB_URL}RemoveTransfer`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode == 213) {\n\t\t\t// Record does not exist\n\t\t\treturn;\n\t\t}\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB removeTransfer: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject || !responseObject.isSuccess) {\n\t\t\tconsole.error('Failed to remove transfer in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to remove transfer in BOB.',\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Check if there are pending settlements\n\t *\n\t * @param reference - The reference ID of the settlement to check\n\t * @returns true if there are pending settlements, false otherwise\n\t */\n\tpublic async hasPendingSettlements(reference: string): Promise<boolean> {\n\t\tconst pendingSettlements = await this.model.find({\n\t\t\tcrmNumber: reference,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\t\treturn pendingSettlements.length > 0;\n\t}\n\n\t/**\n\t * Check if there are pending settlements\n\t *\n\t * @param riderId - The ID of the rider to check\n\t * @returns true if there are pending settlements, false otherwise\n\t */\n\tpublic async hasPendingRiderSettlements(riderId: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tconst pendingSettlements = await this.model.find({\n\t\t\trider: riderId,\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\t\treturn pendingSettlements.length > 0;\n\t}\n\n\t/**\n\t * Get latest settlement info\n\t *\n\t * @param reference - The reference ID of the settlement to check\n\t * @returns the latest settlement if it exists, null otherwise\n\t */\n\tpublic async getLastSettlement(reference: string): Promise<ISettlementInfo | null> {\n\t\tconst pendingSettlements = await this.model\n\t\t\t.findOne({\n\t\t\t\tcrmNumber: reference,\n\t\t\t})\n\t\t\t.sort({ createdAt: -1 });\n\n\t\tif (!pendingSettlements) return null;\n\n\t\treturn {\n\t\t\tamount: pendingSettlements.amount || pendingSettlements.secondaryAmount || 0,\n\t\t\tcurrency: pendingSettlements.amount ? 'USD' : 'LBP',\n\t\t\treferenceNumber: pendingSettlements.crmNumber,\n\t\t\tstatus: (pendingSettlements.status ?? BobSettlementStatus.NOT_PAID) as unknown as ISettlementStatus,\n\t\t\tcreatedAt: pendingSettlements.createdAt ?? new Date(),\n\t\t\tupdatedAt: pendingSettlements.createdAt ?? new Date(),\n\t\t};\n\t}\n\n\t/**\n\t * Get latest settlement info\n\t *\n\t * @param riderId - The ID of the rider to check\n\t * @returns the latest settlement if it exists, null otherwise\n\t */\n\tpublic async getLastRiderSettlement(rider: mongoose.Types.ObjectId): Promise<ISettlementInfo | null> {\n\t\tconst lastSettlement = await this.model\n\t\t\t.findOne({\n\t\t\t\trider: rider,\n\t\t\t})\n\t\t\t.sort({ createdAt: -1 });\n\n\t\tif (!lastSettlement) return null;\n\n\t\treturn {\n\t\t\tamount: lastSettlement.amount || lastSettlement.secondaryAmount || 0,\n\t\t\tcurrency: lastSettlement.amount ? 'USD' : 'LBP',\n\t\t\treferenceNumber: lastSettlement.crmNumber,\n\t\t\tstatus: (lastSettlement.status ?? BobSettlementStatus.NOT_PAID) as unknown as ISettlementStatus,\n\t\t\tcreatedAt: lastSettlement.createdAt ?? new Date(),\n\t\t\tupdatedAt: lastSettlement.updatedAt ?? new Date(),\n\t\t};\n\t}\n\n\tprivate async getTransfers(timeframe: { startDate: Date; endDate: Date }) {\n\t\tconst DateTimeFrom = new Date(timeframe.startDate).toISOString().split('.')[0] + 'Z';\n\t\tconst DateTimeTo = new Date(timeframe.endDate).toISOString().split('.')[0] + 'Z';\n\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tDateTimeFrom,\n\t\t\tDateTimeTo,\n\t\t};\n\t\tconst { data } = await axios.post(`${this.BOB_URL}GetTransfers`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB getTransfers: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject) {\n\t\t\tconsole.error('Failed to get transfers in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to get transfers in BOB.',\n\t\t\t});\n\t\t}\n\n\t\treturn responseObject;\n\t}\n\n\tprivate async decompressResponse(response: string): Promise<any> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Step 1: Decode Base64\n\t\t\tconst decodedBuffer = Buffer.from(response, 'base64');\n\n\t\t\t// Step 2: Decompress GZIP\n\t\t\tzlib.gunzip(decodedBuffer, (err, decompressedBuffer) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tconsole.error('Error decompressing GZIP:', err);\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\t\t\tmessage: 'Failed to decompress data from BOB API.',\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// Step 3: Convert decompressed buffer to string\n\t\t\t\t\tconst decodedString = decompressedBuffer.toString('utf-8');\n\n\t\t\t\t\t// Step 4: Parse the JSON string to a JavaScript object\n\t\t\t\t\tconst responseObject = JSON.parse(decodedString);\n\n\t\t\t\t\tresolve(responseObject);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async hasUnpaidTransfer(crmNumber: string): Promise<Boolean> {\n\t\tconst bobData = {\n\t\t\tChannelType: BobChannelType.CO,\n\t\t\tCredentials: {\n\t\t\t\tUser: this.BOB_USER_NAME,\n\t\t\t\tPassword: this.BOB_PASSWORD,\n\t\t\t},\n\t\t\tModel: BobModel.C2B,\n\t\t\tCRMNumber: crmNumber,\n\t\t};\n\t\tconst { data } = await axios.post(`${this.BOB_URL}GetTransferStatus`, bobData, {\n\t\t\thttpsAgent: new https.Agent({ rejectUnauthorized: false }),\n\t\t});\n\n\t\tif (data.ErrorCode != 100) {\n\t\t\tconsole.error(`Error in BOB getTransferStatus: ${data.ErrorDescription}`);\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to post data to BOB API.',\n\t\t\t});\n\t\t}\n\n\t\tconst responseObject = await this.decompressResponse(data.Response);\n\n\t\tif (!responseObject) {\n\t\t\tconsole.error('Failed to get settlement status in BOB');\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Failed to get settlement status in BOB.',\n\t\t\t});\n\t\t}\n\n\t\tconst hasUnpaidTransfer = responseObject.some(\n\t\t\t(item: any) => item.CRMNumber == crmNumber && item.Status == BOBTransferStatus.NOT_PAID\n\t\t);\n\n\t\treturn hasUnpaidTransfer;\n\t}\n\n\tpublic async checkAllPendingTransfers() {\n\t\tconsole.log(`🔥 [${new Date().toISOString()}] Checking pending BOB transfers`);\n\n\t\tconst notPaidSettlements = await this.model.find({\n\t\t\tstatus: BobSettlementStatus.NOT_PAID,\n\t\t});\n\n\t\tif (!notPaidSettlements.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet maxDate = dayjs();\n\t\tlet minDate = dayjs();\n\n\t\tconst createdAtDates = notPaidSettlements.map(item => dayjs(item.createdAt!));\n\n\t\tif (createdAtDates.length > 0) {\n\t\t\tmaxDate = dayjs.max(...createdAtDates)!;\n\t\t\tminDate = dayjs.min(...createdAtDates)!;\n\t\t}\n\n\t\tconst maxDatePlusOneDay = maxDate.add(1, 'day').toDate();\n\t\tconst minDateMinusOneDay = minDate.add(1, 'day').toDate();\n\n\t\tconst transfers = await this.getTransfers({\n\t\t\tstartDate: minDateMinusOneDay,\n\t\t\tendDate: maxDatePlusOneDay,\n\t\t});\n\n\t\tif (!transfers || transfers.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transferStatusMap = new Map<string, string>();\n\n\t\tfor (const trx of transfers) {\n\t\t\ttransferStatusMap.set(trx.ReferenceNumber, trx.Status);\n\t\t}\n\n\t\tawait Promise.all(\n\t\t\tnotPaidSettlements.map(async settlement => {\n\t\t\t\ttry {\n\t\t\t\t\tconst status = transferStatusMap.get(settlement.crmNumber);\n\n\t\t\t\t\tconst isStillUnpaid = status === BOBTransferStatus.NOT_PAID;\n\n\t\t\t\t\tif (!isStillUnpaid) {\n\t\t\t\t\t\tawait this.settlePayment(settlement);\n\t\t\t\t\t}\n\n\t\t\t\t\tconsole.log(`🔥 Settlement ${settlement.crmNumber}`, { status });\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`❌ Failed settlement ${settlement.crmNumber}`, err);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"]}
|
|
@@ -5,10 +5,10 @@ interface AuthOptions {
|
|
|
5
5
|
autoRefresh?: boolean;
|
|
6
6
|
}
|
|
7
7
|
export declare function createAuthenticatedProcedure(options: AuthOptions): import("@trpc/server").TRPCProcedureBuilder<import("../context").LyxaHTTPContext, object, {
|
|
8
|
+
req: import("http").IncomingMessage;
|
|
8
9
|
res: import("http").ServerResponse<import("http").IncomingMessage>;
|
|
9
10
|
tokenType: TokenType | undefined;
|
|
10
11
|
entity: import("../context").EntityContext | undefined;
|
|
11
|
-
req: import("http").IncomingMessage;
|
|
12
12
|
requestId: string | undefined;
|
|
13
13
|
usedRefreshToken: boolean | undefined;
|
|
14
14
|
tokenRenewed: boolean | undefined;
|
|
@@ -4,10 +4,10 @@ interface RoleProtectedOptions {
|
|
|
4
4
|
allowedRoles: string[];
|
|
5
5
|
}
|
|
6
6
|
export declare function createRoleProtectedProcedure(options: RoleProtectedOptions): import("@trpc/server").TRPCProcedureBuilder<import("../context").LyxaHTTPContext, object, {
|
|
7
|
+
req: import("http").IncomingMessage;
|
|
7
8
|
res: import("http").ServerResponse<import("http").IncomingMessage>;
|
|
8
9
|
tokenType: import("../../auth").TokenType | undefined;
|
|
9
10
|
entity: import("../context").EntityContext | undefined;
|
|
10
|
-
req: import("http").IncomingMessage;
|
|
11
11
|
requestId: string | undefined;
|
|
12
12
|
usedRefreshToken: boolean | undefined;
|
|
13
13
|
tokenRenewed: boolean | undefined;
|
|
@@ -3,10 +3,10 @@ interface PhoneVerifiedOptions {
|
|
|
3
3
|
entityTypes: AuthEntityType[];
|
|
4
4
|
}
|
|
5
5
|
export declare function createPhoneVerifiedProcedure(options: PhoneVerifiedOptions): import("@trpc/server").TRPCProcedureBuilder<import("../context").LyxaHTTPContext, object, {
|
|
6
|
+
req: import("http").IncomingMessage;
|
|
6
7
|
res: import("http").ServerResponse<import("http").IncomingMessage>;
|
|
7
8
|
tokenType: import("../../auth").TokenType | undefined;
|
|
8
9
|
entity: import("../context").EntityContext | undefined;
|
|
9
|
-
req: import("http").IncomingMessage;
|
|
10
10
|
requestId: string | undefined;
|
|
11
11
|
usedRefreshToken: boolean | undefined;
|
|
12
12
|
tokenRenewed: boolean | undefined;
|
|
@@ -5,10 +5,10 @@ interface AuthOptions {
|
|
|
5
5
|
autoRefresh?: boolean;
|
|
6
6
|
}
|
|
7
7
|
export declare function publicUserDecoder(options: AuthOptions): import("@trpc/server").TRPCProcedureBuilder<import("../context").LyxaHTTPContext, object, {
|
|
8
|
+
req: import("http").IncomingMessage;
|
|
8
9
|
res: import("http").ServerResponse<import("http").IncomingMessage>;
|
|
9
10
|
tokenType: TokenType | undefined;
|
|
10
11
|
entity: import("../context").EntityContext | undefined;
|
|
11
|
-
req: import("http").IncomingMessage;
|
|
12
12
|
requestId: string | undefined;
|
|
13
13
|
usedRefreshToken: boolean | undefined;
|
|
14
14
|
tokenRenewed: boolean | undefined;
|
package/dist/types/README.md
CHANGED
package/dist/types/package.json
CHANGED
|
@@ -26,8 +26,8 @@ export declare const FilterSchema: z.ZodOptional<z.ZodObject<{
|
|
|
26
26
|
searchFields?: string[] | undefined;
|
|
27
27
|
} | undefined;
|
|
28
28
|
sort?: Record<string, 1 | -1> | undefined;
|
|
29
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
30
29
|
populate?: any;
|
|
30
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
31
31
|
query?: Record<string, any> | undefined;
|
|
32
32
|
}, {
|
|
33
33
|
search?: {
|
|
@@ -36,8 +36,8 @@ export declare const FilterSchema: z.ZodOptional<z.ZodObject<{
|
|
|
36
36
|
} | undefined;
|
|
37
37
|
sort?: Record<string, 1 | -1> | undefined;
|
|
38
38
|
size?: number | undefined;
|
|
39
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
40
39
|
populate?: any;
|
|
40
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
41
41
|
query?: Record<string, any> | undefined;
|
|
42
42
|
page?: number | undefined;
|
|
43
43
|
}>>;
|
|
@@ -736,12 +736,12 @@ export declare const GetByIdInputSchema: z.ZodObject<{
|
|
|
736
736
|
populate: z.ZodOptional<z.ZodUnion<[z.ZodType<any, z.ZodTypeDef, any>, z.ZodArray<z.ZodType<any, z.ZodTypeDef, any>, "many">]>>;
|
|
737
737
|
}, "strip", z.ZodTypeAny, {
|
|
738
738
|
_id: import("mongoose").Types.ObjectId;
|
|
739
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
740
739
|
populate?: any;
|
|
740
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
741
741
|
}, {
|
|
742
742
|
_id: string | import("mongoose").Types.ObjectId;
|
|
743
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
744
743
|
populate?: any;
|
|
744
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
745
745
|
}>;
|
|
746
746
|
export type GetByIdInputDTO = DTO<typeof GetByIdInputSchema>;
|
|
747
747
|
export declare const GetProductByIdInputSchema: z.ZodObject<{
|
|
@@ -754,12 +754,12 @@ export declare const GetProductByIdInputSchema: z.ZodObject<{
|
|
|
754
754
|
_id: import("mongoose").Types.ObjectId;
|
|
755
755
|
withAttributeHiddenItems: boolean;
|
|
756
756
|
withAddonsHiddenItems: boolean;
|
|
757
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
758
757
|
populate?: any;
|
|
758
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
759
759
|
}, {
|
|
760
760
|
_id: string | import("mongoose").Types.ObjectId;
|
|
761
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
762
761
|
populate?: any;
|
|
762
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
763
763
|
withAttributeHiddenItems?: boolean | undefined;
|
|
764
764
|
withAddonsHiddenItems?: boolean | undefined;
|
|
765
765
|
}>;
|
|
@@ -772,14 +772,14 @@ export declare const GetOrderByIdInputSchema: z.ZodObject<{
|
|
|
772
772
|
userOrderCompletionScope: z.ZodOptional<z.ZodNativeEnum<typeof UserOrderCompletionScope>>;
|
|
773
773
|
}, "strip", z.ZodTypeAny, {
|
|
774
774
|
_id: import("mongoose").Types.ObjectId;
|
|
775
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
776
775
|
populate?: any;
|
|
776
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
777
777
|
groupByCategories?: boolean | undefined;
|
|
778
778
|
userOrderCompletionScope?: UserOrderCompletionScope | undefined;
|
|
779
779
|
}, {
|
|
780
780
|
_id: string | import("mongoose").Types.ObjectId;
|
|
781
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
782
781
|
populate?: any;
|
|
782
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
783
783
|
groupByCategories?: boolean | undefined;
|
|
784
784
|
userOrderCompletionScope?: UserOrderCompletionScope | undefined;
|
|
785
785
|
}>;
|
|
@@ -788,11 +788,11 @@ export declare const GetByTokenInputSchema: z.ZodOptional<z.ZodObject<{
|
|
|
788
788
|
select: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodLiteral<0>, z.ZodLiteral<1>]>>>;
|
|
789
789
|
populate: z.ZodOptional<z.ZodUnion<[z.ZodType<any, z.ZodTypeDef, any>, z.ZodArray<z.ZodType<any, z.ZodTypeDef, any>, "many">]>>;
|
|
790
790
|
}, "strip", z.ZodTypeAny, {
|
|
791
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
792
791
|
populate?: any;
|
|
793
|
-
}, {
|
|
794
792
|
select?: Record<string, 0 | 1> | undefined;
|
|
793
|
+
}, {
|
|
795
794
|
populate?: any;
|
|
795
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
796
796
|
}>>;
|
|
797
797
|
export type GetByTokenInputDTO = DTO<typeof GetByTokenInputSchema>;
|
|
798
798
|
export declare const GetOneQuerySchema: z.ZodObject<{
|
|
@@ -800,12 +800,12 @@ export declare const GetOneQuerySchema: z.ZodObject<{
|
|
|
800
800
|
select: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodLiteral<0>, z.ZodLiteral<1>]>>>;
|
|
801
801
|
populate: z.ZodOptional<z.ZodUnion<[z.ZodType<any, z.ZodTypeDef, any>, z.ZodArray<z.ZodType<any, z.ZodTypeDef, any>, "many">]>>;
|
|
802
802
|
}, "strip", z.ZodTypeAny, {
|
|
803
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
804
803
|
populate?: any;
|
|
804
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
805
805
|
query?: Record<string, any> | undefined;
|
|
806
806
|
}, {
|
|
807
|
-
select?: Record<string, 0 | 1> | undefined;
|
|
808
807
|
populate?: any;
|
|
808
|
+
select?: Record<string, 0 | 1> | undefined;
|
|
809
809
|
query?: Record<string, any> | undefined;
|
|
810
810
|
}>;
|
|
811
811
|
export type GetOneQueryDTO = DTO<typeof GetOneQuerySchema>;
|